rake-terraform 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YmZiOTEzNThjZDlkMDU1MmQzOTJiMmNlMGFhY2E0ODg3ODdjMzQ1NA==
5
+ data.tar.gz: !binary |-
6
+ YWFlOWViNWExNTNkNDhiYTZiMTg3Mjg3NWQ1MTQ2ZTliMzEzMTFmNQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ YmMzMDlhZTFiYmM0OGViOWRiYjYzZGYzMmI3YTA3Mjk4YjM4MTg1ZDQyZDU1
10
+ Y2M2M2ZmN2E3MzQyZjBhYWMyZjk1MDkyZDU5YmY1ZDY0YjdiMjk5MDhiNTNm
11
+ YzA3ZGVhMWQ0ZmZkODk1ZDU4NzA0N2FjZDJjYjU3ZWFiZjJkNjg=
12
+ data.tar.gz: !binary |-
13
+ NTA2NGYxNThhZDZlZmIzYmVlNGYwZDFhY2ZmNDVmZTIxMzI3YjYxMjc1YzZk
14
+ NDQ5OGIzMjQyYWEwYmY3NTc3ODc5YjE3ZDQ5OTIzYjZmYjBlZDY0MzcxMmM3
15
+ ZTQ1ZWJhNGNjYjhkMGMyMmViNDYxZDYyOWNjYTg1NGU3NzRiOTE=
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ terraform/
16
+ .idea/
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.0
4
+ - 2.0.0
5
+ deploy:
6
+ provider: rubygems
7
+ gem: rake-terraform
8
+ on:
9
+ tags: true
10
+ all_branches: true
11
+ api_key:
12
+ secure: hOaHuMk5/lcedaCiP/GkICXy+tNS6uHrrkizoFn4Tv5GhWoAao77e4FWuZh9KNSAmiZIQwPa1z5b9kn8Rq2UE0QjrxBYmDFFp5uM4fDl7xzqPXREfZcBNmrjMFUhXSRnyZnm4rC69lGRQKTSJkHZDAUZfWobFMnouMtRyoDSCbU=
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rake-terraform.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Norm MacLennan
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,105 @@
1
+ # rake-terraform
2
+
3
+ [![Build Status](https://travis-ci.org/maclennann/rake-terraform.svg?branch=master)](https://travis-ci.org/maclennann/rake-terraform)
4
+ [![Code Climate](https://codeclimate.com/github/maclennann/rake-terraform/badges/gpa.svg)](https://codeclimate.com/github/maclennann/rake-terraform)
5
+ [![Test Coverage](https://codeclimate.com/github/maclennann/rake-terraform/badges/coverage.svg)](https://codeclimate.com/github/maclennann/rake-terraform)
6
+ [![Gem](https://img.shields.io/gem/dtv/rake-terraform.svg)]()
7
+
8
+ `rake-terraform` is a gem with a collection of rake tasks for working with [Hashicorp Terraform](https://terraform.io)
9
+ and terraform configuration files.
10
+
11
+ It provides tasks to calculate and execute plans based on a variety of file and module structures.
12
+
13
+ Note: This gem was specifically written for use with the AWS terraform provider. If you need to use another one,
14
+ please open an issue and/or file a pull request.
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ ```ruby
21
+ gem 'rake-terraform'
22
+ ```
23
+
24
+ And then execute:
25
+
26
+ $ bundle
27
+
28
+ Or install it yourself as:
29
+
30
+ $ gem install rake-terraform
31
+
32
+ ## Usage
33
+
34
+ This gem currently provides two different types of tasks:
35
+
36
+ ### `terraform_plan`
37
+ This task can be used to calculate plans for a terraform configuration.
38
+
39
+ You can set the following configuration for the task:
40
+
41
+ * `t.input_dir` - the directory from which to read terraform config (default: `./terraform`)
42
+ * `t.output_file` - the path and name of the plan file to generate (default: `./output/terraform/plan.tf`)
43
+ * `t.credentials` - the path of the [AWS credentials file](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#cli-config-files) to read from (default: `~/.aws/credentials`)
44
+ * `t.aws_project` - the name of the project to use from your credentials file (default: `default`)
45
+
46
+ ### `terraform_apply`
47
+ This task can be used to apply a calculated terraform plan.
48
+
49
+ You can set the following configuration for the task:
50
+
51
+ * `t.plan`: The name of the plan file to apply (default: `./output/terraform/plan.tf`)
52
+ * `t.execution_path`: The path from which to execute the plan (default: `./terraform`)
53
+ * This is useful if you are referencing cloud-config files using relative paths
54
+
55
+ To use these tasks, you should `require 'rake_terraform'` at the top of your Rakefile.
56
+
57
+ ### Default Tasks
58
+
59
+ This gem provides a `default_tasks` partial rakefile that should work for most use-cases.
60
+ It includes the concept of terraform 'environments'. This is useful for the AWS provider,
61
+ as terraform can only control one AWS region at a time. Which means a separate Terraform
62
+ configuration needs to be kept per region.
63
+
64
+ To use it, just `require 'rake-terraform/default_tasks'` at the top of your `Rakefile`.
65
+
66
+ Given, the following terraform hierarchy:
67
+ ```bash
68
+ terraform
69
+ us-east-1
70
+ main.tf
71
+ variables.tf
72
+ output.tf
73
+ us-west-1
74
+ main.tf
75
+ variables.tf
76
+ output.tf
77
+ ```
78
+
79
+ It wil automatically generate the following rake tasks:
80
+
81
+ ```bash
82
+ rake terraform:all # Plan and migrate all environments
83
+
84
+ rake terraform:apply_us-east-1 # Execute plan for us-east-1
85
+ rake terraform:apply_us-west-1 # Execute plan for us-west-1
86
+
87
+ rake terraform:plan_us-east-1 # Plan migration of us-east-1
88
+ rake terraform:plan_us-west-1 # Plan migration of us-west-1
89
+
90
+ rake terraform:us-east-1 # Plan and migrate us-east-1
91
+ rake terraform:us-west-1 # Plan and migrate us-west-1
92
+ ```
93
+
94
+ The following environment variables can be set to tweak `default_task`'s behavior:
95
+ * `ENV['TERRAFORM_AWS_PROJECT']` - Sets `t.aws_project` on the `terraform_plan` tasks (default: `default`)
96
+ * `ENV['TERRAFORM_ENVIRONMENT_GLOB']` - Dir glob used to discover terraform environments (default: `terraform/**/*.tf`)
97
+ * `ENV['TERRAFORM_OUTPUT_BASE']` - Directory to which plan files are saved/read. The environment name is appended to this automatically (default: `output/terraform`)
98
+
99
+ ## Contributing
100
+
101
+ 1. Fork it ( https://github.com/maclennann/rake-terraform/fork )
102
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
103
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
104
+ 4. Push to the branch (`git push origin my-new-feature`)
105
+ 5. Create a new Pull Request
@@ -0,0 +1,7 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake-terraform/default_tasks'
3
+ require 'rubocop/rake_task'
4
+
5
+ task default: :rubocop
6
+
7
+ RuboCop::RakeTask.new
@@ -0,0 +1,31 @@
1
+ require 'rake_terraform'
2
+
3
+ namespace :terraform do
4
+ env_glob = ENV['TERRAFORM_ENVIRONMENT_GLOB'] || 'terraform/**/*.tf'
5
+ output_base = ENV['TERRAFORM_OUTPUT_BASE'] || 'output/terraform'
6
+ environments = (Dir.glob env_glob).map { |f| File.dirname f }.uniq
7
+
8
+ environments.each do |env|
9
+ short_name = File.basename env
10
+ plan_path = File.expand_path File.join(output_base, "#{short_name}.tf")
11
+
12
+ desc "Plan migration of #{short_name}"
13
+ terraform_plan "plan_#{short_name}" do |t|
14
+ t.input_dir = env
15
+ t.aws_project = ENV['TERRAFORM_AWS_PROJECT'] || 'default'
16
+ t.output_file = plan_path
17
+ end
18
+
19
+ desc "Execute plan for #{short_name}"
20
+ terraform_apply "apply_#{short_name}" do |t|
21
+ t.plan = plan_path
22
+ t.execution_path = env
23
+ end
24
+
25
+ desc "Plan and migrate #{short_name}"
26
+ task short_name => %W(plan_#{short_name} apply_#{short_name})
27
+ end
28
+
29
+ desc 'Plan and migrate all environments'
30
+ task all: environments.map { |e| File.basename e }.uniq
31
+ end
@@ -0,0 +1,29 @@
1
+ require 'rake'
2
+
3
+ # Rake terraform
4
+ module RakeTerraform
5
+ private
6
+
7
+ # Definitions of methods for custom rake tasks
8
+ module DSL
9
+ def terraform_plan(*args)
10
+ require 'rake-terraform/tasks/plantask'
11
+ Rake::Task.define_task(*args) do
12
+ c = RakeTerraform::PlanTask::Config.new
13
+ yield c
14
+ RakeTerraform::PlanTask::Task.new(c.opts).execute
15
+ end
16
+ end
17
+
18
+ def terraform_apply(*args)
19
+ require 'rake-terraform/tasks/applytask'
20
+ Rake::Task.define_task(*args) do
21
+ c = RakeTerraform::ApplyTask::Config.new
22
+ yield c
23
+ RakeTerraform::ApplyTask::Task.new(c.opts).execute
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ extend RakeTerraform::DSL
@@ -0,0 +1,55 @@
1
+ module RakeTerraform
2
+ module ApplyTask
3
+ # Configuration data for terraform apply task
4
+ class Config
5
+ attr_accessor :plan
6
+ attr_accessor :execution_path
7
+ def initialize
8
+ @plan = File.expand_path(default_plan)
9
+ @execution_path = File.expand_path 'terraform'
10
+ end
11
+
12
+ def opts
13
+ Map.new(plan: @plan,
14
+ execution_path: @execution_path)
15
+ end
16
+
17
+ private
18
+
19
+ def default_plan
20
+ File.join('output', 'terraform', 'plan.tf')
21
+ end
22
+ end
23
+
24
+ # Custom rake task to run `terraform apply`
25
+ class Task < BaseTask
26
+ def initialize(opts)
27
+ @opts = opts
28
+ end
29
+
30
+ def execute
31
+ require 'highline/import'
32
+
33
+ plan = @opts.get(:plan)
34
+ validate_terraform_installed
35
+ ensure_plan_exists plan
36
+
37
+ system "terraform show --module-depth=2 #{plan}"
38
+
39
+ say 'The above changes will be applied to your environment.'
40
+ exit unless agree 'Are you sure you want to execute this plan? (y/n)'
41
+
42
+ Dir.chdir(@opts.get(:execution_path)) do
43
+ system "terraform apply #{plan}"
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def ensure_plan_exists(plan)
50
+ require 'fileutils'
51
+ fail "Plan #{plan} does not exist! Aborting!" unless File.exist? plan
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,29 @@
1
+ require 'rake/task'
2
+ require 'iniparse'
3
+ require 'English'
4
+
5
+ module RakeTerraform
6
+ # Methods that all tasks have in common
7
+ class BaseTask < Rake::Task
8
+ def validate_terraform_installed
9
+ error = 'Please ensure you have terraform installed and on your path!'
10
+ fail error unless terraform_installed?
11
+ end
12
+
13
+ def terraform_installed?
14
+ `terraform version`
15
+ $CHILD_STATUS.success?
16
+ rescue => _
17
+ false
18
+ end
19
+
20
+ def get_aws_credentials(creds_file, project = 'default')
21
+ error = "Could not locate AWS credentials in #{creds_file}!"
22
+ fail error unless File.exist? creds_file
23
+
24
+ credentials = IniParse.parse(File.read(creds_file))
25
+ { accesskey: credentials[project]['aws_access_key_id'],
26
+ secretkey: credentials[project]['aws_secret_access_key'] }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,87 @@
1
+ require 'rake/task'
2
+ require 'rake-terraform/tasks/basetask'
3
+ require 'map'
4
+
5
+ # Custom rake task to perform `terraform plan`
6
+ module RakeTerraform
7
+ module PlanTask
8
+ # Configuration data for terraform plan task
9
+ class Config
10
+ attr_accessor :input_dir
11
+ attr_accessor :output_file
12
+ attr_accessor :credentials
13
+ attr_accessor :aws_project
14
+
15
+ def initialize
16
+ @input_dir = File.expand_path 'terraform'
17
+ @output_file = File.expand_path(default_output)
18
+ @credentials = File.expand_path(default_credentials)
19
+ @aws_project = 'default'
20
+ end
21
+
22
+ def opts
23
+ Map.new(input_dir: @input_dir,
24
+ output_file: @output_file,
25
+ credentials: @credentials,
26
+ aws_project: @aws_project)
27
+ end
28
+
29
+ private
30
+
31
+ def default_output
32
+ File.join('output', 'terraform', 'plan.tf')
33
+ end
34
+
35
+ def default_credentials
36
+ File.join('~', '.aws', 'credentials')
37
+ end
38
+ end
39
+
40
+ # Custom rake task to run `terraform plan`
41
+ class Task < BaseTask
42
+ attr_accessor :creds_file
43
+
44
+ def initialize(opts)
45
+ @creds_file = opts.get(:credentials)
46
+ @opts = opts
47
+ end
48
+
49
+ def execute
50
+ validate_terraform_installed
51
+ ensure_output_directory
52
+
53
+ creds = get_aws_credentials(@creds_file, @opts.get(:aws_project))
54
+
55
+ Dir.chdir(@opts.get(:input_dir)) do
56
+ puts '=> Fetching modules...'
57
+ system('terraform get')
58
+
59
+ command = construct_command creds
60
+ puts "=> Generating plan for #{@opts.get(:input_dir)}..."
61
+ system(command)
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def construct_command(creds)
68
+ access_key = creds[:accesskey]
69
+ secret_key = creds[:secretkey]
70
+
71
+ command = 'terraform plan '
72
+ command << "-var access_key=\"#{access_key}\" "
73
+ command << "-var secret_key=\"#{secret_key}\" "
74
+ command << '-module-depth 2 '
75
+ command << "-out #{@opts.get(:output_file)}" if @opts.get(:output_file)
76
+
77
+ command
78
+ end
79
+
80
+ def ensure_output_directory
81
+ require 'fileutils'
82
+ dir = File.dirname @opts.get(:output_file)
83
+ FileUtils.mkdir_p dir unless File.exist? dir
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,4 @@
1
+ # Version of the gem
2
+ module RakeTerraform
3
+ VERSION = '0.0.3'
4
+ end
@@ -0,0 +1,6 @@
1
+ require 'rake-terraform/version'
2
+ require 'rake-terraform/dsl'
3
+
4
+ # Top-level module
5
+ module RakeTerraform
6
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rake-terraform/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'rake-terraform'
8
+ spec.version = RakeTerraform::VERSION
9
+ spec.authors = ['Norm MacLennan']
10
+ spec.email = ['norm.maclennan@gmail.com']
11
+ spec.summary = 'Rake tasks for use with Terraform.'
12
+ spec.description = 'A collection of rake tasks that can
13
+ be used to plan, apply, and manage
14
+ configurations for Hashicorp Terraform.'
15
+
16
+ spec.homepage = 'https://github.com/maclennann/rake-terraform'
17
+ spec.license = 'MIT'
18
+
19
+ spec.files = `git ls-files -z`.split("\x0")
20
+ spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
21
+ spec.test_files = spec.files.grep(/^(test|spec|features)\//)
22
+ spec.require_paths = ['lib']
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1'
25
+ spec.add_development_dependency 'rubocop', '~> 0.29'
26
+ spec.add_dependency 'rake', '~> 10.0'
27
+ spec.add_dependency 'map', '~> 6.5'
28
+ spec.add_runtime_dependency 'highline', '~> 1.7'
29
+ spec.add_runtime_dependency 'iniparse', '~> 1.3'
30
+ end
metadata ADDED
@@ -0,0 +1,144 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rake-terraform
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Norm MacLennan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubocop
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '0.29'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '0.29'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: map
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '6.5'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '6.5'
69
+ - !ruby/object:Gem::Dependency
70
+ name: highline
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '1.7'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '1.7'
83
+ - !ruby/object:Gem::Dependency
84
+ name: iniparse
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '1.3'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '1.3'
97
+ description: ! "A collection of rake tasks that can\n be used
98
+ to plan, apply, and manage\n configurations for Hashicorp
99
+ Terraform."
100
+ email:
101
+ - norm.maclennan@gmail.com
102
+ executables: []
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - .gitignore
107
+ - .travis.yml
108
+ - Gemfile
109
+ - LICENSE.txt
110
+ - README.md
111
+ - Rakefile
112
+ - lib/rake-terraform/default_tasks.rb
113
+ - lib/rake-terraform/dsl.rb
114
+ - lib/rake-terraform/tasks/applytask.rb
115
+ - lib/rake-terraform/tasks/basetask.rb
116
+ - lib/rake-terraform/tasks/plantask.rb
117
+ - lib/rake-terraform/version.rb
118
+ - lib/rake_terraform.rb
119
+ - rake-terraform.gemspec
120
+ homepage: https://github.com/maclennann/rake-terraform
121
+ licenses:
122
+ - MIT
123
+ metadata: {}
124
+ post_install_message:
125
+ rdoc_options: []
126
+ require_paths:
127
+ - lib
128
+ required_ruby_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ! '>='
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ! '>='
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ requirements: []
139
+ rubyforge_project:
140
+ rubygems_version: 2.4.5
141
+ signing_key:
142
+ specification_version: 4
143
+ summary: Rake tasks for use with Terraform.
144
+ test_files: []