Skip to content

Instantly share code, notes, and snippets.

@peter
Created December 17, 2020 11:30
Show Gist options
  • Save peter/8ae69d0236a8d276c1021cdea6417a53 to your computer and use it in GitHub Desktop.
Save peter/8ae69d0236a8d276c1021cdea6417a53 to your computer and use it in GitHub Desktop.
De-duplicating Terraform code by generating it from JavaScript
const fs = require('fs')
module.exports = {
writeTerraform,
generateMain,
}
// Templates are just terraform (.tf files) with the following kinds of interpolations:
// 1. Variables embedded in a string: "terraform-states-<id>"
// 2. Variables occupying an entire string: "<apiId>".
// If the value is a string then double quotes are preserved and for most other data types they are not (for say a number).
// If value is an object then quotes are preserved if quotes === true, example object value without quotes:
// { value: `aws_api_gateway_deployment.${api}.stage_name`, quotes: false }
// 2. As a comment on its own line for a block of code: #<lambdas>
function template (name, variables) {
const code = fs.readFileSync(`_terraform/templates/${name}.tf`).toString()
return code.replace(/#?"?<([a-z0-9]+)>"?/gi, (m, key) => {
const value = variables[key]
if (m.startsWith('"') && m.endsWith('"')) {
if (typeof value === 'string') {
return `"${value}"`
} else if (typeof value === 'object' && value.value) {
return value.quotes ? `"${value.value}"` : value.value
} else {
return value
}
} else if (m.startsWith('"') && !m.endsWith('"')) {
return `"${value}`
} else if (!m.startsWith('"') && m.endsWith('"')) {
return `${value}"`
} else {
return value
}
})
}
function writeTerraform (code, options = {}) {
if (Array.isArray(code)) code = code.join('\n')
const tfPath = (options.path || process.argv[1] || 'main.js').replace(/\.js$/, '.tf')
fs.writeFileSync(tfPath, code)
}
// Example Terraform generation from a main.tf template
function generateMain () {
const variables = {
api,
name,
body: { value: `data.template_file.openapi_${api}.rendered`, quotes: false },
restApiId: { value: `aws_api_gateway_rest_api.${api}.id`, quotes: false },
apiId: { value: `aws_api_gateway_rest_api.${api}.id`, quotes: false },
stageName: { value: `aws_api_gateway_deployment.${api}.stage_name`, quotes: false }
}
return template('main', variables)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment