builderator 1.2.3.pre.beta.1 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 83b75ce26deeb6612ec531be9a548b2b5c43f412
4
- data.tar.gz: 1622ca8922bb3596167b1341d3f170ec3feba4e5
3
+ metadata.gz: 710962f091dbc4e8bdb78702764f537c5205d7bb
4
+ data.tar.gz: fb314bfd5f1aa4b35bb2204cb6def699ccc5030f
5
5
  SHA512:
6
- metadata.gz: 16cc1d59457a54b2b86e6ae401b1d870fbb768ae3d61aae10a024a1da7927ef444d7721f1423edef5fa6fe9099ef2159c317766340f02a23d827bc7bf6783203
7
- data.tar.gz: 6d1e30012ec43092c5cd1c3bdab195b1fdc4f6776840367c4b97dbdd7e2630dac6e4a3bc35467f18f25a19c53a6b3b8440e156184fe417619819c0f593b327c0
6
+ metadata.gz: 338681e36782e334d7e08bf6f463fafda8f186f11679b2d81dfdff03423a79d36094279b5987c28b270f16d1f18ec4276797bfd5368dd6c87e21fd824cef4070
7
+ data.tar.gz: 436d1936dccd2f2902aa8a2fbfe9ac564c07424df435314464575a082d4364d695c40c725e55b9c7b2c87c3a71de2bf84d3a89fc3de2fbaa8585a39630e58868
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Builderator
1
+ # Builderator [![Build Status](https://api.travis-ci.org/rapid7/builderator.svg?branch=master)](https://travis-ci.org/rapid7/builderator)
2
2
 
3
3
  Orchestration and configuration of the code development life-cycle.
4
4
 
@@ -262,6 +262,10 @@ module Builderator
262
262
  attribute :ami_users, :type => :list
263
263
  attribute :ami_regions, :type => :list
264
264
 
265
+ # Tagging
266
+ attribute :run_tags, :type => :hash
267
+ attribute :run_volume_tags, :type => :hash
268
+
265
269
  ## Assumable role for tagging AMIs in remote accounts
266
270
  attribute :tagging_role
267
271
  end
@@ -15,6 +15,7 @@ module Builderator
15
15
  class Packer < Interface
16
16
  command 'packer'
17
17
  attr_reader :packerfile
18
+ attr_reader :security_group_id
18
19
 
19
20
  def initialize(*_)
20
21
  super
@@ -60,6 +61,25 @@ module Builderator
60
61
  # This is not directly supported by Packer
61
62
  build_hash.delete(:tagging_role)
62
63
 
64
+ # Use a security group that doesn't suck if user didn't specify.
65
+ # Note that @security_group_id in this class will only ever be the one created here,
66
+ # and will be nil if the user specified their own
67
+ if build_hash.key?(:security_group_ids)
68
+ puts "Using SecurityGroups #{build_hash[:security_group_ids]}"
69
+ elsif build_hash.key?(:security_group_id)
70
+ puts "Using SecurityGroup #{build_hash[:security_group_id]}"
71
+ else
72
+ @security_group_id = Util.get_security_group_id(build_hash[:region])
73
+ build_hash[:security_group_id] = @security_group_id
74
+
75
+ # Delete the security group created above when on builderator exit.
76
+ # Note that for an unclean exit in which the instance was NOT terminated,
77
+ # Amazon will refuse to delete the security group, as it is still attached
78
+ # to an existing instance. This is unfortunate, but is equivalent to packer's
79
+ # default behavior except that now you'll get an exception from aws-sdk.
80
+ at_exit { Util.remove_security_group(build_hash[:region], @security_group_id) }
81
+ end
82
+
63
83
  json[:builders] << build_hash
64
84
  end
65
85
 
@@ -82,6 +82,12 @@ class Thor
82
82
  end
83
83
  end
84
84
 
85
+ alias_method :thor_run, :run
86
+ def run(command, config = {})
87
+ thor_run(command, config)
88
+ fail "Command failed: #{command}" if $?.exitstatus != 0
89
+ end
90
+
85
91
  ##
86
92
  # Make `template` load from a sane path and render in the context of Config
87
93
  ##
@@ -1,5 +1,6 @@
1
1
  require 'aws-sdk'
2
2
  require 'thor'
3
+ require 'retryable'
3
4
 
4
5
  require_relative '../control/data'
5
6
  require_relative '../interface/packer'
@@ -47,7 +48,7 @@ module Builderator
47
48
 
48
49
  build.ami_regions.each do |region|
49
50
  say_status :copy, "image #{image_name} (#{image.image_id}) from #{Config.aws.region} to #{region}"
50
- Util.ec2(region).copy_image(parameters)
51
+ copy_image(region, parameters)
51
52
  end
52
53
  end
53
54
 
@@ -61,11 +62,6 @@ module Builderator
61
62
  invoke :configure, [profile], options
62
63
 
63
64
  images.each do |image_name, (image, build)|
64
- filters = [{
65
- :name => 'name',
66
- :values => [image_name]
67
- }]
68
-
69
65
  ## Add some additional tags about the regional source
70
66
  image.tags << {
71
67
  :key => 'source_region',
@@ -77,7 +73,7 @@ module Builderator
77
73
  }
78
74
 
79
75
  build.ami_regions.each do |region|
80
- regional_image = Util.ec2(region).describe_images(:filters => filters).images.first
76
+ regional_image = find_image(region, image_name)
81
77
 
82
78
  say_status :tag, "AMI #{image_name} (#{regional_image.image_id}) in #{region}"
83
79
  Util.ec2(region).create_tags(:resources => [regional_image.image_id], :tags => image.tags)
@@ -99,13 +95,8 @@ module Builderator
99
95
  waiting = false
100
96
 
101
97
  images.each do |image_name, (image, build)|
102
- filters = [{
103
- :name => 'name',
104
- :values => [image_name]
105
- }]
106
-
107
98
  build.ami_regions.each do |region|
108
- regional_image = Util.ec2(region).describe_images(:filters => filters).images.first
99
+ regional_image = find_image(region, image_name)
109
100
 
110
101
  ## It takes a few seconds for the new AMI to show up in the `describe_images` response-set
111
102
  state = regional_image.nil? ? 'unknown' : regional_image.state
@@ -123,7 +114,7 @@ module Builderator
123
114
  end
124
115
 
125
116
  ## If waiting == false, loop immediately to break
126
- sleep(10) if waiting
117
+ sleep(20) if waiting
127
118
  end
128
119
 
129
120
  say_status :complete, 'All copied images are available'
@@ -143,17 +134,12 @@ module Builderator
143
134
 
144
135
  sts_client = Aws::STS::Client.new(region: region)
145
136
 
146
- filters = [{
147
- :name => 'name',
148
- :values => [image_name]
149
- }]
150
-
151
137
  if build.tagging_role.nil?
152
138
  say_status :complete, 'No remote tagging to be performed as no IAM role is defined'
153
139
  return
154
140
  end
155
141
 
156
- regional_image = Util.ec2(region).describe_images(:filters => filters).images.first
142
+ regional_image = find_image(region, image_name)
157
143
 
158
144
  build.ami_users.each do |account|
159
145
  role_arn = "arn:aws:iam::#{account}:role/#{build.tagging_role}"
@@ -187,12 +173,7 @@ module Builderator
187
173
  build.ami_users.each do |user|
188
174
  shared = true
189
175
 
190
- filters = [{
191
- :name => 'name',
192
- :values => [image_name]
193
- }]
194
-
195
- regional_image = Util.ec2(region).describe_images(:filters => filters).images.first
176
+ regional_image = find_image(region, image_name)
196
177
 
197
178
  say_status :share, "image #{image_name} (#{regional_image.image_id}) with #{user}"
198
179
 
@@ -222,6 +203,27 @@ module Builderator
222
203
  memo[build.ami_name] = [Control::Data.lookup(:image, :name => build.ami_name).first, build]
223
204
  end
224
205
  end
