builderator 1.2.3.pre.beta.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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