hashicorptools 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0ab24eab79fce02f1b28ca1d7e814abb904ee653
4
+ data.tar.gz: 3fadbdac2a9c7e0b2ccebe60c4589813d5cd2422
5
+ SHA512:
6
+ metadata.gz: 23d0b87a25e6b091cf0f0d08df8ad6cf030ec35b7c24ff964a1e4e28a14f8f4262dbd6b22ab0dee82aa7eb04d657321d2ad305b8f97d543ad611913756468ce2
7
+ data.tar.gz: ad161180ec14a7cebd6a04d6d3baea0dd5c27b32346177326a1a963de15bc1b94f4ebd3a495dee45443314ed17388855ed20fb827ad10abe9980134769da844d
data/Gemfile ADDED
@@ -0,0 +1,23 @@
1
+ source "http://rubygems.org"
2
+
3
+ # try to slowly migrate to v2 of the aws api
4
+ gem 'aws-sdk', '~> 2'
5
+
6
+ gem 'dynect_rest'
7
+
8
+ gem 'aws-sdk-v1'
9
+ gem 'dotenv'
10
+ gem 'thor'
11
+ gem 'activesupport'
12
+ gem 'byebug'
13
+ gem 'git'
14
+
15
+ # Add dependencies to develop your gem here.
16
+ # Include everything needed to run rake, tests, features, etc.
17
+ group :development do
18
+ gem "rspec", "~> 2.8.0"
19
+ gem "rdoc", "~> 3.12"
20
+ gem "bundler", "~> 1.0"
21
+ gem "jeweler", "~> 2.0.1"
22
+ gem "simplecov", ">= 0"
23
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,119 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activesupport (4.2.4)
5
+ i18n (~> 0.7)
6
+ json (~> 1.7, >= 1.7.7)
7
+ minitest (~> 5.1)
8
+ thread_safe (~> 0.3, >= 0.3.4)
9
+ tzinfo (~> 1.1)
10
+ addressable (2.3.8)
11
+ aws-sdk (2.1.29)
12
+ aws-sdk-resources (= 2.1.29)
13
+ aws-sdk-core (2.1.29)
14
+ jmespath (~> 1.0)
15
+ aws-sdk-resources (2.1.29)
16
+ aws-sdk-core (= 2.1.29)
17
+ aws-sdk-v1 (1.66.0)
18
+ json (~> 1.4)
19
+ nokogiri (>= 1.4.4)
20
+ builder (3.2.2)
21
+ byebug (6.0.2)
22
+ descendants_tracker (0.0.4)
23
+ thread_safe (~> 0.3, >= 0.3.1)
24
+ diff-lcs (1.1.3)
25
+ docile (1.1.5)
26
+ domain_name (0.5.25)
27
+ unf (>= 0.0.5, < 1.0.0)
28
+ dotenv (2.0.1)
29
+ dynect_rest (0.4.6)
30
+ rest-client
31
+ faraday (0.9.1)
32
+ multipart-post (>= 1.2, < 3)
33
+ git (1.2.9.1)
34
+ github_api (0.12.3)
35
+ addressable (~> 2.3)
36
+ descendants_tracker (~> 0.0.4)
37
+ faraday (~> 0.8, < 0.10)
38
+ hashie (>= 3.3)
39
+ multi_json (>= 1.7.5, < 2.0)
40
+ nokogiri (~> 1.6.3)
41
+ oauth2
42
+ hashie (3.4.1)
43
+ highline (1.7.2)
44
+ http-cookie (1.0.2)
45
+ domain_name (~> 0.5)
46
+ i18n (0.7.0)
47
+ jeweler (2.0.1)
48
+ builder
49
+ bundler (>= 1.0)
50
+ git (>= 1.2.5)
51
+ github_api
52
+ highline (>= 1.6.15)
53
+ nokogiri (>= 1.5.10)
54
+ rake
55
+ rdoc
56
+ jmespath (1.1.3)
57
+ json (1.8.3)
58
+ jwt (1.5.0)
59
+ mime-types (2.6.2)
60
+ mini_portile (0.6.2)
61
+ minitest (5.8.1)
62
+ multi_json (1.11.0)
63
+ multi_xml (0.5.5)
64
+ multipart-post (2.0.0)
65
+ netrc (0.11.0)
66
+ nokogiri (1.6.6.2)
67
+ mini_portile (~> 0.6.0)
68
+ oauth2 (1.0.0)
69
+ faraday (>= 0.8, < 0.10)
70
+ jwt (~> 1.0)
71
+ multi_json (~> 1.3)
72
+ multi_xml (~> 0.5)
73
+ rack (~> 1.2)
74
+ rack (1.6.1)
75
+ rake (10.4.2)
76
+ rdoc (3.12.2)
77
+ json (~> 1.4)
78
+ rest-client (1.8.0)
79
+ http-cookie (>= 1.0.2, < 2.0)
80
+ mime-types (>= 1.16, < 3.0)
81
+ netrc (~> 0.7)
82
+ rspec (2.8.0)
83
+ rspec-core (~> 2.8.0)
84
+ rspec-expectations (~> 2.8.0)
85
+ rspec-mocks (~> 2.8.0)
86
+ rspec-core (2.8.0)
87
+ rspec-expectations (2.8.0)
88
+ diff-lcs (~> 1.1.2)
89
+ rspec-mocks (2.8.0)
90
+ simplecov (0.10.0)
91
+ docile (~> 1.1.0)
92
+ json (~> 1.8)
93
+ simplecov-html (~> 0.10.0)
94
+ simplecov-html (0.10.0)
95
+ thor (0.19.1)
96
+ thread_safe (0.3.5)
97
+ tzinfo (1.2.2)
98
+ thread_safe (~> 0.1)
99
+ unf (0.1.4)
100
+ unf_ext
101
+ unf_ext (0.0.7.1)
102
+
103
+ PLATFORMS
104
+ ruby
105
+
106
+ DEPENDENCIES
107
+ activesupport
108
+ aws-sdk (~> 2)
109
+ aws-sdk-v1
110
+ bundler (~> 1.0)
111
+ byebug
112
+ dotenv
113
+ dynect_rest
114
+ git
115
+ jeweler (~> 2.0.1)
116
+ rdoc (~> 3.12)
117
+ rspec (~> 2.8.0)
118
+ simplecov
119
+ thor
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 ChangeSprout Inc.
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 all
13
+ 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 THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # hashicorptools
2
+ a set of ruby utilities for interacting with and wrapping packer, terraform and amazon web services.
3
+
4
+ ## ec2_host
5
+
6
+ Allows quick lookup and ssh to machines by role and environment. Queries for instances by AWS tags.
7
+
8
+ ## packer wrapper
9
+
10
+ Wraps the packer product from hashicorp with standard configuration.
11
+
12
+ ## terraform wrapper
13
+
14
+ Wraps the terraform product from hashicorp with standard conventions for encrypting tfstate and segmenting production
15
+ and staging environments.
16
+
17
+
18
+ Copyright (c) 2015 ChangeSprout Inc. See LICENSE for
19
+ further details.
20
+
21
+
data/Rakefile ADDED
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
17
+ gem.name = "hashicorptools"
18
+ gem.homepage = "http://github.com/woodhull/hashicorptools"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Wrappers for terraform and packer}
21
+ gem.description = %Q{Wrappers for terraform and packer}
22
+ gem.email = "systems@controlshiftlabs.com"
23
+ gem.authors = ["Nathan Woodhull"]
24
+ gem.executables = ['ec2_host']
25
+ # dependencies defined in Gemfile
26
+ end
27
+ Jeweler::RubygemsDotOrgTasks.new
28
+
29
+ require 'rspec/core'
30
+ require 'rspec/core/rake_task'
31
+ RSpec::Core::RakeTask.new(:spec) do |spec|
32
+ spec.pattern = FileList['spec/**/*_spec.rb']
33
+ end
34
+
35
+ desc "Code coverage detail"
36
+ task :simplecov do
37
+ ENV['COVERAGE'] = "true"
38
+ Rake::Task['spec'].execute
39
+ end
40
+
41
+ task :default => :spec
42
+
43
+ require 'rdoc/task'
44
+ Rake::RDocTask.new do |rdoc|
45
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
46
+
47
+ rdoc.rdoc_dir = 'rdoc'
48
+ rdoc.title = "hashicorptools #{version}"
49
+ rdoc.rdoc_files.include('README*')
50
+ rdoc.rdoc_files.include('lib/**/*.rb')
51
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.3
data/bin/ec2_host ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'hashicorptools'
4
+
5
+ Dotenv.load
6
+
7
+ Hashicorptools::Host.start(ARGV)
@@ -0,0 +1,48 @@
1
+ {
2
+ "variables": {
3
+ "aws_access_key": "",
4
+ "aws_secret_key": "",
5
+ "source_ami": "",
6
+ "ami_tag": "",
7
+ "cookbook_name": ""
8
+ },
9
+
10
+ "builders": [
11
+ {
12
+ "type": "amazon-ebs",
13
+ "access_key": "{{user `aws_access_key`}}",
14
+ "secret_key": "{{user `aws_secret_key`}}",
15
+ "region": "us-east-1",
16
+ "source_ami": "{{user `source_ami`}}",
17
+ "instance_type": "c4.large",
18
+ "ssh_username": "ubuntu",
19
+ "ami_name": "{{user `ami_tag`}} {{timestamp}}",
20
+ "tags": {
21
+ "Name": "{{user `ami_tag`}}",
22
+ "{{user `ami_tag`}}": "{{timestamp}}",
23
+ "created_at": "{{isotime}}",
24
+ "parent_ami": "{{user `source_ami`}}"
25
+ },
26
+ "run_tags": {
27
+ "kind": "packer",
28
+ "role": "AMI builder"
29
+ },
30
+ "launch_block_device_mappings": [{
31
+ "device_name": "/dev/sda1",
32
+ "volume_size": 8,
33
+ "volume_type": "gp2",
34
+ "delete_on_termination": true
35
+ }]
36
+ }
37
+ ],
38
+ "provisioners": [
39
+ {
40
+ "type": "chef-solo",
41
+ "cookbook_paths": ["cookbooks", "site-cookbooks"],
42
+ "run_list": ["{{user `cookbook_name`}}"],
43
+ "skip_install": true,
44
+ "data_bags_path": "data_bags",
45
+ "encrypted_data_bag_secret_path": "/etc/chef/encrypted_data_bag_secret"
46
+ }
47
+ ]
48
+ }
@@ -0,0 +1,97 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: hashicorptools 0.0.3 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "hashicorptools"
9
+ s.version = "0.0.3"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
13
+ s.authors = ["Nathan Woodhull"]
14
+ s.date = "2015-12-21"
15
+ s.description = "Wrappers for terraform and packer"
16
+ s.email = "systems@controlshiftlabs.com"
17
+ s.executables = ["ec2_host"]
18
+ s.extra_rdoc_files = [
19
+ "LICENSE",
20
+ "README.md"
21
+ ]
22
+ s.files = [
23
+ "Gemfile",
24
+ "Gemfile.lock",
25
+ "LICENSE",
26
+ "README.md",
27
+ "Rakefile",
28
+ "VERSION",
29
+ "bin/ec2_host",
30
+ "data/standard-ami.json",
31
+ "hashicorptools.gemspec",
32
+ "lib/hashicorptools.rb",
33
+ "lib/hashicorptools/auto_scaling_group.rb",
34
+ "lib/hashicorptools/code_deploy.rb",
35
+ "lib/hashicorptools/ec2_utilities.rb",
36
+ "lib/hashicorptools/host.rb",
37
+ "lib/hashicorptools/packer.rb",
38
+ "lib/hashicorptools/terraform.rb",
39
+ "lib/hashicorptools/update_launch_configuration.rb",
40
+ "lib/hashicorptools/variables.rb",
41
+ "spec/hashicorptools_spec.rb",
42
+ "spec/spec_helper.rb"
43
+ ]
44
+ s.homepage = "http://github.com/woodhull/hashicorptools"
45
+ s.licenses = ["MIT"]
46
+ s.rubygems_version = "2.4.8"
47
+ s.summary = "Wrappers for terraform and packer"
48
+
49
+ if s.respond_to? :specification_version then
50
+ s.specification_version = 4
51
+
52
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
53
+ s.add_runtime_dependency(%q<aws-sdk>, ["~> 2"])
54
+ s.add_runtime_dependency(%q<dynect_rest>, [">= 0"])
55
+ s.add_runtime_dependency(%q<aws-sdk-v1>, [">= 0"])
56
+ s.add_runtime_dependency(%q<dotenv>, [">= 0"])
57
+ s.add_runtime_dependency(%q<thor>, [">= 0"])
58
+ s.add_runtime_dependency(%q<activesupport>, [">= 0"])
59
+ s.add_runtime_dependency(%q<byebug>, [">= 0"])
60
+ s.add_runtime_dependency(%q<git>, [">= 0"])
61
+ s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
62
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
63
+ s.add_development_dependency(%q<bundler>, ["~> 1.0"])
64
+ s.add_development_dependency(%q<jeweler>, ["~> 2.0.1"])
65
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
66
+ else
67
+ s.add_dependency(%q<aws-sdk>, ["~> 2"])
68
+ s.add_dependency(%q<dynect_rest>, [">= 0"])
69
+ s.add_dependency(%q<aws-sdk-v1>, [">= 0"])
70
+ s.add_dependency(%q<dotenv>, [">= 0"])
71
+ s.add_dependency(%q<thor>, [">= 0"])
72
+ s.add_dependency(%q<activesupport>, [">= 0"])
73
+ s.add_dependency(%q<byebug>, [">= 0"])
74
+ s.add_dependency(%q<git>, [">= 0"])
75
+ s.add_dependency(%q<rspec>, ["~> 2.8.0"])
76
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
77
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
78
+ s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
79
+ s.add_dependency(%q<simplecov>, [">= 0"])
80
+ end
81
+ else
82
+ s.add_dependency(%q<aws-sdk>, ["~> 2"])
83
+ s.add_dependency(%q<dynect_rest>, [">= 0"])
84
+ s.add_dependency(%q<aws-sdk-v1>, [">= 0"])
85
+ s.add_dependency(%q<dotenv>, [">= 0"])
86
+ s.add_dependency(%q<thor>, [">= 0"])
87
+ s.add_dependency(%q<activesupport>, [">= 0"])
88
+ s.add_dependency(%q<byebug>, [">= 0"])
89
+ s.add_dependency(%q<git>, [">= 0"])
90
+ s.add_dependency(%q<rspec>, ["~> 2.8.0"])
91
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
92
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
93
+ s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
94
+ s.add_dependency(%q<simplecov>, [">= 0"])
95
+ end
96
+ end
97
+
@@ -0,0 +1,149 @@
1
+ require "timeout"
2
+
3
+ module Hashicorptools
4
+ class AutoScalingGroup
5
+ attr_accessor :name
6
+
7
+ def initialize(attrs = {})
8
+ attrs.each do |key,value|
9
+ if self.respond_to?("#{key}=")
10
+ self.send("#{key}=", value)
11
+ end
12
+ end
13
+ end
14
+
15
+ def set_desired_instances(desired_instances)
16
+ puts "updating size of #{name} to #{desired_instances}"
17
+ autoscaling.set_desired_capacity({auto_scaling_group_name: name, desired_capacity: desired_instances, honor_cooldown: false })
18
+
19
+ # wait for the instance count to be correct.
20
+ wait_until do
21
+ current_size = group.instances.size
22
+ puts "asg currently has #{current_size} instances"
23
+ current_size == desired_instances
24
+ end
25
+
26
+ puts "waiting for scaling events to finish"
27
+ groups.each do |group|
28
+ wait_for_activities_to_complete(group)
29
+ end
30
+ puts "all #{desired_instances} scaling activities successful."
31
+ wait_until_instances_ready
32
+ puts "all #{desired_instances} instances ready."
33
+ end
34
+
35
+ def wait_until_instances_ready
36
+ wait_until do
37
+ group.instances.any?
38
+ end
39
+
40
+ pending_instance_ids = group.instances.find_all{|i| ['Pending', 'Pending:Wait', 'Pending:Proceed'].include?(i.lifecycle_state) }.collect{|i| i.instance_id}
41
+ shutting_down_ids = group.instances.find_all{|i| ['Terminating', 'Terminating:Wait', 'Terminating:Proceed'].include?(i.lifecycle_state) }.collect{|i| i.instance_id}
42
+
43
+ ec2.wait_until(:instance_running, instance_ids: pending_instance_ids) if pending_instance_ids.any?
44
+ ec2.wait_until(:instance_terminated, instance_ids: shutting_down_ids) if shutting_down_ids.any?
45
+
46
+ # now that all of the instances starting up / shutting down have settled, we can verify that running instances are healthy.
47
+ puts "waiting for instance status checks to pass.."
48
+ wait_until do
49
+ puts "checking instance statuses"
50
+ resp = ec2.describe_instance_status(instance_ids: group.instances.collect{|i| i.instance_id})
51
+ resp.instance_statuses.all?{|s| s.system_status.status == 'ok'}
52
+ end
53
+
54
+ puts "waiting for ELB health checks to pass..."
55
+ wait_until do
56
+ all_load_balancers_at_full_health?
57
+ end
58
+
59
+ wait_for_activities_to_complete(group)
60
+ end
61
+
62
+ def group
63
+ groups.first
64
+ end
65
+
66
+ def all_load_balancers_at_full_health?
67
+ names = group.load_balancer_names
68
+ names.each do |lb_name|
69
+ puts "checking health of instances in #{lb_name}"
70
+ inst_health = elb.describe_instance_health({load_balancer_name: lb_name})
71
+ unless inst_health.instance_states.all?{|inst| inst.state == 'InService'}
72
+ return false
73
+ end
74
+ end
75
+ return true
76
+ end
77
+
78
+ def delete!
79
+ groups.each do |group|
80
+ wait_for_instances_to_delete(group)
81
+
82
+ autoscaling.delete_auto_scaling_group(auto_scaling_group_name: group.auto_scaling_group_name)
83
+ puts "waiting for #{group.auto_scaling_group_name} to delete"
84
+
85
+ wait_until do
86
+ autoscaling.describe_auto_scaling_groups(auto_scaling_group_names: [group.auto_scaling_group_name]).auto_scaling_groups.empty?
87
+ end
88
+ autoscaling.delete_launch_configuration(launch_configuration_name: group.launch_configuration_name)
89
+ end
90
+ end
91
+
92
+ private
93
+
94
+ def wait_for_activities_to_complete(group)
95
+ autoscaling.describe_scaling_activities(auto_scaling_group_name: group.auto_scaling_group_name).activities.each do |activity|
96
+ unless activity.status_code == 'Successful' || activity.status_code == 'Failed' || activity.status_code == 'Cancelled'
97
+ puts "waiting for #{activity.status_code} activity to finish: #{activity.description}..."
98
+ wait_until(6000) do
99
+ activity = autoscaling.describe_scaling_activities(auto_scaling_group_name: group.auto_scaling_group_name, activity_ids: [activity.activity_id]).activities.first
100
+ puts "#{activity.status_code}"
101
+ activity.status_code == 'Successful' || activity.status_code == 'Failed' || activity.status_code == 'Cancelled'
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ def autoscaling
108
+ @autoscaling ||= Aws::AutoScaling::Client.new(region: 'us-east-1')
109
+ end
110
+
111
+ def ec2
112
+ @ec2 ||= Aws::EC2::Client.new(region: 'us-east-1')
113
+ end
114
+
115
+ def elb
116
+ @elb ||= Aws::ElasticLoadBalancing::Client.new(region: 'us-east-1')
117
+ end
118
+
119
+ def groups
120
+ autoscaling.describe_auto_scaling_groups(auto_scaling_group_names: [name]).auto_scaling_groups
121
+ end
122
+
123
+ def wait_for_instances_to_delete(group)
124
+ autoscaling.update_auto_scaling_group(auto_scaling_group_name: group.auto_scaling_group_name, min_size: 0, max_size: 0, desired_capacity: 0)
125
+ instance_ids = group.instances.collect{|i| i.instance_id}
126
+ puts "waiting for #{name} to empty"
127
+ ec2.wait_until(:instance_terminated, instance_ids: instance_ids) if instance_ids.any?
128
+
129
+ wait_until do
130
+ autoscaling.describe_auto_scaling_groups(auto_scaling_group_names: [group.auto_scaling_group_name]).auto_scaling_groups.first.instances.empty?
131
+ end
132
+
133
+ wait_for_activities_to_complete(group)
134
+ end
135
+
136
+ def wait_until(max_time=420)
137
+ Timeout.timeout(max_time) do
138
+ seconds_to_sleep = 10
139
+
140
+ until value = yield do
141
+ sleep(seconds_to_sleep)
142
+ seconds_to_sleep *= 3
143
+ end
144
+
145
+ value
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'aws-sdk'
4
+ require 'dotenv'
5
+ require 'git'
6
+ require 'logger'
7
+ require 'thor'
8
+
9
+ module Hashicorptools
10
+ class CodeDeploy < Thor
11
+
12
+ desc 'deploy', 'deploy latest code to environment'
13
+ option :environment, :required => true
14
+ option :branch, default: 'master'
15
+ option :commit
16
+ def deploy
17
+ g = Git.open('..')
18
+
19
+ commit = if options[:commit].present?
20
+ g.gcommit(options[:commit])
21
+ else
22
+ g.checkout(options[:branch].to_sym)
23
+ g.log.first
24
+ end
25
+
26
+
27
+ puts "deploying commit: #{commit.sha} #{commit.message}"
28
+
29
+ create_deployment(commit.sha, commit.message)
30
+ end
31
+
32
+ private
33
+
34
+ def create_deployment(commit_id, commit_message = nil)
35
+ Dotenv.load
36
+
37
+ client = Aws::CodeDeploy::Client.new
38
+ response = client.create_deployment({
39
+ application_name: application_name,
40
+ deployment_group_name: "#{application_name}-#{options[:environment]}",
41
+ revision: {
42
+ revision_type: 'GitHub',
43
+ git_hub_location: {
44
+ repository: "controlshift/#{application_name}",
45
+ commit_id: commit_id
46
+ }
47
+ },
48
+ description: (commit_message || "commit #{commit_id}").slice(0,99)
49
+ })
50
+ puts "created deployment #{response.deployment_id}"
51
+ puts "https://console.aws.amazon.com/codedeploy/home?region=#{ENV['AWS_REGION']}#/deployments/#{response.deployment_id}"
52
+ end
53
+
54
+ def application_name
55
+ raise "implement me"
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,37 @@
1
+ module Hashicorptools
2
+ module Ec2Utilities
3
+ def current_ami(tag = tag_name)
4
+ amis(tag).first
5
+ end
6
+
7
+ def amis(tag = tag_name)
8
+ sort_by_created_at( ec2.images.with_owner('self').tagged(tag).to_a, tag )
9
+ end
10
+
11
+ def ec2
12
+ ec2 = AWS::EC2.new
13
+ end
14
+
15
+ def vpc_with_name(name)
16
+ vpcs = ec2.client.describe_vpcs({filters: [{name: 'tag:Name', values: [name]}]}).vpc_set
17
+ vpcs.first
18
+ end
19
+
20
+ def internet_gateway_for_vpc(vpc_id)
21
+ igs = ec2.client.describe_internet_gateways({filters: [{name: 'attachment.vpc-id', values: [vpc_id]}]}).internet_gateway_set
22
+ igs.first
23
+ end
24
+
25
+ def image_created_at(image, tag= tag_name)
26
+ if image
27
+ image.tags.to_h[tag].to_i
28
+ else
29
+ 0
30
+ end
31
+ end
32
+
33
+ def sort_by_created_at(collection, tag = tag_name)
34
+ collection.sort{|a, b| self.image_created_at(b, tag) <=> self.image_created_at(a, tag) }
35
+ end
36
+ end
37
+ end