206
+
207
+ def copy_image(region, params)
208
+ Retryable.retryable(:sleep => lambda { |n| 4**n }, :tries => 4, :on => [Aws::EC2::Errors::ServiceError]) do |retries, _|
209
+ say_status :error, 'Error copying image', :red if retries.positive?
210
+ Util.ec2(region).copy_image(params)
211
+ end
212
+ end
213
+
214
+ def find_image(region, image_name)
215
+ filters = [{
216
+ :name => 'name',
217
+ :values => [image_name]
218
+ }]
219
+
220
+ image = nil
221
+ Retryable.retryable(:sleep => lambda { |n| 4**n }, :tries => 4, :on => [Aws::EC2::Errors::ServiceError]) do |retries, _|
222
+ say_status :error, 'Error finding image', :red if retries.positive?
223
+ image = Util.ec2(region).describe_images(:filters => filters).images.first
224
+ end
225
+ image
226
+ end
225
227
  end
226
228
  end
227
229
  end
@@ -19,7 +19,7 @@ module Builderator
19
19
  desc 'current', 'Print the current version and write it to file'
20
20
  def current
21
21
  unless Config.autoversion.search_tags
22
- say_status :disabled, 'Automatically detecting version informantion '\
22
+ say_status :disabled, 'Automatically detecting version information '\
23
23
  'from SCM tags is disabled', :red
24
24
  return
25
25
  end
@@ -79,6 +79,52 @@ module Builderator
79
79
  clients["asg-#{region}"] ||= Aws::AutoScaling::Client.new(:region => region)
80
80
  end
81
81
 
82
+ def remove_security_group(region = Config.aws.region, group_id = nil)
83
+ if region.nil?
84
+ puts "Dry-run; skipping delete of group_id #{group_id}"
85
+ return
86
+ end
87
+ if group_id.nil?
88
+ puts "Not removing security group"
89
+ return
90
+ end
91
+ ec2 = ec2(region)
92
+ resp = ec2.delete_security_group(group_id: group_id)
93
+ puts "Deleted SecurityGroup #{group_id}"
94
+ end
95
+
96
+ def get_security_group_id(region = Config.aws.region)
97
+ group_id = nil
98
+ if region.nil?
99
+ group_id = 'sg-DRYRUNSG'
100
+ puts "Dry-run; skipping create and returning #{group_id}"
101
+ return group_id
102
+ end
103
+ ec2 = ec2(region)
104
+ group = nil
105
+ require 'open-uri'
106
+ external_ip = open('http://checkip.amazonaws.com').read.strip
107
+ cidr_ip = external_ip + '/32'
108
+
109
+ # Create a security group
110
+ resp = ec2.create_security_group(group_name: "BuilderatorSecurityGroupSSHOnly-#{Time.now.to_i}",
111
+ description: "Created by Builderator at #{Time.now}")
112
+ group_id = resp[:group_id]
113
+
114
+ resp = ec2.describe_security_groups(group_ids: [group_id])
115
+ groups = resp[:security_groups]
116
+ group = groups.first
117
+
118
+ # Ensure the group_id has the right permissions
119
+ resp = ec2.authorize_security_group_ingress(group_id: group_id,
120
+ ip_protocol: 'tcp',
121
+ from_port: 22,
122
+ to_port: 22,
123
+ cidr_ip: cidr_ip)
124
+ puts "Created SecurityGroup #{group_id}"
125
+ group_id
126
+ end
127
+
82
128
  private
83
129
 
84
130
  def clients
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: builderator
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.3.pre.beta.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Manero
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-03 00:00:00.000000000 Z
11
+ date: 2017-06-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -178,6 +178,20 @@ dependencies:
178
178
  - - "~>"
179
179
  - !ruby/object:Gem::Version
180
180
  version: 0.19.0
181
+ - !ruby/object:Gem::Dependency
182
+ name: retryable
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: 2.0.4
188
+ type: :runtime
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: 2.0.4
181
195
  description: Builderator automates many of the common steps required to build VMs
182
196
  and images with Chef. It provides a common configuration layer for Chef, Berkshelf,
183
197
  Vagrant, and Packer, and tasks to orchestrate the usage of each. https://github.com/rapid7/builderator
@@ -260,9 +274,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
260
274
  version: '0'
261
275
  required_rubygems_version: !ruby/object:Gem::Requirement
262
276
  requirements:
263
- - - ">"
277
+ - - ">="
264
278
  - !ruby/object:Gem::Version
265
- version: 1.3.1
279
+ version: '0'
266
280
  requirements: []
267
281
  rubyforge_project:
268
282
  rubygems_version: 2.5.2