├── .gitattributes ├── .eslintignore ├── .gitignore ├── generators └── app │ ├── templates │ ├── modules │ │ ├── output.tf │ │ ├── input.tf │ │ └── module.tf │ ├── environments │ │ └── components │ │ │ ├── output.tf │ │ │ ├── terraform.tfvars │ │ │ ├── input.tf │ │ │ └── component.tf │ ├── gitignore │ ├── backends.json │ └── providers.json │ └── index.js ├── .travis.yml ├── .yo-rc.json ├── .editorconfig ├── LICENSE ├── helpers └── backendsTestData.js ├── package.json ├── __tests__ └── app.js └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | coverage 2 | **/templates 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | -------------------------------------------------------------------------------- /generators/app/templates/modules/output.tf: -------------------------------------------------------------------------------- 1 | # Put output variables that are dependencies for other modules here -------------------------------------------------------------------------------- /generators/app/templates/environments/components/output.tf: -------------------------------------------------------------------------------- 1 | # Put output variables that are dependencies for other modules here -------------------------------------------------------------------------------- /generators/app/templates/gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - v11 4 | - v10 5 | - v8 6 | - v6 7 | after_script: cat ./coverage/lcov.info | coveralls 8 | -------------------------------------------------------------------------------- /generators/app/templates/backends.json: -------------------------------------------------------------------------------- 1 | { 2 | "s3": ["bucket", "key", "region"], 3 | "consul": ["address", "path", "access_token"], 4 | "atlas": ["name"] 5 | } -------------------------------------------------------------------------------- /generators/app/templates/environments/components/terraform.tfvars: -------------------------------------------------------------------------------- 1 | # Supply values for your environment-specific variables here 2 | environment_name = "<%= environment %>" 3 | component_name = "<%= component %>" -------------------------------------------------------------------------------- /generators/app/templates/providers.json: -------------------------------------------------------------------------------- 1 | { 2 | "aws": ["access_key", "secret_key", "region"], 3 | "azurerm": ["subscription_id", "client_id", "client_secret", "tenant_id"], 4 | "google": ["project", "region"] 5 | } -------------------------------------------------------------------------------- /.yo-rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "generator-node": { 3 | "promptValues": { 4 | "authorName": "William Tsoi", 5 | "authorEmail": "william@williamtsoi.net", 6 | "authorUrl": "https://about.me/williamtsoi" 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | 10 | [*.md] 11 | trim_trailing_whitespace = false 12 | -------------------------------------------------------------------------------- /generators/app/templates/modules/input.tf: -------------------------------------------------------------------------------- 1 | # variables declarations that are passed in to the component module go here 2 | # supply the actual values in terraform.tfvars within the environment folder 3 | variable "environment_name" { } 4 | variable "component_name" { } -------------------------------------------------------------------------------- /generators/app/templates/environments/components/input.tf: -------------------------------------------------------------------------------- 1 | # variables declarations that are passed in to the component module go here 2 | # supply the actual values in terraform.tfvars within the environment folder 3 | variable "environment_name" { } 4 | variable "component_name" { } -------------------------------------------------------------------------------- /generators/app/templates/modules/module.tf: -------------------------------------------------------------------------------- 1 | # Make reference other modules here. As a pattern you should not be creating resources directly here. 2 | # Either use a module from the Terraform module registry (https://registry.terraform.io/) or write one yourself 3 | 4 | resource "null_resource" "<%= component %>" { 5 | provisioner "local-exec" { 6 | command = "echo You are deploying the ${var.component_name} component into the ${var.environment_name} environment!" 7 | } 8 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 William Tsoi (https://about.me/williamtsoi) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /helpers/backendsTestData.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const path = require("path"); 4 | const helpers = require("yeoman-test"); 5 | 6 | exports.s3BackendTestData = () => { 7 | return helpers.run(path.join(__dirname, "../generators/app")).withPrompts({ 8 | environments: "1,2,3", 9 | components: "a,b,c", 10 | backend: "s3", 11 | provider: "aws", 12 | backendBucketName: "myBucket", 13 | backendBucketKeyPrefix: "terraform-remote-state", 14 | backendBucketRegion: "ap-southeast-2" 15 | }); 16 | }; 17 | 18 | exports.consulBackendTestData = () => { 19 | return helpers.run(path.join(__dirname, "../generators/app")).withPrompts({ 20 | environments: "1,2,3", 21 | components: "a,b,c", 22 | backend: "consul", 23 | provider: "aws", 24 | backendConsulAddress: "consul", 25 | backendConsulPathPrefix: "terraform-remote-state" 26 | }); 27 | }; 28 | 29 | exports.atlasBackendTestData = () => { 30 | return helpers.run(path.join(__dirname, "../generators/app")).withPrompts({ 31 | environments: "1,2,3", 32 | components: "a,b,c", 33 | backend: "atlas", 34 | provider: "aws", 35 | backendAtlasOrganisationName: "myOrg", 36 | backendAtlasWorkspacePrefix: "myApp" 37 | }); 38 | }; 39 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "generator-terraform-environments", 3 | "version": "0.6.0", 4 | "description": "Scaffolding used to create infrastructure environments using Terraform", 5 | "homepage": "https://github.com/williamtsoi1/generator-terraform-environments", 6 | "author": { 7 | "name": "William Tsoi", 8 | "email": "william@williamtsoi.net", 9 | "url": "https://about.me/williamtsoi" 10 | }, 11 | "files": [ 12 | "generators" 13 | ], 14 | "main": "generators/index.js", 15 | "keywords": [ 16 | "", 17 | "yeoman-generator" 18 | ], 19 | "devDependencies": { 20 | "yeoman-test": "^1.7.0", 21 | "yeoman-assert": "^3.1.0", 22 | "coveralls": "^3.0.2", 23 | "eslint": "^5.9.0", 24 | "prettier": "^1.15.2", 25 | "husky": "^1.2.0", 26 | "lint-staged": "^8.1.0", 27 | "eslint-config-prettier": "^3.3.0", 28 | "eslint-plugin-prettier": "^3.0.0", 29 | "eslint-config-xo": "^0.25.0", 30 | "jest": "^23.5.0" 31 | }, 32 | "engines": { 33 | "npm": ">= 4.0.0" 34 | }, 35 | "dependencies": { 36 | "yeoman-generator": "^2.0.1", 37 | "chalk": "^2.1.0", 38 | "yosay": "^2.0.1" 39 | }, 40 | "jest": { 41 | "testEnvironment": "node" 42 | }, 43 | "lint-staged": { 44 | "*.js": [ 45 | "eslint --fix", 46 | "git add" 47 | ], 48 | "*.json": [ 49 | "prettier --write", 50 | "git add" 51 | ] 52 | }, 53 | "eslintConfig": { 54 | "extends": [ 55 | "xo", 56 | "prettier" 57 | ], 58 | "env": { 59 | "jest": true, 60 | "node": true 61 | }, 62 | "rules": { 63 | "prettier/prettier": "error" 64 | }, 65 | "plugins": [ 66 | "prettier" 67 | ] 68 | }, 69 | "scripts": { 70 | "pretest": "eslint .", 71 | "test": "jest" 72 | }, 73 | "repository": "williamtsoi1/generator-terraform-environments", 74 | "license": "MIT" 75 | } 76 | -------------------------------------------------------------------------------- /generators/app/templates/environments/components/component.tf: -------------------------------------------------------------------------------- 1 | # Complete your provider information here 2 | # Full list of providers: https://www.terraform.io/docs/providers/index.html 3 | provider "<%= provider %>" { 4 | # provider parameters here. Override any secrets at run time and avoid storing them in source control<% for (i in providerAttributes) { %> 5 | <%= providerAttributes[i] %> = ""<% } %> 6 | } 7 | 8 | # Make a single call to the component module in the modules folder of this repo. 9 | # Do not create any resources nor reference other modules here. 10 | # That belongs in ../../../modules/<%= component %>/<%= component %>.tf 11 | module "<%= component %>" { 12 | source = "../../../modules/<%= component %>" 13 | # other variables to be passed in go here 14 | environment_name = "${var.environment_name}" 15 | component_name = "${var.component_name}" 16 | } 17 | 18 | <% if (backend == "s3") { %> 19 | terraform { 20 | backend "<%= backend %>" { 21 | bucket = "<%= backendBucketName %>" 22 | key = "<%= backendBucketKeyPrefix %>/<%= environment %>/<%= component %>/terraform.tfstate" 23 | region = "<%= backendBucketRegion %>" 24 | } 25 | } 26 | <% for (i in components) { %><% if (components[i] != component) { %> 27 | data "terraform_remote_state" "<%= components[i] %>" { 28 | backend = "<%= backend %>" 29 | config { 30 | bucket = "<%= backendBucketName %>" 31 | key = "<%= backendBucketKeyPrefix %>/<%= environment %>/<%= components[i] %>/terraform.tfstate" 32 | region = "<%= backendBucketRegion %>" 33 | } 34 | } 35 | <% } %><% } %><% } %> 36 | 37 | <% if (backend == "consul") { %> 38 | # The "access_token" parameter is left here for completeness, but should be set as the CONSUL_HTTP_TOKEN environment variable 39 | terraform { 40 | backend "<%= backend %>" { 41 | address = "<%= backendConsulAddress %>" 42 | path = "<%= backendConsulPathPrefix %>/<%= environment %>/<%= component %>" 43 | access_token = "" 44 | } 45 | } 46 | <% for (i in components) { %><% if (components[i] != component) { %> 47 | data "terraform_remote_state" "<%= components[i] %>" { 48 | backend = "<%= backend %>" 49 | config { 50 | address = "<%= backendConsulAddress %>" 51 | path = "<%= backendConsulPathPrefix %>/<%= environment %>/<%= components[i] %>" 52 | access_token = "" 53 | } 54 | } 55 | <% } %><% } %><% } %> 56 | 57 | <% if (backend == "atlas") { %> 58 | atlas { 59 | name = "<%=backendAtlasOrganisationName %>/<%= backendAtlasWorkspacePrefix %>-<%= environment %>-<%= component %>" 60 | } 61 | 62 | terraform { 63 | backend "<%= backend %>" { 64 | name = "<%=backendAtlasOrganisationName %>/<%= backendAtlasWorkspacePrefix %>-<%= environment %>-<%= component %>" 65 | } 66 | } 67 | <% for (i in components) { %><% if (components[i] != component) { %> 68 | data "terraform_remote_state" "<%= components[i] %>" { 69 | backend = "<%= backend %>" 70 | config { 71 | name = "<%=backendAtlasOrganisationName %>/<%= backendAtlasWorkspacePrefix %>-<%= environment %>-<%= components[i] %>" 72 | } 73 | } 74 | <% } %><% } %><% } %> -------------------------------------------------------------------------------- /__tests__/app.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const assert = require("yeoman-assert"); 3 | const backendsTestData = require("../helpers/backendsTestData"); 4 | 5 | describe("generator-terraform-environments:app", () => { 6 | describe("basic folder tests", () => { 7 | beforeAll(() => { 8 | return backendsTestData.s3BackendTestData(); 9 | }); 10 | 11 | it("creates per-environment folders", () => { 12 | assert.file(["environments"]); 13 | assert.file(["environments/1"]); 14 | assert.file(["environments/1/a"]); 15 | assert.file(["environments/1/b"]); 16 | assert.file(["environments/1/c"]); 17 | assert.file(["environments/2"]); 18 | assert.file(["environments/2/a"]); 19 | assert.file(["environments/2/b"]); 20 | assert.file(["environments/2/c"]); 21 | assert.file(["environments/3"]); 22 | assert.file(["environments/3/a"]); 23 | assert.file(["environments/3/b"]); 24 | assert.file(["environments/3/c"]); 25 | }); 26 | 27 | it("creates correct files in an environment", () => { 28 | assert.file([ 29 | "environments/1/a/a.tf", 30 | "environments/1/a/terraform.tfvars", 31 | "environments/1/a/input.tf", 32 | "environments/1/a/output.tf" 33 | ]); 34 | }); 35 | 36 | it("creates per-module folders and files", () => { 37 | assert.file(["modules/a", "modules/b", "modules/c"]); 38 | assert.file([ 39 | "modules/a/a.tf", 40 | "modules/a/input.tf", 41 | "modules/a/output.tf", 42 | "modules/b/b.tf", 43 | "modules/b/input.tf", 44 | "modules/b/output.tf", 45 | "modules/c/c.tf", 46 | "modules/c/input.tf", 47 | "modules/c/output.tf" 48 | ]); 49 | }); 50 | }); 51 | 52 | describe("s3 remote backend", () => { 53 | beforeAll(() => { 54 | return backendsTestData.s3BackendTestData(); 55 | }); 56 | 57 | it("creates the correct s3 backend structure", () => { 58 | assert.fileContent([ 59 | ["environments/1/a/a.tf", "terraform {"], 60 | ["environments/1/a/a.tf", 'backend "s3"'], 61 | ["environments/1/a/a.tf", 'bucket = "myBucket"'], 62 | [ 63 | "environments/1/a/a.tf", 64 | 'key = "terraform-remote-state/1/a/terraform.tfstate"' 65 | ], 66 | ["environments/1/a/a.tf", 'region = "ap-southeast-2"'] 67 | ]); 68 | }); 69 | 70 | it("creates the correct references to other state files", () => { 71 | assert.fileContent([ 72 | ["environments/1/a/a.tf", 'data "terraform_remote_state" "b"'], 73 | ["environments/1/a/a.tf", 'data "terraform_remote_state" "c"'] 74 | ]); 75 | }); 76 | 77 | it("does not create a reference to itself", () => { 78 | assert.noFileContent([ 79 | ["environments/1/a/a.tf", 'data "terraform_remote_state" "a"'], 80 | ["environments/1/b/b.tf", 'data "terraform_remote_state" "b"'], 81 | ["environments/1/c/c.tf", 'data "terraform_remote_state" "c"'] 82 | ]); 83 | }); 84 | }); 85 | 86 | describe("consul remote backend", () => { 87 | beforeAll(() => { 88 | return backendsTestData.consulBackendTestData(); 89 | }); 90 | 91 | it("creates the correct consul backend structure", () => { 92 | assert.fileContent([ 93 | ["environments/1/a/a.tf", "terraform {"], 94 | ["environments/1/a/a.tf", 'backend "consul"'], 95 | ["environments/1/a/a.tf", 'address = "consul"'], 96 | ["environments/1/a/a.tf", 'path = "terraform-remote-state/1/a"'] 97 | ]); 98 | }); 99 | }); 100 | 101 | describe("atlas remote backend", () => { 102 | beforeAll(() => { 103 | return backendsTestData.atlasBackendTestData(); 104 | }); 105 | 106 | it("creates the correct atlas backend structure", () => { 107 | assert.fileContent([ 108 | ["environments/1/a/a.tf", "terraform {"], 109 | ["environments/1/a/a.tf", 'backend "atlas"'], 110 | ["environments/1/a/a.tf", 'name = "myOrg/myApp-1-a"'] 111 | ]); 112 | }); 113 | }); 114 | }); 115 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # generator-terraform-environments [![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Dependency Status][daviddm-image]][daviddm-url] [![Coverage percentage][coveralls-image]][coveralls-url] 2 | 3 | > Scaffolding used to create infrastructure environments using Terraform 4 | 5 | ## Installation 6 | 7 | First, install [Yeoman](http://yeoman.io) and generator-terraform-environments using [npm](https://www.npmjs.com/) (we assume you have pre-installed [node.js](https://nodejs.org/)). 8 | 9 | ```bash 10 | npm install -g yo 11 | npm install -g generator-terraform-environments 12 | ``` 13 | 14 | Then generate your new project, answering the prompts as required: 15 | 16 | ```bash 17 | yo terraform-environments 18 | ``` 19 | 20 | ## Usage 21 | 22 | After creating your scaffolding, you should have a folder structure similar to the following: 23 | 24 | ``` 25 | . 26 | ├── environments 27 | │   ├── production 28 | │   │   ├── compute 29 | │   │   │   ├── compute.tf 30 | │   │   │   ├── input.tf 31 | │   │   │   ├── output.tf 32 | │   │   │   └── terraform.tfvars 33 | │   │   ├── core 34 | │   │   │   ├── core.tf 35 | │   │   │   ├── input.tf 36 | │   │   │   ├── output.tf 37 | │   │   │   └── terraform.tfvars 38 | │   │   └── data 39 | │   │   ├── data.tf 40 | │   │   ├── input.tf 41 | │   │      ├── output.tf 42 | │   │   └── terraform.tfvars 43 | │   └── test 44 | │   ├── compute 45 | │   │   ├── compute.tf 46 | │   │   ├── input.tf 47 | │      │   ├── output.tf 48 | │   │   └── terraform.tfvars 49 | │   ├── core 50 | │   │   ├── core.tf 51 | │   │   ├── input.tf 52 | │      │   ├── output.tf 53 | │   │   └── terraform.tfvars 54 | │   └── data 55 | │   ├── data.tf 56 | │   ├── input.tf 57 | │         ├── output.tf 58 | │   └── terraform.tfvars 59 | └── modules 60 | ├── compute 61 | │   ├── compute.tf 62 | │   ├── input.tf 63 | │   └── output.tf 64 | ├── core 65 | │   ├── core.tf 66 | │   ├── input.tf 67 | │   └── output.tf 68 | └── data 69 | ├── data.tf 70 | ├── input.tf 71 | └── output.tf 72 | ``` 73 | 74 | The above example assumes that there are two environments (`production` and `test`), as well as three separate components (`core`, `compute` and `data`) 75 | 76 | To configure your component modules: 77 | 78 | - Edit `modules//.tf` and add terraform resources, or references to other modules that you need. 79 | - Edit `modules//input.tf` and add input parameters that the component module requires. 80 | - Edit `modules//output.tf` and add output parameters that are used by other component modules. 81 | 82 | To configure your environments: 83 | 84 | - Edit `environment///input.tf` and add input parameters required by the component module 85 | - Edit `environment///terraform.tfvars` and supply values here 86 | - Edit `environment///output.tf` and add output parameters that are used by other component modules. 87 | 88 | To deploy the core component into the test environment: 89 | 90 | ```bash 91 | cd ./environments/test/core 92 | terraform init 93 | terraform apply 94 | ``` 95 | 96 | Once the deployment is successful, you can rinse and repeat for all your other environments. 97 | 98 | ## Remote State Backends 99 | 100 | Currently this code generator supports the following remote state backends: 101 | 102 | - s3 103 | - consul 104 | 105 | ### s3 106 | 107 | For the s3 backend, you will be asked for the bucket name, a key prefix, as well as the AWS region for the bucket. The key prefix is especially useful if you have to share this bucket with other apps so the state files can be segregated off. 108 | 109 | As a pattern, the state files will be stored in ```s3://////terraform.tfstate``` 110 | 111 | Note: This code generator will not actually create the s3 bucket for you, and you will also need to provision permissions for the s3 bucket (via bucket policies and IAM users/roles) yourself. 112 | 113 | ### Consul 114 | 115 | For the consul backend, you will be asked for the consul address (defaults to localhost:8500), as well as the key prefix. The key prefix is especially useful if you have to share the Consul key-value store with other apps so the state files can be segregated off. 116 | 117 | As a pattern, the state will be stored in key ```//``` 118 | 119 | Note: This code generator will not manage permissions such as authentication keys, nor ACLs. You will need to manage and provision the appropriate ACLs yourself. 120 | 121 | ## License 122 | 123 | MIT © [William Tsoi](https://about.me/williamtsoi) 124 | 125 | [npm-image]: https://badge.fury.io/js/generator-terraform-environments.svg 126 | [npm-url]: https://npmjs.org/package/generator-terraform-environments 127 | [travis-image]: https://travis-ci.org/williamtsoi1/generator-terraform-environments.svg?branch=master 128 | [travis-url]: https://travis-ci.org/williamtsoi1/generator-terraform-environments 129 | [daviddm-image]: https://david-dm.org/williamtsoi1/generator-terraform-environments.svg?theme=shields.io 130 | [daviddm-url]: https://david-dm.org/williamtsoi1/generator-terraform-environments 131 | [coveralls-image]: https://coveralls.io/repos/williamtsoi1/generator-terraform-environments/badge.svg 132 | [coveralls-url]: https://coveralls.io/r/williamtsoi1/generator-terraform-environments 133 | -------------------------------------------------------------------------------- /generators/app/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const Generator = require("yeoman-generator"); 3 | const chalk = require("chalk"); 4 | const yosay = require("yosay"); 5 | const providers = require("./templates/providers.json"); 6 | const backends = require("./templates/backends.json"); 7 | 8 | module.exports = class extends Generator { 9 | prompting() { 10 | // Have Yeoman greet the user. 11 | this.log( 12 | yosay( 13 | "Welcome to the slick " + 14 | chalk.red("generator-terraform-environments") + 15 | " generator!" 16 | ) 17 | ); 18 | 19 | const prompts = [ 20 | { 21 | type: "input", 22 | name: "environments", 23 | message: 24 | "What logical environments will you be running (separate multiple responses by comma)?", 25 | default: "staging,production", 26 | store: true 27 | }, 28 | { 29 | type: "input", 30 | name: "components", 31 | message: 32 | "What components will you be running (separate multiple responses by comma)?", 33 | default: "core,compute,data", 34 | store: true 35 | }, 36 | { 37 | type: "list", 38 | name: "backend", 39 | message: 40 | "What state backend will you be using? Full list of backends here: https://www.terraform.io/docs/backend/types/index.html", 41 | choices: Object.keys(backends) 42 | }, 43 | { 44 | type: "list", 45 | name: "provider", 46 | message: 47 | "What Terraform provider will you be using? Full list of providers here: https://www.terraform.io/docs/providers", 48 | choices: Object.keys(providers) 49 | }, 50 | { 51 | when: props => props.backend === "s3", 52 | type: "input", 53 | name: "backendBucketName", 54 | message: "Name of the S3 Bucket for remote state", 55 | validate: input => input.length > 0 56 | }, 57 | { 58 | when: props => props.backend === "s3", 59 | type: "input", 60 | name: "backendBucketKeyPrefix", 61 | message: "The key prefix for the remote state files", 62 | default: "terraform-remote-state" 63 | }, 64 | { 65 | when: props => props.backend === "s3", 66 | type: "input", 67 | name: "backendBucketRegion", 68 | message: "The AWS region for the S3 Bucket", 69 | default: "ap-southeast-2" 70 | }, 71 | { 72 | when: props => props.backend === "consul", 73 | type: "input", 74 | name: "backendConsulAddress", 75 | message: "The address of the Consul agent", 76 | default: "localhost:8500", 77 | validate: input => input.length > 0 78 | }, 79 | { 80 | when: props => props.backend === "consul", 81 | type: "input", 82 | name: "backendConsulPathPrefix", 83 | message: "The path prefix for the remote state", 84 | default: "terraform-remote-state" 85 | }, 86 | { 87 | when: props => props.backend === "atlas", 88 | type: "input", 89 | name: "backendAtlasOrganisationName", 90 | message: "The name of your Terraform Enterprise Organisation", 91 | default: "myOrg", 92 | validate: input => input.length > 0 93 | }, 94 | { 95 | when: props => props.backend === "atlas", 96 | type: "input", 97 | name: "backendAtlasWorkspacePrefix", 98 | message: "Prefix for your Terraform Enterprise Workspaces", 99 | default: "myApp", 100 | validate: input => input.length > 0 101 | } 102 | ]; 103 | 104 | return this.prompt(prompts).then(props => { 105 | // To access props later use this.props.someAnswer; 106 | this.props = props; 107 | }); 108 | } 109 | 110 | writingEnvironments() { 111 | var environments = this.props.environments.split(","); 112 | var components = this.props.components.split(","); 113 | for (let component of components) { 114 | // Creates environment folders 115 | for (let environment of environments) { 116 | this.fs.copyTpl( 117 | this.templatePath("environments/components/component.tf"), 118 | this.destinationPath( 119 | `environments/${environment}/${component}/${component}.tf` 120 | ), 121 | { 122 | provider: this.props.provider, 123 | providerAttributes: providers[this.props.provider], 124 | appName: this.props.appName, 125 | backend: this.props.backend, 126 | backendBucketName: this.props.backendBucketName, 127 | backendBucketKeyPrefix: this.props.backendBucketKeyPrefix, 128 | backendBucketRegion: this.props.backendBucketRegion, 129 | backendConsulAddress: this.props.backendConsulAddress, 130 | backendConsulPathPrefix: this.props.backendConsulPathPrefix, 131 | backendAtlasOrganisationName: this.props 132 | .backendAtlasOrganisationName, 133 | backendAtlasWorkspacePrefix: this.props.backendAtlasWorkspacePrefix, 134 | environment: environment, 135 | component: component, 136 | components: components 137 | } 138 | ); 139 | this.fs.copyTpl( 140 | this.templatePath("environments/components/terraform.tfvars"), 141 | this.destinationPath( 142 | `environments/${environment}/${component}/terraform.tfvars` 143 | ), 144 | { 145 | environment: environment, 146 | component: component 147 | } 148 | ); 149 | this.fs.copy( 150 | this.templatePath("environments/components/input.tf"), 151 | this.destinationPath( 152 | `environments/${environment}/${component}/input.tf` 153 | ) 154 | ); 155 | this.fs.copy( 156 | this.templatePath("environments/components/output.tf"), 157 | this.destinationPath( 158 | `environments/${environment}/${component}/output.tf` 159 | ) 160 | ); 161 | this.fs.copy( 162 | this.templatePath("gitignore"), 163 | this.destinationPath(".gitignore") 164 | ); 165 | } 166 | } 167 | } 168 | 169 | writingModules() { 170 | var components = this.props.components.split(","); 171 | for (let component of components) { 172 | // Creates module folders 173 | this.fs.copy( 174 | this.templatePath("modules/input.tf"), 175 | this.destinationPath(`modules/${component}/input.tf`) 176 | ); 177 | this.fs.copyTpl( 178 | this.templatePath("modules/module.tf"), 179 | this.destinationPath(`modules/${component}/${component}.tf`), 180 | { component: component } 181 | ); 182 | this.fs.copy( 183 | this.templatePath("modules/output.tf"), 184 | this.destinationPath(`modules/${component}/output.tf`) 185 | ); 186 | } 187 | } 188 | 189 | install() {} 190 | }; 191 | --------------------------------------------------------------------------------