Last active
September 29, 2021 10:14
-
-
Save dploeger/a98e0d2489c9affdc3d5379a5ec5e08b to your computer and use it in GitHub Desktop.
AWS to Azure Terraform script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const Handlebars = require("handlebars"); | |
const process = require('process') | |
const fs = require('fs') | |
const dns = require('dns').promises | |
const DEFAULT_TTL = 300 | |
const IGNORED_ZONE_TYPES = ['SOA', 'NS'] | |
const args = process.argv.slice(2) | |
if (args.length !== 3) { | |
console.log(` | |
Usage: | |
route53JsonToTerraform.js <zone name> <JSON zone file> <resourcegroup var name> | |
`) | |
process.exit(1) | |
} | |
let context = { | |
zone: args[0], | |
resourceGroupVar: args[2], | |
records: [] | |
} | |
const zoneFile = args[1] | |
const zones = JSON.parse(fs.readFileSync(zoneFile)) | |
Handlebars.registerHelper('literalArray', (value) => { | |
return JSON.stringify(value) | |
}) | |
Handlebars.registerHelper('isRecordType', (type, value) => { | |
return value === type | |
}) | |
Handlebars.registerHelper('resourceName', (value) => { | |
let rewrittenValue = '' | |
if (value) { | |
if (value === '@') { | |
value = context.zone | |
} | |
rewrittenValue = value.replace(new RegExp('\\.', 'g'), '_') | |
} | |
if (!rewrittenValue.match(/^[a-z_]/)) { | |
rewrittenValue=`_${rewrittenValue}` | |
} | |
return rewrittenValue | |
}) | |
async function generateRecords(context, zones) { | |
const records = [] | |
for (const zone of zones.ResourceRecordSets) { | |
const record = { | |
name: zone.Name.replace(`.${context.zone}`, '').replace(/\.$/, ''), | |
ttl: 'TTL' in zone ? zone.TTL : DEFAULT_TTL, | |
records: [] | |
} | |
if (record.name === context.zone) { | |
record.name = '@' | |
} | |
if (zone.Type === 'A') { | |
record.type = 'A' | |
if (record.name === context.zone) { | |
record.name = '@' | |
} | |
if ('AliasTarget' in zone) { | |
try { | |
const resolved = await dns.lookup(zone.AliasTarget.DNSName) | |
record.records = [resolved.address] | |
} catch (e) { | |
console.error(`Error resolving ${zone.AliasTarget.DNSName} for ${zone.Name}. Continuing: ${e}`) | |
continue | |
} | |
} else if ('ResourceRecords' in zone) { | |
record.records = zone.ResourceRecords.map(resourceRecord => resourceRecord.Value) | |
} | |
} else if (zone.Type === 'CNAME') { | |
record.type = 'CNAME' | |
record.records = zone.ResourceRecords.map(resourceRecord => resourceRecord.Value) | |
} else if (zone.Type === 'MX') { | |
record.type = 'MX' | |
record.records = zone.ResourceRecords.map(resourceRecord => { | |
let preference, exchange | |
[preference, exchange] = resourceRecord.Value.split(/ /) | |
return { | |
preference: preference, | |
exchange: exchange | |
} | |
}) | |
} else if (zone.Type === 'NS' && zone.Name !== `${context.zone}.` ) { | |
record.type = 'NS' | |
record.records = record.records = zone.ResourceRecords.map(resourceRecord => resourceRecord.Value) | |
} else if (zone.Type === 'TXT' || zone.Type === 'SPF') { | |
record.type = 'TXT' | |
record.records = zone.ResourceRecords.map(resourceRecord => resourceRecord.Value) | |
} else if (!zone.Type in IGNORED_ZONE_TYPES) { | |
console.error(`Zone type ${zone.Type} not implemented yet: ${JSON.stringify(zone)}`) | |
continue | |
} else { | |
console.error(`Ignoring zone record ${JSON.stringify(zone)}`) | |
continue | |
} | |
records.push(record) | |
} | |
return records | |
} | |
async function main(context, zones) { | |
context.records = await generateRecords(context, zones) | |
const template = Handlebars.compile(fs.readFileSync("azure.tf.handlebars", {encoding: 'UTF-8'})) | |
console.log(template(context)) | |
} | |
main(context, zones) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This converts JSON output from aws route53 list-record-sets to Terraform resources managing an Azure domain.
Currently supported record types: A, CNAME, MX and TXT (or SPF, which basically is the same)
Fetch all hosted zones using awscli: