TerraformDevKit 0.1.9 → 0.1.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -10
- data/TerraformDevKit.gemspec +2 -1
- data/lib/TerraformDevKit.rb +3 -0
- data/lib/TerraformDevKit/environment.rb +47 -0
- data/lib/TerraformDevKit/terraform_config_manager.rb +67 -0
- data/lib/TerraformDevKit/terraform_template_config_file.rb +26 -0
- data/lib/TerraformDevKit/version.rb +1 -1
- data/tasks/devkit.rake +106 -0
- metadata +21 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e92fbd82b70265947a9eb3db56bad0c5b85d78f
|
4
|
+
data.tar.gz: 9048f6a2ea5e8ff08181d87515050ccf10e0931e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ebef969303e8fc2f00e1911a04990d3f3abbf790277f3a863788cdd57ea00bb848c25d5bdb346bd9a931375e3dcd7bbfbdb06a708a83067d950235d77ec6490
|
7
|
+
data.tar.gz: 294017e43b6b007d2c0fc23e93ab7bbed995e65c011eaeda6062ca8a6381f28d1361575ce7cc2ff15e3175d292bd48b7a72570571786f925eccbf6ccf28cfb8b
|
data/README.md
CHANGED
@@ -1,22 +1,24 @@
|
|
1
1
|
# TerraformDevKit
|
2
2
|
|
3
|
-
[![Build Status](https://travis-ci.org/
|
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/4vkyr196li83vju6/branch/master?svg=true)](https://ci.appveyor.com/project/betabandido/terraformdevkit/branch/master)
|
4
4
|
|
5
5
|
Set of scripts to ease development and testing with [Terraform](https://www.terraform.io/).
|
6
6
|
|
7
|
-
The script collection
|
7
|
+
The script collection includes support for:
|
8
8
|
|
9
9
|
* Managing AWS credentials
|
10
|
-
* Simple reading and writing to AWS DynamoDB
|
11
|
-
* Polling an AWS ApiGateway endpoint until it becomes ready
|
12
|
-
* Executing commands
|
13
|
-
* Locally installing Terraform and [Terragrunt](https://github.com/gruntwork-io/terragrunt)
|
14
10
|
* Backing up the state from a failed Terraform execution
|
15
|
-
*
|
11
|
+
* Executing external commands
|
16
12
|
* Simple configuration management
|
13
|
+
* Simple reading and writing to AWS DynamoDB
|
14
|
+
* Multiplatform tools
|
15
|
+
* Making simple HTTP requests
|
16
|
+
* Retrying a block of code
|
17
17
|
* Terraform environment management
|
18
|
+
* Locally installing Terraform and [Terragrunt](https://github.com/gruntwork-io/terragrunt)
|
19
|
+
* Filtering Terraform logging messages
|
18
20
|
|
19
|
-
Most of these scripts exist to provide support to a module development and testing environment for Terraform: [TerraformModules](https://github.com/
|
21
|
+
Most of these scripts exist to provide support to a module development and testing environment for Terraform: [TerraformModules](https://github.com/vistaprint/TerraformModules). But, they might be useful for other purposes too.
|
20
22
|
|
21
23
|
## Installation
|
22
24
|
|
@@ -50,8 +52,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
50
52
|
|
51
53
|
## Contributing
|
52
54
|
|
53
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
54
|
-
|
55
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/vistaprint/TerraformDevKit.
|
55
56
|
|
56
57
|
## License
|
57
58
|
|
data/TerraformDevKit.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
|
|
11
11
|
spec.email = ['vjimenez@vistaprint.com']
|
12
12
|
|
13
13
|
spec.summary = 'Set of scripts to ease development and testing with Terraform.'
|
14
|
-
spec.homepage = 'https://github.com/
|
14
|
+
spec.homepage = 'https://github.com/vistaprint/TerraformDevKit'
|
15
15
|
spec.license = 'Apache-2.0'
|
16
16
|
|
17
17
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
@@ -27,5 +27,6 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.add_development_dependency 'webmock', '~> 3.0.1'
|
28
28
|
|
29
29
|
spec.add_runtime_dependency 'aws-sdk', '~> 2.9.37'
|
30
|
+
spec.add_runtime_dependency 'mustache', '~> 1.0.2'
|
30
31
|
spec.add_runtime_dependency 'rubyzip', '~> 1.2.1'
|
31
32
|
end
|
data/lib/TerraformDevKit.rb
CHANGED
@@ -3,12 +3,15 @@ require 'TerraformDevKit/backup_state'
|
|
3
3
|
require 'TerraformDevKit/command'
|
4
4
|
require 'TerraformDevKit/config'
|
5
5
|
require 'TerraformDevKit/dynamodb'
|
6
|
+
require 'TerraformDevKit/environment'
|
6
7
|
require 'TerraformDevKit/os'
|
7
8
|
require 'TerraformDevKit/request'
|
8
9
|
require 'TerraformDevKit/retry'
|
10
|
+
require 'TerraformDevKit/terraform_config_manager'
|
9
11
|
require 'TerraformDevKit/terraform_env_manager'
|
10
12
|
require 'TerraformDevKit/terraform_installer'
|
11
13
|
require 'TerraformDevKit/terraform_log_filter'
|
14
|
+
require 'TerraformDevKit/terraform_template_config_file'
|
12
15
|
require 'TerraformDevKit/terragrunt_installer'
|
13
16
|
require 'TerraformDevKit/url'
|
14
17
|
require 'TerraformDevKit/version'
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module TerraformDevKit
|
4
|
+
class Environment
|
5
|
+
attr_reader :name
|
6
|
+
|
7
|
+
def initialize(name)
|
8
|
+
raise 'Environment must not be null' if name.nil?
|
9
|
+
raise "Invalid environment name: #{name}" unless /^[0-9a-zA-Z]+$/ =~ name
|
10
|
+
@name = name.downcase
|
11
|
+
end
|
12
|
+
|
13
|
+
def config
|
14
|
+
case @name
|
15
|
+
when 'prod'
|
16
|
+
'prod'
|
17
|
+
when 'test'
|
18
|
+
'test'
|
19
|
+
else
|
20
|
+
'dev'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def local_backend?
|
25
|
+
case @name
|
26
|
+
when 'prod', 'test'
|
27
|
+
false
|
28
|
+
else
|
29
|
+
true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def working_dir
|
34
|
+
"envs/#{@name}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.temp_name
|
38
|
+
hostname = Socket.gethostname
|
39
|
+
date = Time.now.strftime('%y%m%d%H%M')
|
40
|
+
"#{hostname}#{date}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.running_on_jenkins?
|
44
|
+
ENV.key?('JENKINS_URL') && ENV.key?('BUILD_ID')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'TerraformDevKit/terraform_template_config_file'
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module TerraformDevKit
|
6
|
+
class TerraformConfigManager
|
7
|
+
def self.setup(env, extra_vars: {})
|
8
|
+
fix_configuration(env)
|
9
|
+
create_environment_directory(env)
|
10
|
+
render_template_config_files(env, extra_vars)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.update_modules?
|
14
|
+
skip_update = ENV.fetch('TF_DEV_KIT_SKIP_MODULE_UPDATE', 'false')
|
15
|
+
.strip
|
16
|
+
.downcase
|
17
|
+
skip_update != 'true'
|
18
|
+
end
|
19
|
+
|
20
|
+
private_class_method
|
21
|
+
def self.fix_configuration(env)
|
22
|
+
raise 'No AWS section in the config file' if Configuration.get('aws').nil?
|
23
|
+
if Environment.running_on_jenkins?
|
24
|
+
Configuration.get('aws').delete('profile')
|
25
|
+
elsif Configuration.get('aws').key?('profile')
|
26
|
+
unless env.local_backend?
|
27
|
+
raise "AWS credentials for environment #{env.name} must not be stored!"
|
28
|
+
end
|
29
|
+
else
|
30
|
+
profile = request_profile(env)
|
31
|
+
Configuration.get('aws')['profile'] = profile
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private_class_method
|
36
|
+
def self.create_environment_directory(env)
|
37
|
+
FileUtils.makedirs(env.working_dir)
|
38
|
+
end
|
39
|
+
|
40
|
+
private_class_method
|
41
|
+
def self.render_template_config_files(env, extra_vars)
|
42
|
+
aws_config = Configuration.get('aws')
|
43
|
+
file_list = Dir['*.tf.mustache'] + Dir['*.tfvars.mustache']
|
44
|
+
file_list.each do |fname|
|
45
|
+
template_file = TerraformTemplateConfigFile.new(
|
46
|
+
File.read(fname),
|
47
|
+
env,
|
48
|
+
aws_config,
|
49
|
+
extra_vars: extra_vars
|
50
|
+
)
|
51
|
+
config_fname = File.basename(fname, File.extname(fname))
|
52
|
+
Dir.chdir(env.working_dir) do
|
53
|
+
File.open(config_fname, 'w') { |f| f.write(template_file.render) }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private_class_method
|
59
|
+
def self.request_profile(env)
|
60
|
+
puts "Environment #{env.name} requires manual input of AWS credentials"
|
61
|
+
print 'Enter the profile to use: '
|
62
|
+
profile = $stdin.gets.tr("\r\n", '')
|
63
|
+
raise 'Invalid profile name' unless /^\w+$/ =~ profile
|
64
|
+
profile
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'mustache'
|
2
|
+
|
3
|
+
module TerraformDevKit
|
4
|
+
class TerraformTemplateConfigFile
|
5
|
+
def initialize(content, env, aws_config, extra_vars: {})
|
6
|
+
@content = content
|
7
|
+
@env = env
|
8
|
+
@aws_config = aws_config
|
9
|
+
@extra_vars = extra_vars
|
10
|
+
end
|
11
|
+
|
12
|
+
def render
|
13
|
+
args = {
|
14
|
+
Profile: @aws_config.fetch('profile', ''),
|
15
|
+
Region: @aws_config.fetch('region'),
|
16
|
+
Environment: @env.name,
|
17
|
+
LocalBackend: @env.local_backend?
|
18
|
+
}
|
19
|
+
args.merge!(@extra_vars)
|
20
|
+
Mustache.render(
|
21
|
+
@content,
|
22
|
+
args
|
23
|
+
)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/tasks/devkit.rake
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'TerraformDevKit'
|
3
|
+
|
4
|
+
TDK = TerraformDevKit
|
5
|
+
|
6
|
+
raise 'ROOT_PATH is not defined' if defined?(ROOT_PATH).nil?
|
7
|
+
BIN_PATH = File.join(ROOT_PATH, 'bin')
|
8
|
+
|
9
|
+
# Ensure terraform and terragrunt are in the PATH
|
10
|
+
ENV['PATH'] = TDK::OS.join_env_path(
|
11
|
+
TDK::OS.convert_to_local_path(BIN_PATH),
|
12
|
+
ENV['PATH']
|
13
|
+
)
|
14
|
+
|
15
|
+
TF_CONFIG_EXTRA_VARS = {}.freeze unless defined?(TF_CONFIG_EXTRA_VARS)
|
16
|
+
|
17
|
+
def destroy_if_fails(env)
|
18
|
+
yield
|
19
|
+
rescue StandardError => e
|
20
|
+
puts "ERROR: #{e.message}"
|
21
|
+
puts e.backtrace.join("\n")
|
22
|
+
task('destroy').invoke(env.name) if env.local_backend?
|
23
|
+
raise
|
24
|
+
end
|
25
|
+
|
26
|
+
desc 'Prepares the environment to create the infrastructure'
|
27
|
+
task :prepare, [:env] do |_, args|
|
28
|
+
puts "== Configuring environment #{args.env}"
|
29
|
+
env = TDK::Environment.new(args.env)
|
30
|
+
|
31
|
+
config_file = "config/config-#{env.config}.yml"
|
32
|
+
puts "== Loading configuration from #{config_file}"
|
33
|
+
TDK::Configuration.init(config_file)
|
34
|
+
|
35
|
+
TDK::TerraformInstaller.install_local(
|
36
|
+
TDK::Configuration.get('terraform-version'),
|
37
|
+
directory: BIN_PATH
|
38
|
+
)
|
39
|
+
TDK::TerragruntInstaller.install_local(
|
40
|
+
TDK::Configuration.get('terragrunt-version'),
|
41
|
+
directory: BIN_PATH
|
42
|
+
)
|
43
|
+
|
44
|
+
TDK::TerraformConfigManager.setup(env, extra_vars: TF_CONFIG_EXTRA_VARS)
|
45
|
+
|
46
|
+
task('custom_prepare').invoke(args.env) if Rake::Task.task_defined?('custom_prepare')
|
47
|
+
|
48
|
+
TDK::Command.run(
|
49
|
+
'terragrunt init',
|
50
|
+
directory: env.working_dir,
|
51
|
+
close_stdin: false
|
52
|
+
)
|
53
|
+
|
54
|
+
cmd = 'terragrunt get'
|
55
|
+
cmd += ' -update=true' if TDK::TerraformConfigManager.update_modules?
|
56
|
+
TDK::Command.run(cmd, directory: env.working_dir)
|
57
|
+
end
|
58
|
+
|
59
|
+
desc 'Shows the plan to create the infrastructure'
|
60
|
+
task :plan, [:env] => :prepare do |_, args|
|
61
|
+
env = TDK::Environment.new(args.env)
|
62
|
+
TDK::Command.run('terragrunt plan', directory: env.working_dir)
|
63
|
+
end
|
64
|
+
|
65
|
+
desc 'Creates the infrastructure'
|
66
|
+
task :apply, [:env] => :prepare do |_, args|
|
67
|
+
env = TDK::Environment.new(args.env)
|
68
|
+
destroy_if_fails(env) do
|
69
|
+
TDK::Command.run('terragrunt apply', directory: env.working_dir)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
desc 'Tests a local environment'
|
74
|
+
task :test, [:env] do |_, args|
|
75
|
+
env = TDK::Environment.new(args.env)
|
76
|
+
raise 'Testing is only allowed for local environments' unless env.local_backend?
|
77
|
+
|
78
|
+
task('apply').invoke(env.name)
|
79
|
+
|
80
|
+
destroy_if_fails(env) do
|
81
|
+
task('custom_test').invoke(args.env) if Rake::Task.task_defined?('custom_test')
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
desc 'Creates the infrastructure and run the tests'
|
86
|
+
task :preflight, [:teardown] do |_, args|
|
87
|
+
args.with_defaults(teardown: 'true')
|
88
|
+
env = TDK::Environment.new(TDK::Environment.temp_name)
|
89
|
+
task('test').invoke(env.name)
|
90
|
+
task('clean').invoke(env.name) if args.teardown == 'true'
|
91
|
+
end
|
92
|
+
|
93
|
+
desc 'Destroys the infrastructure'
|
94
|
+
task :destroy, [:env] => :prepare do |_, args|
|
95
|
+
env = TDK::Environment.new(args.env)
|
96
|
+
cmd = 'terragrunt destroy'
|
97
|
+
cmd += ' -force' if env.local_backend?
|
98
|
+
TDK::Command.run(cmd, directory: env.working_dir, close_stdin: false)
|
99
|
+
end
|
100
|
+
|
101
|
+
desc 'Cleans an environment (infrastructure is destroyed too)'
|
102
|
+
task :clean, [:env] => :destroy do |_, args|
|
103
|
+
env = TDK::Environment.new(args.env)
|
104
|
+
puts "Deleting environment #{env.name}"
|
105
|
+
FileUtils.rm_rf(env.working_dir, secure: true)
|
106
|
+
end
|
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.10
|
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-10-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 2.9.37
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: mustache
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.0.2
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.0.2
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: rubyzip
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -121,17 +135,21 @@ files:
|
|
121
135
|
- lib/TerraformDevKit/config.rb
|
122
136
|
- lib/TerraformDevKit/download.rb
|
123
137
|
- lib/TerraformDevKit/dynamodb.rb
|
138
|
+
- lib/TerraformDevKit/environment.rb
|
124
139
|
- lib/TerraformDevKit/os.rb
|
125
140
|
- lib/TerraformDevKit/request.rb
|
126
141
|
- lib/TerraformDevKit/retry.rb
|
142
|
+
- lib/TerraformDevKit/terraform_config_manager.rb
|
127
143
|
- lib/TerraformDevKit/terraform_env_manager.rb
|
128
144
|
- lib/TerraformDevKit/terraform_installer.rb
|
129
145
|
- lib/TerraformDevKit/terraform_log_filter.rb
|
146
|
+
- lib/TerraformDevKit/terraform_template_config_file.rb
|
130
147
|
- lib/TerraformDevKit/terragrunt_installer.rb
|
131
148
|
- lib/TerraformDevKit/url.rb
|
132
149
|
- lib/TerraformDevKit/version.rb
|
133
150
|
- lib/TerraformDevKit/zip_file_generator.rb
|
134
|
-
|
151
|
+
- tasks/devkit.rake
|
152
|
+
homepage: https://github.com/vistaprint/TerraformDevKit
|
135
153
|
licenses:
|
136
154
|
- Apache-2.0
|
137
155
|
metadata: {}
|