stemcell 0.9.0 → 0.10.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 +5 -13
- data/.travis.yml +4 -2
- data/CHANGELOG.md +3 -1
- data/Gemfile +1 -2
- data/Rakefile +1 -1
- data/lib/stemcell/launcher.rb +130 -46
- data/lib/stemcell/option_parser.rb +33 -0
- data/lib/stemcell/version.rb +1 -1
- data/spec/lib/stemcell/launcher_spec.rb +34 -7
- data/spec/lib/stemcell/metadata_source_spec.rb +6 -6
- data/spec/lib/stemcell/option_parser_spec.rb +13 -0
- data/spec/spec_helper.rb +1 -2
- data/stemcell.gemspec +6 -1
- metadata +36 -27
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
Y2FhMDhjNGUwNGFlZGU0YTkwY2RiNTliNTZlYTc5MTU1ZjhkNGNjNQ==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 871924c8a955cfdba26317f7f7dcff52dea5a958
|
4
|
+
data.tar.gz: e62ab6445f2a240a52dd6ccff12861d1c51f6e0a
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
Zjg1NTcyYTYwZjQ5ZWI1NDIzNjM4NmYyZjBkZGFlYzVlYzA5YzQ2Y2ZkM2Y3
|
11
|
-
Y2UwNzI5NjI2OWE5ZTdiM2VmOTlmNzA2NmY2YzY5M2E0OTg3MDc=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
ODNlNGRlYjQ0MWIyMGVhODg2ZDliMTgzYTQ4ZTI3ZWFmYzJkMGNmYmQzYTE2
|
14
|
-
NzQ4NjZhNjc5NWU4MmYwOGNhMTFkOWExYTVlNTg3OGQ5YTA4Yjg4OTgyYjZi
|
15
|
-
MTk4N2RlMTc0OWY1MzE1ODEyY2JmN2YxOTJhZGY4OTRkY2Q5ZjY=
|
6
|
+
metadata.gz: 60a1f87a3a1316ce5efbea9f5e582b23819ac09580494f031d05379009a8dcdcbd0e94e4c12d9afee3dd8c9649bae5e9665ea97347ee2c5fdcb76bc946732983
|
7
|
+
data.tar.gz: 990eddea2e886dcbef2859b706d4e04af931527da6bdbde3688a35633bde7203d0765f132f2ca90e70bfda2feebb9a7e8c6513cc5efeedac1d7149ac44b6fddf
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/Rakefile
CHANGED
data/lib/stemcell/launcher.rb
CHANGED
@@ -8,11 +8,8 @@ require "stemcell/option_parser"
|
|
8
8
|
|
9
9
|
module Stemcell
|
10
10
|
class Launcher
|
11
|
-
|
12
11
|
REQUIRED_OPTIONS = [
|
13
|
-
'
|
14
|
-
'aws_secret_key',
|
15
|
-
'region'
|
12
|
+
'region',
|
16
13
|
]
|
17
14
|
|
18
15
|
REQUIRED_LAUNCH_PARAMETERS = [
|
@@ -53,8 +50,10 @@ module Stemcell
|
|
53
50
|
'security_groups',
|
54
51
|
'security_group_ids',
|
55
52
|
'tags',
|
53
|
+
'classic_link',
|
56
54
|
'iam_role',
|
57
55
|
'ebs_optimized',
|
56
|
+
'termination_protection',
|
58
57
|
'block_device_mappings',
|
59
58
|
'ephemeral_devices',
|
60
59
|
'placement_group'
|
@@ -63,34 +62,25 @@ module Stemcell
|
|
63
62
|
TEMPLATE_PATH = '../templates/bootstrap.sh.erb'
|
64
63
|
LAST_BOOTSTRAP_LINE = "Stemcell bootstrap finished successfully!"
|
65
64
|
|
65
|
+
MAX_RUNNING_STATE_WAIT_TIME = 300 # seconds
|
66
|
+
RUNNING_STATE_WAIT_SLEEP_TIME = 5 # seconds
|
67
|
+
|
66
68
|
def initialize(opts={})
|
67
69
|
@log = Logger.new(STDOUT)
|
68
70
|
@log.level = Logger::INFO unless ENV['DEBUG']
|
69
71
|
@log.debug "creating new stemcell object"
|
70
72
|
@log.debug "opts are #{opts.inspect}"
|
71
73
|
|
72
|
-
REQUIRED_OPTIONS.each do |
|
73
|
-
raise ArgumentError, "missing required
|
74
|
-
instance_variable_set("@#{req}",opts[req])
|
74
|
+
REQUIRED_OPTIONS.each do |opt|
|
75
|
+
raise ArgumentError, "missing required option 'region'" unless opts[opt]
|
75
76
|
end
|
76
77
|
|
77
|
-
@
|
78
|
-
@
|
79
|
-
@
|
80
|
-
|
81
|
-
AWS.config({
|
82
|
-
:access_key_id => @aws_access_key,
|
83
|
-
:secret_access_key => @aws_secret_key})
|
84
|
-
|
85
|
-
if opts['vpc_id']
|
86
|
-
puts 'using vpc tho'
|
87
|
-
@ec2 = AWS::VPC.new(opts['vpc_id'], :ec2_endpoint => @ec2_url)
|
88
|
-
else
|
89
|
-
@ec2 = AWS::EC2.new(:ec2_endpoint => @ec2_url)
|
90
|
-
end
|
78
|
+
@region = opts['region']
|
79
|
+
@vpc_id = opts['vpc_id']
|
80
|
+
@aws_access_key = opts['aws_access_key']
|
81
|
+
@aws_secret_key = opts['aws_secret_key']
|
91
82
|
end
|
92
83
|
|
93
|
-
|
94
84
|
def launch(opts={})
|
95
85
|
verify_required_options(opts, REQUIRED_LAUNCH_PARAMETERS)
|
96
86
|
|
@@ -161,6 +151,12 @@ module Stemcell
|
|
161
151
|
# specify an EBS-optimized instance (optional)
|
162
152
|
launch_options[:ebs_optimized] = true if opts['ebs_optimized']
|
163
153
|
|
154
|
+
# specify placement group (optional)
|
155
|
+
if opts['instance_initiated_shutdown_behavior']
|
156
|
+
launch_options[:instance_initiated_shutdown_behavior] =
|
157
|
+
opts['instance_initiated_shutdown_behavior']
|
158
|
+
end
|
159
|
+
|
164
160
|
# specify raw block device mappings (optional)
|
165
161
|
if opts['block_device_mappings']
|
166
162
|
launch_options[:block_device_mappings] = opts['block_device_mappings']
|
@@ -184,10 +180,22 @@ module Stemcell
|
|
184
180
|
# launch instances
|
185
181
|
instances = do_launch(launch_options)
|
186
182
|
|
187
|
-
#
|
183
|
+
# everything from here on out must succeed, or we kill the instances we just launched
|
188
184
|
begin
|
185
|
+
# set tags on all instances launched
|
189
186
|
set_tags(instances, tags)
|
190
|
-
@log.info "sent ec2 api requests successfully"
|
187
|
+
@log.info "sent ec2 api tag requests successfully"
|
188
|
+
|
189
|
+
# link to classiclink
|
190
|
+
set_classic_link(instances, opts['classic_link'])
|
191
|
+
@log.info "succesfully applied classic link settings (if any)"
|
192
|
+
|
193
|
+
# turn on termination protection
|
194
|
+
# we do this now to make sure all other settings worked
|
195
|
+
if opts['termination_protection']
|
196
|
+
enable_termination_protection(instances)
|
197
|
+
@log.info "succesfully enabled termination protection"
|
198
|
+
end
|
191
199
|
|
192
200
|
# wait for aws to report instance stats
|
193
201
|
if opts.fetch('wait', true)
|
@@ -208,24 +216,19 @@ module Stemcell
|
|
208
216
|
return instances
|
209
217
|
end
|
210
218
|
|
211
|
-
def
|
212
|
-
return
|
213
|
-
end
|
214
|
-
|
215
|
-
def kill(instance_ids, opts={})
|
216
|
-
return if instance_ids.nil?
|
219
|
+
def kill(instances, opts={})
|
220
|
+
return if !instances || instances.empty?
|
217
221
|
|
218
|
-
errors = run_batch_operation(
|
222
|
+
errors = run_batch_operation(instances) do |instance|
|
219
223
|
begin
|
220
|
-
instance
|
221
|
-
@log.warn "Terminating instance #{instance.instance_id}"
|
224
|
+
@log.warn "Terminating instance #{instance.id}"
|
222
225
|
instance.terminate
|
223
226
|
nil # nil == success
|
224
227
|
rescue AWS::EC2::Errors::InvalidInstanceID::NotFound => e
|
225
228
|
opts[:ignore_not_found] ? nil : e
|
226
229
|
end
|
227
230
|
end
|
228
|
-
check_errors(:kill,
|
231
|
+
check_errors(:kill, instances.map(&:id), errors)
|
229
232
|
end
|
230
233
|
|
231
234
|
# this is made public for ec2admin usage
|
@@ -252,22 +255,18 @@ module Stemcell
|
|
252
255
|
end
|
253
256
|
|
254
257
|
def wait(instances)
|
255
|
-
@log.info "Waiting up to #{
|
256
|
-
"instance(s) (#{instances.inspect})
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
raise TimeoutError, "exceded timeout of #{@timeout}"
|
262
|
-
else
|
263
|
-
sleep min(5, @timeout - elapsed)
|
264
|
-
end
|
258
|
+
@log.info "Waiting up to #{MAX_RUNNING_STATE_WAIT_TIME} seconds for #{instances.count} " \
|
259
|
+
"instance(s): (#{instances.inspect})"
|
260
|
+
|
261
|
+
times_out_at = Time.now + MAX_RUNNING_STATE_WAIT_TIME
|
262
|
+
until instances.all?{ |i| i.status == :running }
|
263
|
+
wait_time_expire_or_sleep(times_out_at)
|
265
264
|
end
|
266
265
|
|
267
266
|
@log.info "all instances in running state"
|
268
267
|
end
|
269
268
|
|
270
|
-
def verify_required_options(params,required_options)
|
269
|
+
def verify_required_options(params, required_options)
|
271
270
|
@log.debug "params is #{params}"
|
272
271
|
@log.debug "required_options are #{required_options}"
|
273
272
|
required_options.each do |required|
|
@@ -280,7 +279,7 @@ module Stemcell
|
|
280
279
|
def do_launch(opts={})
|
281
280
|
@log.debug "about to launch instance(s) with options #{opts}"
|
282
281
|
@log.info "launching instances"
|
283
|
-
instances =
|
282
|
+
instances = ec2.instances.create(opts)
|
284
283
|
instances = [instances] unless Array === instances
|
285
284
|
instances.each do |instance|
|
286
285
|
@log.info "launched instance #{instance.instance_id}"
|
@@ -301,6 +300,59 @@ module Stemcell
|
|
301
300
|
check_errors(:set_tags, instances.map(&:id), errors)
|
302
301
|
end
|
303
302
|
|
303
|
+
def set_classic_link(left_to_process, classic_link)
|
304
|
+
return unless classic_link['vpc_id']
|
305
|
+
return unless classic_link['security_group_ids'] && !classic_link['security_group_ids'].empty?
|
306
|
+
|
307
|
+
@log.info "applying classic link settings on #{left_to_process.count} instance(s)"
|
308
|
+
|
309
|
+
errors = []
|
310
|
+
processed = []
|
311
|
+
times_out_at = Time.now + MAX_RUNNING_STATE_WAIT_TIME
|
312
|
+
until left_to_process.empty?
|
313
|
+
wait_time_expire_or_sleep(times_out_at)
|
314
|
+
|
315
|
+
# we can only apply classic link when instances are in the running state
|
316
|
+
# lets apply classiclink as instances become available so we don't wait longer than necessary
|
317
|
+
recently_running = left_to_process.select{ |inst| inst.status == :running }
|
318
|
+
left_to_process = left_to_process.reject{ |inst| recently_running.include?(inst) }
|
319
|
+
|
320
|
+
processed += recently_running
|
321
|
+
errors += run_batch_operation(recently_running) do |instance|
|
322
|
+
begin
|
323
|
+
result = ec2.client.attach_classic_link_vpc({
|
324
|
+
:instance_id => instance.id,
|
325
|
+
:vpc_id => classic_link['vpc_id'],
|
326
|
+
:groups => classic_link['security_group_ids'],
|
327
|
+
})
|
328
|
+
result.error
|
329
|
+
rescue StandardError => e
|
330
|
+
e
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
check_errors(:set_classic_link, processed.map(&:id), errors)
|
336
|
+
end
|
337
|
+
|
338
|
+
def enable_termination_protection(instances)
|
339
|
+
@log.info "enabling termination protection on instance(s)"
|
340
|
+
errors = run_batch_operation(instances) do |instance|
|
341
|
+
begin
|
342
|
+
resp = ec2.client.modify_instance_attribute({
|
343
|
+
:instance_id => instance.id,
|
344
|
+
:disable_api_termination => {
|
345
|
+
:value => true
|
346
|
+
}
|
347
|
+
})
|
348
|
+
resp.error # returns nil (success) unless there was an error
|
349
|
+
rescue StandardError => e
|
350
|
+
e
|
351
|
+
end
|
352
|
+
end
|
353
|
+
check_errors(:enable_termination_protection, instances.map(&:id), errors)
|
354
|
+
end
|
355
|
+
|
304
356
|
# attempt to accept keys as file paths
|
305
357
|
def try_file(opt="")
|
306
358
|
File.read(File.expand_path(opt)) rescue opt
|
@@ -341,5 +393,37 @@ module Stemcell
|
|
341
393
|
instance_ids.zip(errors).reject { |i, e| e.nil? }
|
342
394
|
)
|
343
395
|
end
|
396
|
+
|
397
|
+
def ec2
|
398
|
+
return @ec2 if @ec2
|
399
|
+
|
400
|
+
# configure AWS with creds/region
|
401
|
+
aws_configs = {:region => @region}
|
402
|
+
aws_configs.merge!({
|
403
|
+
:access_key_id => @aws_access_key,
|
404
|
+
:secret_access_key => @aws_secret_key
|
405
|
+
}) if @aws_access_key && @aws_secret_key
|
406
|
+
AWS.config(aws_configs)
|
407
|
+
|
408
|
+
# calculate our ec2 url
|
409
|
+
ec2_url = "ec2.#{@region}.amazonaws.com"
|
410
|
+
|
411
|
+
if @vpc_id
|
412
|
+
@ec2 = AWS::VPC.new(@vpc_id, :ec2_endpoint => ec2_url)
|
413
|
+
else
|
414
|
+
@ec2 = AWS::EC2.new(:ec2_endpoint => ec2_url)
|
415
|
+
end
|
416
|
+
|
417
|
+
@ec2
|
418
|
+
end
|
419
|
+
|
420
|
+
def wait_time_expire_or_sleep(times_out_at)
|
421
|
+
now = Time.now
|
422
|
+
if now >= times_out_at
|
423
|
+
raise TimeoutError, "exceded timeout of #{MAX_RUNNING_STATE_WAIT_TIME} seconds"
|
424
|
+
else
|
425
|
+
sleep [RUNNING_STATE_WAIT_SLEEP_TIME, times_out_at - now].min
|
426
|
+
end
|
427
|
+
end
|
344
428
|
end
|
345
429
|
end
|
@@ -83,6 +83,18 @@ module Stemcell
|
|
83
83
|
:type => String,
|
84
84
|
:env => 'VPC_ID'
|
85
85
|
},
|
86
|
+
{
|
87
|
+
:name => 'classic_link_vpc_id',
|
88
|
+
:desc => 'VPC ID to which this instance will be classic-linked',
|
89
|
+
:type => String,
|
90
|
+
:env => 'CLASSIC_LINK_VPC_ID',
|
91
|
+
},
|
92
|
+
{
|
93
|
+
:name => 'classic_link_security_group_ids',
|
94
|
+
:desc => 'comma-separated list of security group IDs to link into ClassicLink; not used unless classic_link_vpc_id is set',
|
95
|
+
:type => String,
|
96
|
+
:env => 'CLASSIC_LINK_SECURITY_GROUP_IDS',
|
97
|
+
},
|
86
98
|
{
|
87
99
|
:name => 'subnet',
|
88
100
|
:desc => "VPC subnet for which to launch this instance",
|
@@ -137,6 +149,19 @@ module Stemcell
|
|
137
149
|
:type => String,
|
138
150
|
:env => 'EBS_OPTIMIZED'
|
139
151
|
},
|
152
|
+
{
|
153
|
+
:name => 'termination_protection',
|
154
|
+
:desc => "Prevent created instances from being terminated via the API",
|
155
|
+
:type => String,
|
156
|
+
:env => 'TERMINATION_PROTECTION'
|
157
|
+
},
|
158
|
+
{
|
159
|
+
:name => 'instance_initiated_shutdown_behavior',
|
160
|
+
:desc => "What happens when the instance shuts down? ('stop' or 'terminate')",
|
161
|
+
:type => String,
|
162
|
+
:default => 'stop',
|
163
|
+
:env => 'INSTANCE_INITIATED_SHUTDOWN_BEHAVIOR',
|
164
|
+
},
|
140
165
|
{
|
141
166
|
:name => 'block_device_mappings',
|
142
167
|
:desc => 'block device mappings',
|
@@ -358,6 +383,14 @@ module Stemcell
|
|
358
383
|
# convert ephemeral_devices from comma separated string to ruby array
|
359
384
|
options['ephemeral_devices'] &&= options['ephemeral_devices'].split(',')
|
360
385
|
|
386
|
+
# format the classic link options
|
387
|
+
if options['classic_link_vpc_id']
|
388
|
+
options['classic_link']['vpc_id'] = options['classic_link_vpc_id']
|
389
|
+
end
|
390
|
+
if options['classic_link_security_group_ids']
|
391
|
+
options['classic_link']['security_group_ids'] = options['classic_link_security_group_ids']
|
392
|
+
end
|
393
|
+
|
361
394
|
options
|
362
395
|
end
|
363
396
|
|
data/lib/stemcell/version.rb
CHANGED
@@ -8,6 +8,10 @@ class MockInstance
|
|
8
8
|
def id
|
9
9
|
@id
|
10
10
|
end
|
11
|
+
|
12
|
+
def status
|
13
|
+
:running
|
14
|
+
end
|
11
15
|
end
|
12
16
|
|
13
17
|
class MockException < StandardError
|
@@ -15,8 +19,7 @@ end
|
|
15
19
|
|
16
20
|
describe Stemcell::Launcher do
|
17
21
|
let(:launcher) {
|
18
|
-
opts = {}
|
19
|
-
Stemcell::Launcher::REQUIRED_OPTIONS.map { |k| opts[k] = "" }
|
22
|
+
opts = {'region' => 'region'}
|
20
23
|
launcher = Stemcell::Launcher.new(opts)
|
21
24
|
launcher
|
22
25
|
}
|
@@ -24,11 +27,35 @@ describe Stemcell::Launcher do
|
|
24
27
|
let(:instances) { (1..4).map { |id| MockInstance.new(id) } }
|
25
28
|
let(:instance_ids) { instances.map(&:id) }
|
26
29
|
|
27
|
-
describe '#
|
30
|
+
describe '#set_classic_link' do
|
31
|
+
let(:ec2) { instance_double(AWS::EC2) }
|
32
|
+
let(:client) { double(AWS::EC2::Client) }
|
33
|
+
let(:response) { instance_double(AWS::Core::Response) }
|
34
|
+
before do
|
35
|
+
allow(launcher).to receive(:ec2).and_return(ec2)
|
36
|
+
allow(ec2).to receive(:client).and_return(client)
|
37
|
+
allow(response).to receive(:error).and_return(nil)
|
38
|
+
end
|
39
|
+
|
40
|
+
let(:classic_link) { {'vpc_id' => 'vpc_id', 'security_group_ids' => ['sg1', 'sg2']} }
|
28
41
|
|
42
|
+
it 'invokes classic link on all of the instances' do
|
43
|
+
instances.each do |instance|
|
44
|
+
expect(client).to receive(:attach_classic_link_vpc).ordered.with(a_hash_including(
|
45
|
+
:instance_id => instance.id,
|
46
|
+
:vpc_id => classic_link['vpc_id'],
|
47
|
+
:groups => classic_link['security_group_ids'],
|
48
|
+
)).and_return(response)
|
49
|
+
end
|
50
|
+
|
51
|
+
launcher.send(:set_classic_link, instances, classic_link)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#run_batch_operation' do
|
29
56
|
it "raises no exception when no internal error occur" do
|
30
57
|
errors = launcher.send(:run_batch_operation, instances) {}
|
31
|
-
errors.all?(&:nil?).
|
58
|
+
expect(errors.all?(&:nil?)).to be true
|
32
59
|
end
|
33
60
|
|
34
61
|
it "runs full batch even when there are two error" do
|
@@ -36,8 +63,8 @@ describe Stemcell::Launcher do
|
|
36
63
|
instances) do |instance, error|
|
37
64
|
raise "error-#{instance.id}" if instance.id % 2 == 0
|
38
65
|
end
|
39
|
-
errors.count(&:nil?).
|
40
|
-
errors.reject(&:nil?).map { |e| e.message }.
|
66
|
+
expect(errors.count(&:nil?)).to be_eql(2)
|
67
|
+
expect(errors.reject(&:nil?).map { |e| e.message }).to \
|
41
68
|
be_eql([2, 4].map { |id| "error-#{id}" })
|
42
69
|
end
|
43
70
|
|
@@ -52,7 +79,7 @@ describe Stemcell::Launcher do
|
|
52
79
|
nil
|
53
80
|
end
|
54
81
|
end
|
55
|
-
errors.all?(&:nil?).
|
82
|
+
expect(errors.all?(&:nil?)).to be true
|
56
83
|
end
|
57
84
|
end
|
58
85
|
end
|
@@ -68,10 +68,10 @@ describe Stemcell::MetadataSource do
|
|
68
68
|
let(:expand_options) { Hash.new }
|
69
69
|
|
70
70
|
before do
|
71
|
-
config.
|
72
|
-
config.
|
73
|
-
config.
|
74
|
-
chef_repo.
|
71
|
+
allow(config).to receive(:default_options) { default_options }
|
72
|
+
allow(config).to receive(:availability_zones) { availability_zones }
|
73
|
+
allow(config).to receive(:options_for_backing_store) { backing_options }
|
74
|
+
allow(chef_repo).to receive(:metadata_for_role) { role_metadata }
|
75
75
|
end
|
76
76
|
|
77
77
|
let(:role) { 'role' }
|
@@ -159,13 +159,13 @@ describe Stemcell::MetadataSource do
|
|
159
159
|
it "calls the config object to retrieve the backing store options" do
|
160
160
|
backing_options.merge!('image_id' => 'ami-nyancat')
|
161
161
|
override_options.merge!('backing_store' => 'ebs')
|
162
|
-
config.
|
162
|
+
expect(config).to receive(:options_for_backing_store).with('ebs') { backing_options }
|
163
163
|
expect(expansion['image_id']).to eql 'ami-nyancat'
|
164
164
|
end
|
165
165
|
|
166
166
|
it "calls the repository object to determine the role metadata" do
|
167
167
|
role_metadata.merge!('image_id' => 'ami-nyancat')
|
168
|
-
chef_repo.
|
168
|
+
expect(chef_repo).to receive(:metadata_for_role).with(role, environment) { role_metadata }
|
169
169
|
expect(expansion['image_id']).to eql 'ami-nyancat'
|
170
170
|
end
|
171
171
|
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Stemcell::OptionParser do
|
4
|
+
describe '#parse!' do
|
5
|
+
it 'returns a hash containing all of the options' do
|
6
|
+
result = subject.parse!([])
|
7
|
+
expect(result).to be_an_instance_of(Hash)
|
8
|
+
|
9
|
+
possible_keys = described_class::OPTION_DEFINITIONS.map { |d| d[:name] }
|
10
|
+
expect(result).to include(*possible_keys)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/spec/spec_helper.rb
CHANGED
data/stemcell.gemspec
CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.name = "stemcell"
|
7
7
|
s.version = Stemcell::VERSION
|
8
8
|
s.authors = ["Martin Rhoads", "Igor Serebryany", "Nelson Gauthier", "Patrick Viet"]
|
9
|
-
s.email = ["
|
9
|
+
s.email = ["igor.serebryany@airbnb.com"]
|
10
10
|
s.description = %q{A tool for launching and bootstrapping EC2 instances}
|
11
11
|
s.summary = %q{no summary}
|
12
12
|
s.homepage = "https://github.com/airbnb/stemcell"
|
@@ -25,6 +25,11 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.add_runtime_dependency 'chef', ['>= 11.4.0', '< 12.0.0']
|
26
26
|
end
|
27
27
|
|
28
|
+
# this is a transitive dependency, but the latest vesion has a late ruby
|
29
|
+
# version dependency. lets explicitly include it here. if this becomes
|
30
|
+
# no-longer a dependency of chef via chef-zero, then remove it
|
31
|
+
s.add_runtime_dependency 'rack', '< 2.0.0'
|
32
|
+
|
28
33
|
s.add_runtime_dependency 'trollop', '~> 2.1'
|
29
34
|
s.add_runtime_dependency 'aws-creds', '~> 0.2.3'
|
30
35
|
s.add_runtime_dependency 'colored', '~> 1.2'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stemcell
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martin Rhoads
|
@@ -11,115 +11,122 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2016-07-28 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: aws-sdk-v1
|
18
18
|
requirement: !ruby/object:Gem::Requirement
|
19
19
|
requirements:
|
20
|
-
- - ~>
|
20
|
+
- - "~>"
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: '1.63'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
|
-
- - ~>
|
27
|
+
- - "~>"
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '1.63'
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: net-ssh
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
requirements:
|
34
|
-
- - ~>
|
34
|
+
- - "~>"
|
35
35
|
- !ruby/object:Gem::Version
|
36
36
|
version: '2.9'
|
37
37
|
type: :runtime
|
38
38
|
prerelease: false
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
40
40
|
requirements:
|
41
|
-
- - ~>
|
41
|
+
- - "~>"
|
42
42
|
- !ruby/object:Gem::Version
|
43
43
|
version: '2.9'
|
44
44
|
- !ruby/object:Gem::Dependency
|
45
45
|
name: chef
|
46
46
|
requirement: !ruby/object:Gem::Requirement
|
47
47
|
requirements:
|
48
|
-
- -
|
48
|
+
- - ">="
|
49
49
|
- !ruby/object:Gem::Version
|
50
50
|
version: 11.4.0
|
51
|
-
- - <
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: 12.0.0
|
54
51
|
type: :runtime
|
55
52
|
prerelease: false
|
56
53
|
version_requirements: !ruby/object:Gem::Requirement
|
57
54
|
requirements:
|
58
|
-
- -
|
55
|
+
- - ">="
|
59
56
|
- !ruby/object:Gem::Version
|
60
57
|
version: 11.4.0
|
61
|
-
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: rack
|
60
|
+
requirement: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - "<"
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 2.0.0
|
65
|
+
type: :runtime
|
66
|
+
prerelease: false
|
67
|
+
version_requirements: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - "<"
|
62
70
|
- !ruby/object:Gem::Version
|
63
|
-
version:
|
71
|
+
version: 2.0.0
|
64
72
|
- !ruby/object:Gem::Dependency
|
65
73
|
name: trollop
|
66
74
|
requirement: !ruby/object:Gem::Requirement
|
67
75
|
requirements:
|
68
|
-
- - ~>
|
76
|
+
- - "~>"
|
69
77
|
- !ruby/object:Gem::Version
|
70
78
|
version: '2.1'
|
71
79
|
type: :runtime
|
72
80
|
prerelease: false
|
73
81
|
version_requirements: !ruby/object:Gem::Requirement
|
74
82
|
requirements:
|
75
|
-
- - ~>
|
83
|
+
- - "~>"
|
76
84
|
- !ruby/object:Gem::Version
|
77
85
|
version: '2.1'
|
78
86
|
- !ruby/object:Gem::Dependency
|
79
87
|
name: aws-creds
|
80
88
|
requirement: !ruby/object:Gem::Requirement
|
81
89
|
requirements:
|
82
|
-
- - ~>
|
90
|
+
- - "~>"
|
83
91
|
- !ruby/object:Gem::Version
|
84
92
|
version: 0.2.3
|
85
93
|
type: :runtime
|
86
94
|
prerelease: false
|
87
95
|
version_requirements: !ruby/object:Gem::Requirement
|
88
96
|
requirements:
|
89
|
-
- - ~>
|
97
|
+
- - "~>"
|
90
98
|
- !ruby/object:Gem::Version
|
91
99
|
version: 0.2.3
|
92
100
|
- !ruby/object:Gem::Dependency
|
93
101
|
name: colored
|
94
102
|
requirement: !ruby/object:Gem::Requirement
|
95
103
|
requirements:
|
96
|
-
- - ~>
|
104
|
+
- - "~>"
|
97
105
|
- !ruby/object:Gem::Version
|
98
106
|
version: '1.2'
|
99
107
|
type: :runtime
|
100
108
|
prerelease: false
|
101
109
|
version_requirements: !ruby/object:Gem::Requirement
|
102
110
|
requirements:
|
103
|
-
- - ~>
|
111
|
+
- - "~>"
|
104
112
|
- !ruby/object:Gem::Version
|
105
113
|
version: '1.2'
|
106
114
|
- !ruby/object:Gem::Dependency
|
107
115
|
name: json
|
108
116
|
requirement: !ruby/object:Gem::Requirement
|
109
117
|
requirements:
|
110
|
-
- - ~>
|
118
|
+
- - "~>"
|
111
119
|
- !ruby/object:Gem::Version
|
112
120
|
version: 1.8.2
|
113
121
|
type: :runtime
|
114
122
|
prerelease: false
|
115
123
|
version_requirements: !ruby/object:Gem::Requirement
|
116
124
|
requirements:
|
117
|
-
- - ~>
|
125
|
+
- - "~>"
|
118
126
|
- !ruby/object:Gem::Version
|
119
127
|
version: 1.8.2
|
120
128
|
description: A tool for launching and bootstrapping EC2 instances
|
121
129
|
email:
|
122
|
-
- martin.rhoads@airbnb.com
|
123
130
|
- igor.serebryany@airbnb.com
|
124
131
|
executables:
|
125
132
|
- necrosis
|
@@ -127,8 +134,8 @@ executables:
|
|
127
134
|
extensions: []
|
128
135
|
extra_rdoc_files: []
|
129
136
|
files:
|
130
|
-
- .gitignore
|
131
|
-
- .travis.yml
|
137
|
+
- ".gitignore"
|
138
|
+
- ".travis.yml"
|
132
139
|
- CHANGELOG.md
|
133
140
|
- Gemfile
|
134
141
|
- LICENSE.txt
|
@@ -175,6 +182,7 @@ files:
|
|
175
182
|
- spec/lib/stemcell/metadata_source/chef_repository_spec.rb
|
176
183
|
- spec/lib/stemcell/metadata_source/configuration_spec.rb
|
177
184
|
- spec/lib/stemcell/metadata_source_spec.rb
|
185
|
+
- spec/lib/stemcell/option_parser_spec.rb
|
178
186
|
- spec/spec_helper.rb
|
179
187
|
- spec/support/fixture_helper.rb
|
180
188
|
- stemcell.gemspec
|
@@ -188,17 +196,17 @@ require_paths:
|
|
188
196
|
- lib
|
189
197
|
required_ruby_version: !ruby/object:Gem::Requirement
|
190
198
|
requirements:
|
191
|
-
- -
|
199
|
+
- - ">="
|
192
200
|
- !ruby/object:Gem::Version
|
193
201
|
version: '0'
|
194
202
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
195
203
|
requirements:
|
196
|
-
- -
|
204
|
+
- - ">="
|
197
205
|
- !ruby/object:Gem::Version
|
198
206
|
version: '0'
|
199
207
|
requirements: []
|
200
208
|
rubyforge_project:
|
201
|
-
rubygems_version: 2.4.
|
209
|
+
rubygems_version: 2.4.5.1
|
202
210
|
signing_key:
|
203
211
|
specification_version: 4
|
204
212
|
summary: no summary
|
@@ -228,5 +236,6 @@ test_files:
|
|
228
236
|
- spec/lib/stemcell/metadata_source/chef_repository_spec.rb
|
229
237
|
- spec/lib/stemcell/metadata_source/configuration_spec.rb
|
230
238
|
- spec/lib/stemcell/metadata_source_spec.rb
|
239
|
+
- spec/lib/stemcell/option_parser_spec.rb
|
231
240
|
- spec/spec_helper.rb
|
232
241
|
- spec/support/fixture_helper.rb
|