TerraformDevKit 0.1.10 → 0.1.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +103 -1
- data/lib/TerraformDevKit/terraform_config_manager.rb +12 -6
- data/lib/TerraformDevKit/version.rb +1 -1
- data/tasks/devkit.rake +13 -8
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73056367038798386bcc02b1d20f801c27e43ef0
|
4
|
+
data.tar.gz: 0e1f59d12f2dd358ea463360bb3dce9e0f5255b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f61ca6d7b4d70b25298ea785c27245c0e59df4e8e41f8490ece88a33e6e9e900b7e048029bd2429d90b631d519fcf8aa04f1d27754d939a6927f27393609a75f
|
7
|
+
data.tar.gz: 5eef28470ca98ce7e859c20bae13cfc8f1baa4b9c362f2278bd406543c6f0358e80e6e935b04db9572b23679e79984a8c6a17eed01428d5a03dab888e50f80c0
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# TerraformDevKit
|
2
2
|
|
3
|
-
[![Build Status](https://travis-ci.org/vistaprint/TerraformDevKit.svg?branch=master)](https://travis-ci.org/vistaprint/TerraformDevKit) [![Build status](https://ci.appveyor.com/api/projects/status/
|
3
|
+
[![Build Status](https://travis-ci.org/vistaprint/TerraformDevKit.svg?branch=master)](https://travis-ci.org/vistaprint/TerraformDevKit) [![Build status](https://ci.appveyor.com/api/projects/status/74s4yd7dmuwg5tmn/branch/master?svg=true)](https://ci.appveyor.com/project/Vistaprint/terraformdevkit/branch/master)
|
4
4
|
|
5
5
|
Set of scripts to ease development and testing with [Terraform](https://www.terraform.io/).
|
6
6
|
|
@@ -44,6 +44,108 @@ To use the library simply import it as:
|
|
44
44
|
require 'TerraformDevKit'
|
45
45
|
```
|
46
46
|
|
47
|
+
## Managing Terraform Environments
|
48
|
+
|
49
|
+
TerraformDevKit provides a set of Rake tasks and Ruby scripts to ease the management of multiple Terraform environments. Three major environment types are supported: `dev`, `test` and `prod`.
|
50
|
+
|
51
|
+
There might be many development environments (`dev`), each one with its own name. Development environments use a local Terraform backend. They are intented to be used by developers while adding features to the infrastructure.
|
52
|
+
|
53
|
+
Testing (`test`) and production (`prod`) environment use a remote backend. Thus, the Terraform state file is not kept in the local disk, but on S3. This allows multiple developers to easily work on the same infrastructure instance. For safety reasons, operations that affect testing and production environments require manual user input. This is not the case for development environments.
|
54
|
+
|
55
|
+
TerraformDevKit expects templated versions (using [Mustache](https://mustache.github.io/)) of the Terraform files. Such files might contain placeholders for several fields such as `Environment`, (AWS) `Region` or (AWS) `Profile`, among others. TerraformDevKit uses the template files to generate the final files that will be consumed by Terraform and Terragrunt. As an example, for the production environment, the resulting files are placed in a directory named `envs/prod`.
|
56
|
+
|
57
|
+
### Configuration Files
|
58
|
+
|
59
|
+
Configuration files must be placed in a directory named `config`. Each environment type requires a different configuration file. Thus, the following three files must be placed in the `config` directory:
|
60
|
+
|
61
|
+
* `config-dev.yml`
|
62
|
+
* `config-test.yml`
|
63
|
+
* `config-prod.yml`
|
64
|
+
|
65
|
+
The first one contains the configuration for **all** the development environments that are created. The other two contain the configuration for the test and production environments, respectively.
|
66
|
+
|
67
|
+
A sample configuration files is shown next:
|
68
|
+
|
69
|
+
```yaml
|
70
|
+
terraform-version: 0.10.8
|
71
|
+
terragrunt-version: 0.13.15
|
72
|
+
aws:
|
73
|
+
profile: myprofile
|
74
|
+
region: eu-west-1
|
75
|
+
```
|
76
|
+
|
77
|
+
The AWS profile **must not** be specified for test and production accounts, as users are required to manually type the profile name.
|
78
|
+
|
79
|
+
### A Minimal Rakefile
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
ROOT_PATH = File.dirname(File.expand_path(__FILE__))
|
83
|
+
|
84
|
+
spec = Gem::Specification.find_by_name 'TerraformDevKit'
|
85
|
+
load "#{spec.gem_dir}/tasks/devkit.rake"
|
86
|
+
|
87
|
+
task :custom_test, [:env] do |_, args|
|
88
|
+
# Add some tests here
|
89
|
+
end
|
90
|
+
```
|
91
|
+
|
92
|
+
### Sample Terraform/Terragrunt Templates
|
93
|
+
|
94
|
+
The following file (`main.tf.mustache`) contains the infrastructure configuration (a single S3 bucket) as well as information related to the AWS provider.
|
95
|
+
|
96
|
+
```hcl
|
97
|
+
locals {
|
98
|
+
env = "{{Environment}}"
|
99
|
+
}
|
100
|
+
|
101
|
+
terraform {
|
102
|
+
backend {{#LocalBackend}}"local"{{/LocalBackend}}{{^LocalBackend}}"s3"{{/LocalBackend}} {}
|
103
|
+
}
|
104
|
+
|
105
|
+
provider "aws" {
|
106
|
+
profile = "{{Profile}}"
|
107
|
+
region = "{{Region}}"
|
108
|
+
}
|
109
|
+
|
110
|
+
resource "aws_s3_bucket" "raw" {
|
111
|
+
bucket = "foo-${local.env}"
|
112
|
+
acl = "private"
|
113
|
+
|
114
|
+
{{#LocalBackend}}
|
115
|
+
force_destroy = true
|
116
|
+
{{/LocalBackend}}
|
117
|
+
{{^LocalBackend}}
|
118
|
+
lifecycle {
|
119
|
+
prevent_destroy = true
|
120
|
+
}
|
121
|
+
{{/LocalBackend}}
|
122
|
+
}
|
123
|
+
```
|
124
|
+
|
125
|
+
An additional file (`terraform.tfvars.mustache`) contains the Terragrunt configuration. Terragrunt is used as it makes it easier to manage a remote backend. While Terraform is able to keep the state file in S3, it does not transparently create the DynamoDB lock table that prevents multiple developers from concurrently modifying the state file. Terragrunt, however, is able to do this without user intervention.
|
126
|
+
|
127
|
+
```hcl
|
128
|
+
terragrunt = {
|
129
|
+
remote_state {
|
130
|
+
{{#LocalBackend}}
|
131
|
+
backend = "local"
|
132
|
+
config {}
|
133
|
+
{{/LocalBackend}}
|
134
|
+
{{^LocalBackend}}
|
135
|
+
backend = "s3"
|
136
|
+
config {
|
137
|
+
bucket = "foo-remote-state"
|
138
|
+
key = "foo-{{Environment}}.tfstate"
|
139
|
+
lock_table = "foo-{{Environment}}-lock-table"
|
140
|
+
encrypt = true
|
141
|
+
profile = "{{Profile}}"
|
142
|
+
region = "{{Region}}"
|
143
|
+
}
|
144
|
+
{{/LocalBackend}}
|
145
|
+
}
|
146
|
+
}
|
147
|
+
```
|
148
|
+
|
47
149
|
## Development
|
48
150
|
|
49
151
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -4,14 +4,20 @@ require 'fileutils'
|
|
4
4
|
|
5
5
|
module TerraformDevKit
|
6
6
|
class TerraformConfigManager
|
7
|
-
|
7
|
+
@extra_vars_proc = proc { {} }
|
8
|
+
|
9
|
+
def self.register_extra_vars_proc(p)
|
10
|
+
@extra_vars_proc = p
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.setup(env)
|
8
14
|
fix_configuration(env)
|
9
15
|
create_environment_directory(env)
|
10
|
-
render_template_config_files(env
|
16
|
+
render_template_config_files(env)
|
11
17
|
end
|
12
18
|
|
13
19
|
def self.update_modules?
|
14
|
-
skip_update = ENV.fetch('
|
20
|
+
skip_update = ENV.fetch('TF_DEVKIT_SKIP_MODULE_UPDATE', 'false')
|
15
21
|
.strip
|
16
22
|
.downcase
|
17
23
|
skip_update != 'true'
|
@@ -38,7 +44,7 @@ module TerraformDevKit
|
|
38
44
|
end
|
39
45
|
|
40
46
|
private_class_method
|
41
|
-
def self.render_template_config_files(env
|
47
|
+
def self.render_template_config_files(env)
|
42
48
|
aws_config = Configuration.get('aws')
|
43
49
|
file_list = Dir['*.tf.mustache'] + Dir['*.tfvars.mustache']
|
44
50
|
file_list.each do |fname|
|
@@ -46,7 +52,7 @@ module TerraformDevKit
|
|
46
52
|
File.read(fname),
|
47
53
|
env,
|
48
54
|
aws_config,
|
49
|
-
extra_vars:
|
55
|
+
extra_vars: @extra_vars_proc.call(env)
|
50
56
|
)
|
51
57
|
config_fname = File.basename(fname, File.extname(fname))
|
52
58
|
Dir.chdir(env.working_dir) do
|
@@ -60,7 +66,7 @@ module TerraformDevKit
|
|
60
66
|
puts "Environment #{env.name} requires manual input of AWS credentials"
|
61
67
|
print 'Enter the profile to use: '
|
62
68
|
profile = $stdin.gets.tr("\r\n", '')
|
63
|
-
raise 'Invalid profile name'
|
69
|
+
/^\w+$/ =~ profile || (raise 'Invalid profile name')
|
64
70
|
profile
|
65
71
|
end
|
66
72
|
end
|
data/tasks/devkit.rake
CHANGED
@@ -12,8 +12,6 @@ ENV['PATH'] = TDK::OS.join_env_path(
|
|
12
12
|
ENV['PATH']
|
13
13
|
)
|
14
14
|
|
15
|
-
TF_CONFIG_EXTRA_VARS = {}.freeze unless defined?(TF_CONFIG_EXTRA_VARS)
|
16
|
-
|
17
15
|
def destroy_if_fails(env)
|
18
16
|
yield
|
19
17
|
rescue StandardError => e
|
@@ -41,17 +39,19 @@ task :prepare, [:env] do |_, args|
|
|
41
39
|
directory: BIN_PATH
|
42
40
|
)
|
43
41
|
|
44
|
-
TDK::TerraformConfigManager.setup(env
|
42
|
+
TDK::TerraformConfigManager.setup(env)
|
45
43
|
|
46
|
-
|
44
|
+
if Rake::Task.task_defined?('custom_prepare')
|
45
|
+
task('custom_prepare').invoke(args.env)
|
46
|
+
end
|
47
47
|
|
48
48
|
TDK::Command.run(
|
49
|
-
'terragrunt init',
|
49
|
+
'terragrunt init -upgrade=false',
|
50
50
|
directory: env.working_dir,
|
51
51
|
close_stdin: false
|
52
52
|
)
|
53
53
|
|
54
|
-
cmd
|
54
|
+
cmd = 'terragrunt get'
|
55
55
|
cmd += ' -update=true' if TDK::TerraformConfigManager.update_modules?
|
56
56
|
TDK::Command.run(cmd, directory: env.working_dir)
|
57
57
|
end
|
@@ -73,12 +73,14 @@ end
|
|
73
73
|
desc 'Tests a local environment'
|
74
74
|
task :test, [:env] do |_, args|
|
75
75
|
env = TDK::Environment.new(args.env)
|
76
|
-
raise 'Testing is only allowed for local environments'
|
76
|
+
env.local_backend? || (raise 'Testing is only allowed for local environments')
|
77
77
|
|
78
78
|
task('apply').invoke(env.name)
|
79
79
|
|
80
80
|
destroy_if_fails(env) do
|
81
|
-
|
81
|
+
if Rake::Task.task_defined?('custom_test')
|
82
|
+
task('custom_test').invoke(args.env)
|
83
|
+
end
|
82
84
|
end
|
83
85
|
end
|
84
86
|
|
@@ -96,6 +98,9 @@ task :destroy, [:env] => :prepare do |_, args|
|
|
96
98
|
cmd = 'terragrunt destroy'
|
97
99
|
cmd += ' -force' if env.local_backend?
|
98
100
|
TDK::Command.run(cmd, directory: env.working_dir, close_stdin: false)
|
101
|
+
if Rake::Task.task_defined?('custom_destroy')
|
102
|
+
task('custom_destroy').invoke(args.env)
|
103
|
+
end
|
99
104
|
end
|
100
105
|
|
101
106
|
desc 'Cleans an environment (infrastructure is destroyed too)'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: TerraformDevKit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Victor Jimenez
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-11-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|