import child_process from 'child_process' ; import fs from 'fs' ; import path from 'path' ; import shell from 'shelljs' ; import { Block , Resource , Data , Module , Output , Provider , Variable , Backend , Provisioner , ResourceToDataOptions , Locals } from './blocks' ; import { Util } from './Util' ; category export interface WriteOptions { /**
     * Directory to write to.
     *
     * Default = .
     */ dir ? : string ; /**
     * Terraform filename, must ends with .tf.
     *
     * Default = terraform.tf
     */ tfFilename ? : string ; /**
     * Terraform variables filename, must ends with .tfvars.
     *
     * Default = terraform.tfvars
     */ tfvarsFilename ? : string ; /**
     * Put `true` to use `terraform fmt` to format the configuration, Terraform must be installed.
     *
     * If the terraform binary is named differently in your machine, put the binary name instead.
     *
     * Default = false
     */ format ? : boolean | string ; } category export class TerraformGenerator { readonly #arguments ? : Record < string , any > ; readonly #blocks : Block [ ] = [ ] ; #variables : Record < string , any > = { } ; param args constructor ( args ? ) { this . #arguments = args ; } /**
     * Generate Terraform configuration as string.
     */ generate ( ) { return { tf : this . #generateTf ( ) , tfvars : Object . keys ( this . #variables ) . length > 0 ? this . #generateTfvars ( ) : undefined } ; } #generateTf ( ) { let str = '' ; if ( this . #arguments || this . #blocks . filter ( block => block instanceof Backend ) . length > 0 ) { str += 'terraform {\n' ; str += Util . argumentsToString ( this . #arguments ) ; this . #blocks . forEach ( block => { if ( block instanceof Backend ) { str += block . toTerraform ( ) ; } } ) ; str += '}\n\n' ; } this . #blocks . forEach ( block => { if ( ! ( block instanceof Backend ) ) { str += block . toTerraform ( ) ; } } ) ; return Util . unescape ( str ) ; } #generateTfvars ( ) { let str = '' ; Object . keys ( this . #variables ) . forEach ( key => { str += Util . argumentsToString ( { [ key ] : this . #variables [ key ] } ) ; str += '\n' ; } ) ; return str ; } param options write ( options ? ) { if ( ! options ) { options = { } ; } if ( ! options . dir ) { options . dir = '.' ; } if ( ! options . tfFilename ) { options . tfFilename = 'terraform.tf' ; } if ( ! options . tfFilename . endsWith ( '.tf' ) ) { options . tfFilename += '.tf' ; } if ( ! options . tfvarsFilename ) { options . tfvarsFilename = 'terraform.tfvars' ; } if ( ! options . tfvarsFilename . endsWith ( '.tfvars' ) ) { options . tfvarsFilename += '.tfvars' ; } if ( options . format === true ) { options . format = 'terraform' ; } const result = this . generate ( ) ; shell . mkdir ( '-p' , options . dir ) ; fs . writeFileSync ( path . join ( options . dir , options . tfFilename ) , result . tf ) ; if ( result . tfvars ) { fs . writeFileSync ( path . join ( options . dir , options . tfvarsFilename ) , result . tfvars ) ; } if ( options . format ) { child_process . execSync ( `${ options . format } fmt` , { cwd : options . dir } ) ; } } param blocks addBlocks ( ... blocks ) { blocks . forEach ( block => this . #blocks . push ( block ) ) ; return this ; } param type param args provider ( type , args ? ) { const block = new Provider ( type , args ) ; this . addBlocks ( block ) ; return block ; } param type param name param args param provisioners resource ( type , name , args ? , provisioners ? ) { const block = new Resource ( type , name , args , provisioners ) ; this . addBlocks ( block ) ; return block ; } param resource param options param argNames param args dataFromResource ( resource , options , argNames , args ? ) { const block = resource . toData ( options , argNames , args ) ; this . addBlocks ( block ) ; return block ; } param type param name param args data ( type , name , args ? ) { const block = new Data ( type , name , args ) ; this . addBlocks ( block ) ; return block ; } param name param args module ( name , args ? ) { const block = new Module ( name , args ) ; this . addBlocks ( block ) ; return block ; } param name param args output ( name , args ? ) { const block = new Output ( name , args ) ; this . addBlocks ( block ) ; return block ; } param args locals ( args ? ) { const block = new Locals ( args ) ; this . addBlocks ( block ) ; return block ; } param name param args param value variable ( name , args ? , value ? ) { const block = new Variable ( name , args ) ; this . addBlocks ( block ) ; if ( value != null ) { this . addVars ( { [ name ] : value } ) ; } return block ; } param type param args backend ( type , args ? ) { const block = new Backend ( type , args ) ; this . addBlocks ( block ) ; return block ; } param type param args provisioner ( type , args ? ) { const block = new Provisioner ( type , args ) ; this . addBlocks ( block ) ; return block ; } param variables addVars ( variables ) { this . #variables = { ... this . #variables , ... variables } ; return this ; } param tfgs merge ( ... tfgs ) { tfgs . forEach ( tfg => { this . addBlocks ( ... tfg . getBlocks ( ) ) ; this . addVars ( tfg . getVars ( ) ) ; } ) ; return this ; } /**
     * Get arguments.
     */ getArguments ( ) { return this . #arguments ; } /**
     * Get blocks.
     */ getBlocks ( ) { return this . #blocks ; } /**
     * Get variables.
     */ getVars ( ) { return this . #variables ; } }