beaker-aws 0.1.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 +15 -0
- data/.gitignore +25 -0
- data/.simplecov +9 -0
- data/Gemfile +27 -0
- data/LICENSE +202 -0
- data/README.md +37 -0
- data/Rakefile +160 -0
- data/acceptance/config/nodes/hosts.yml +40 -0
- data/aws.md +149 -0
- data/beaker-aws.gemspec +37 -0
- data/bin/beaker-aws +32 -0
- data/config/image_templates/ec2.yaml +5 -0
- data/ec2.md +82 -0
- data/lib/beaker/hypervisor/aws_sdk.rb +1001 -0
- data/lib/beaker/hypervisor/ec2.rb +10 -0
- data/lib/beaker/hypervisor/ec2_helper.rb +42 -0
- data/lib/beaker-aws/version.rb +3 -0
- data/spec/beaker/hypervisor/aws_sdk_spec.rb +1018 -0
- data/spec/beaker/hypervisor/ec2_helper_spec.rb +44 -0
- data/spec/spec_helper.rb +17 -0
- metadata +218 -0
@@ -0,0 +1,1018 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Beaker
|
4
|
+
describe AwsSdk do
|
5
|
+
let( :options ) { make_opts.merge({ 'logger' => double().as_null_object, 'timestamp' => Time.now }) }
|
6
|
+
let(:aws) {
|
7
|
+
# Mock out the call to load_fog_credentials
|
8
|
+
allow_any_instance_of( Beaker::AwsSdk ).
|
9
|
+
to receive(:load_fog_credentials).
|
10
|
+
and_return({
|
11
|
+
:access_key => fog_file_contents[:default][:aws_access_key_id],
|
12
|
+
:secret_key => fog_file_contents[:default][:aws_secret_access_key],
|
13
|
+
})
|
14
|
+
|
15
|
+
|
16
|
+
# This is needed because the EC2 api looks up a local endpoints.json file
|
17
|
+
FakeFS.deactivate!
|
18
|
+
aws = Beaker::AwsSdk.new(@hosts, options)
|
19
|
+
FakeFS.activate!
|
20
|
+
|
21
|
+
aws
|
22
|
+
}
|
23
|
+
let(:amispec) {{
|
24
|
+
"centos-5-x86-64-west" => {
|
25
|
+
:image => {:pe => "ami-sekrit1"},
|
26
|
+
:region => "us-west-2",
|
27
|
+
},
|
28
|
+
"centos-6-x86-64-west" => {
|
29
|
+
:image => {:pe => "ami-sekrit2"},
|
30
|
+
:region => "us-west-2",
|
31
|
+
},
|
32
|
+
"centos-7-x86-64-west" => {
|
33
|
+
:image => {:pe => "ami-sekrit3"},
|
34
|
+
:region => "us-west-2",
|
35
|
+
},
|
36
|
+
"ubuntu-12.04-amd64-west" => {
|
37
|
+
:image => {:pe => "ami-sekrit4"},
|
38
|
+
:region => "us-west-2"
|
39
|
+
},
|
40
|
+
}}
|
41
|
+
|
42
|
+
before :each do
|
43
|
+
@hosts = make_hosts({:snapshot => :pe}, 6)
|
44
|
+
@hosts[0][:platform] = "centos-5-x86-64-west"
|
45
|
+
@hosts[1][:platform] = "centos-6-x86-64-west"
|
46
|
+
@hosts[2][:platform] = "centos-7-x86-64-west"
|
47
|
+
@hosts[3][:platform] = "ubuntu-12.04-amd64-west"
|
48
|
+
@hosts[3][:user] = "ubuntu"
|
49
|
+
@hosts[4][:platform] = 'f5-host'
|
50
|
+
@hosts[4][:user] = 'notroot'
|
51
|
+
@hosts[5][:platform] = 'netscaler-host'
|
52
|
+
|
53
|
+
ENV['AWS_ACCESS_KEY'] = nil
|
54
|
+
ENV['AWS_SECRET_ACCESS_KEY'] = nil
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'loading credentials' do
|
58
|
+
|
59
|
+
it 'from .fog file' do
|
60
|
+
creds = aws.load_fog_credentials
|
61
|
+
expect( creds[:access_key] ).to eq("IMANACCESSKEY")
|
62
|
+
expect( creds[:secret_key] ).to eq("supersekritkey")
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
it 'from environment variables' do
|
67
|
+
ENV['AWS_ACCESS_KEY_ID'] = "IMANACCESSKEY"
|
68
|
+
ENV['AWS_SECRET_ACCESS_KEY'] = "supersekritkey"
|
69
|
+
|
70
|
+
creds = aws.load_env_credentials
|
71
|
+
expect( creds[:access_key] ).to eq("IMANACCESSKEY")
|
72
|
+
expect( creds[:secret_key] ).to eq("supersekritkey")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe '#provision' do
|
77
|
+
before :each do
|
78
|
+
expect(aws).to receive(:launch_all_nodes)
|
79
|
+
expect(aws).to receive(:add_tags)
|
80
|
+
expect(aws).to receive(:populate_dns)
|
81
|
+
expect(aws).to receive(:enable_root_on_hosts)
|
82
|
+
expect(aws).to receive(:set_hostnames)
|
83
|
+
expect(aws).to receive(:configure_hosts)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should step through provisioning' do
|
87
|
+
allow( aws ).to receive( :wait_for_status_netdev )
|
88
|
+
aws.provision
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should return nil' do
|
92
|
+
allow( aws ).to receive( :wait_for_status_netdev )
|
93
|
+
expect(aws.provision).to be_nil
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe '#kill_instances' do
|
98
|
+
let( :ec2_instance ) { double('ec2_instance', :nil? => false, :exists? => true, :id => "ec2", :terminate => nil) }
|
99
|
+
let( :vpc_instance ) { double('vpc_instance', :nil? => false, :exists? => true, :id => "vpc", :terminate => nil) }
|
100
|
+
let( :nil_instance ) { double('vpc_instance', :nil? => true, :exists? => true, :id => "nil", :terminate => nil) }
|
101
|
+
let( :unreal_instance ) { double('vpc_instance', :nil? => false, :exists? => false, :id => "unreal", :terminate => nil) }
|
102
|
+
subject(:kill_instances) { aws.kill_instances(instance_set) }
|
103
|
+
|
104
|
+
it 'should return nil' do
|
105
|
+
instance_set = [ec2_instance, vpc_instance, nil_instance, unreal_instance]
|
106
|
+
expect(aws.kill_instances(instance_set)).to be_nil
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'cleanly handles an empty instance list' do
|
110
|
+
instance_set = []
|
111
|
+
expect(aws.kill_instances(instance_set)).to be_nil
|
112
|
+
end
|
113
|
+
|
114
|
+
context 'in general use' do
|
115
|
+
let( :instance_set ) { [ec2_instance, vpc_instance] }
|
116
|
+
|
117
|
+
it 'terminates each running instance' do
|
118
|
+
instance_set.each do |instance|
|
119
|
+
expect(instance).to receive(:terminate).once
|
120
|
+
end
|
121
|
+
expect(kill_instances).to be_nil
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'verifies instances are not nil' do
|
125
|
+
instance_set.each do |instance|
|
126
|
+
expect(instance).to receive(:nil?)
|
127
|
+
allow(instance).to receive(:terminate).once
|
128
|
+
end
|
129
|
+
expect(kill_instances).to be_nil
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'verifies instances exist in AWS' do
|
133
|
+
instance_set.each do |instance|
|
134
|
+
expect(instance).to receive(:exists?)
|
135
|
+
allow(instance).to receive(:terminate).once
|
136
|
+
end
|
137
|
+
expect(kill_instances).to be_nil
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
context 'for a single running instance' do
|
142
|
+
let( :instance_set ) { [ec2_instance] }
|
143
|
+
|
144
|
+
it 'terminates the running instance' do
|
145
|
+
instance_set.each do |instance|
|
146
|
+
expect(instance).to receive(:terminate).once
|
147
|
+
end
|
148
|
+
expect(kill_instances).to be_nil
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'verifies instance is not nil' do
|
152
|
+
instance_set.each do |instance|
|
153
|
+
expect(instance).to receive(:nil?)
|
154
|
+
allow(instance).to receive(:terminate).once
|
155
|
+
end
|
156
|
+
expect(kill_instances).to be_nil
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'verifies instance exists in AWS' do
|
160
|
+
instance_set.each do |instance|
|
161
|
+
expect(instance).to receive(:exists?)
|
162
|
+
allow(instance).to receive(:terminate).once
|
163
|
+
end
|
164
|
+
expect(kill_instances).to be_nil
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
context 'when an instance does not exist' do
|
169
|
+
let( :instance_set ) { [unreal_instance] }
|
170
|
+
|
171
|
+
it 'does not call terminate' do
|
172
|
+
instance_set.each do |instance|
|
173
|
+
expect(instance).to receive(:terminate).exactly(0).times
|
174
|
+
end
|
175
|
+
expect(kill_instances).to be_nil
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'verifies instance does not exist' do
|
179
|
+
instance_set.each do |instance|
|
180
|
+
expect(instance).to receive(:exists?).once
|
181
|
+
allow(instance).to receive(:terminate).exactly(0).times
|
182
|
+
end
|
183
|
+
expect(kill_instances).to be_nil
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
context 'when an instance is nil' do
|
188
|
+
let( :instance_set ) { [nil_instance] }
|
189
|
+
|
190
|
+
it 'does not call terminate' do
|
191
|
+
instance_set.each do |instance|
|
192
|
+
expect(instance).to receive(:terminate).exactly(0).times
|
193
|
+
end
|
194
|
+
expect(kill_instances).to be_nil
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'verifies instance is nil' do
|
198
|
+
instance_set.each do |instance|
|
199
|
+
expect(instance).to receive(:nil?).once
|
200
|
+
allow(instance).to receive(:terminate).exactly(0).times
|
201
|
+
end
|
202
|
+
expect(kill_instances).to be_nil
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
|
208
|
+
describe '#cleanup' do
|
209
|
+
subject(:cleanup) { aws.cleanup }
|
210
|
+
let( :ec2_instance ) { double('ec2_instance', :nil? => false, :exists? => true, :terminate => nil, :id => 'id') }
|
211
|
+
|
212
|
+
context 'with a list of hosts' do
|
213
|
+
before :each do
|
214
|
+
@hosts.each {|host| host['instance'] = ec2_instance}
|
215
|
+
expect(aws).to receive( :delete_key_pair_all_regions )
|
216
|
+
end
|
217
|
+
|
218
|
+
it { is_expected.to be_nil }
|
219
|
+
|
220
|
+
it 'kills instances' do
|
221
|
+
expect(aws).to receive(:kill_instances).once
|
222
|
+
expect(cleanup).to be_nil
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
context 'with an empty host list' do
|
227
|
+
before :each do
|
228
|
+
@hosts = []
|
229
|
+
expect(aws).to receive( :delete_key_pair_all_regions )
|
230
|
+
end
|
231
|
+
|
232
|
+
it { is_expected.to be_nil }
|
233
|
+
|
234
|
+
it 'kills instances' do
|
235
|
+
expect(aws).to receive(:kill_instances).once
|
236
|
+
expect(cleanup).to be_nil
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
describe '#log_instances', :wip do
|
242
|
+
end
|
243
|
+
|
244
|
+
describe '#instance_by_id' do
|
245
|
+
subject { aws.instance_by_id('my_id') }
|
246
|
+
it { is_expected.to be_instance_of(AWS::EC2::Instance) }
|
247
|
+
end
|
248
|
+
|
249
|
+
describe '#instances' do
|
250
|
+
subject { aws.instances }
|
251
|
+
it { is_expected.to be_instance_of(AWS::EC2::InstanceCollection) }
|
252
|
+
end
|
253
|
+
|
254
|
+
describe '#vpc_by_id' do
|
255
|
+
subject { aws.vpc_by_id('my_id') }
|
256
|
+
it { is_expected.to be_instance_of(AWS::EC2::VPC) }
|
257
|
+
end
|
258
|
+
|
259
|
+
describe '#vpcs' do
|
260
|
+
subject { aws.vpcs }
|
261
|
+
it { is_expected.to be_instance_of(AWS::EC2::VPCCollection) }
|
262
|
+
end
|
263
|
+
|
264
|
+
describe '#security_group_by_id' do
|
265
|
+
subject { aws.security_group_by_id('my_id') }
|
266
|
+
it { is_expected.to be_instance_of(AWS::EC2::SecurityGroup) }
|
267
|
+
end
|
268
|
+
|
269
|
+
describe '#security_groups' do
|
270
|
+
subject { aws.security_groups }
|
271
|
+
it { is_expected.to be_instance_of(AWS::EC2::SecurityGroupCollection) }
|
272
|
+
end
|
273
|
+
|
274
|
+
describe '#kill_zombies' do
|
275
|
+
it 'calls delete_key_pair_all_regions' do
|
276
|
+
ec2_mock = Object.new
|
277
|
+
allow(ec2_mock).to receive( :regions ).and_return( {} )
|
278
|
+
aws.instance_variable_set( :@ec2, ec2_mock )
|
279
|
+
|
280
|
+
expect( aws ).to receive( :delete_key_pair_all_regions ).once
|
281
|
+
|
282
|
+
aws.kill_zombies()
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
describe '#kill_zombie_volumes', :wip do
|
287
|
+
end
|
288
|
+
|
289
|
+
describe '#create_instance', :wip do
|
290
|
+
end
|
291
|
+
|
292
|
+
describe '#launch_nodes_on_some_subnet', :wip do
|
293
|
+
end
|
294
|
+
|
295
|
+
describe '#launch_all_nodes', :wip do
|
296
|
+
end
|
297
|
+
|
298
|
+
describe '#wait_for_status' do
|
299
|
+
let( :aws_instance ) { double('aws_instance', :id => "ec2", :terminate => nil) }
|
300
|
+
let( :instance_set ) { [{:instance => aws_instance}] }
|
301
|
+
subject(:wait_for_status) { aws.wait_for_status(:running, instance_set) }
|
302
|
+
|
303
|
+
context 'single instance' do
|
304
|
+
it 'behaves correctly in typical case' do
|
305
|
+
allow(aws_instance).to receive(:status).and_return(:waiting, :waiting, :running)
|
306
|
+
expect(aws).to receive(:backoff_sleep).exactly(3).times
|
307
|
+
expect(wait_for_status).to eq(instance_set)
|
308
|
+
end
|
309
|
+
|
310
|
+
it 'executes block correctly instead of status if given one' do
|
311
|
+
barn_value = 'did you grow up in a barn?'
|
312
|
+
allow(aws_instance).to receive( :[] ).with( :barn ) { barn_value }
|
313
|
+
expect(aws_instance).to receive(:status).exactly(0).times
|
314
|
+
expect(aws).to receive(:backoff_sleep).exactly(1).times
|
315
|
+
aws.wait_for_status(:running, instance_set) do |instance|
|
316
|
+
expect( instance[:barn] ).to be === barn_value
|
317
|
+
true
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
context 'with multiple instances' do
|
323
|
+
let( :instance_set ) { [{:instance => aws_instance}, {:instance => aws_instance}] }
|
324
|
+
|
325
|
+
it 'returns the instance set passed to it' do
|
326
|
+
allow(aws_instance).to receive(:status).and_return(:waiting, :waiting, :running, :waiting, :waiting, :running)
|
327
|
+
allow(aws).to receive(:backoff_sleep).exactly(6).times
|
328
|
+
expect(wait_for_status).to eq(instance_set)
|
329
|
+
end
|
330
|
+
|
331
|
+
it 'calls backoff_sleep once per instance.status call' do
|
332
|
+
allow(aws_instance).to receive(:status).and_return(:waiting, :waiting, :running, :waiting, :waiting, :running)
|
333
|
+
expect(aws).to receive(:backoff_sleep).exactly(6).times
|
334
|
+
expect(wait_for_status).to eq(instance_set)
|
335
|
+
end
|
336
|
+
|
337
|
+
it 'executes block correctly instead of status if given one' do
|
338
|
+
barn_value = 'did you grow up in a barn?'
|
339
|
+
not_barn_value = 'notabarn'
|
340
|
+
allow(aws_instance).to receive( :[] ).with( :barn ).and_return(not_barn_value, barn_value, not_barn_value, barn_value)
|
341
|
+
allow(aws_instance).to receive(:status).and_return(:waiting)
|
342
|
+
expect(aws).to receive(:backoff_sleep).exactly(4).times
|
343
|
+
aws.wait_for_status(:running, instance_set) do |instance|
|
344
|
+
instance[:barn] == barn_value
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
context 'after 10 tries' do
|
350
|
+
it 'raises RuntimeError' do
|
351
|
+
expect(aws_instance).to receive(:status).and_return(:waiting).exactly(10).times
|
352
|
+
expect(aws).to receive(:backoff_sleep).exactly(9).times
|
353
|
+
expect { wait_for_status }.to raise_error('Instance never reached state running')
|
354
|
+
end
|
355
|
+
|
356
|
+
it 'still raises RuntimeError if given a block' do
|
357
|
+
expect(aws_instance).to receive(:status).and_return(:waiting).exactly(10).times
|
358
|
+
expect(aws).to receive(:backoff_sleep).exactly(9).times
|
359
|
+
expect { wait_for_status { false } }.to raise_error('Instance never reached state running')
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
context 'with an invalid instance' do
|
364
|
+
it 'raises AWS::EC2::Errors::InvalidInstanceID::NotFound' do
|
365
|
+
expect(aws_instance).to receive(:status).and_raise(AWS::EC2::Errors::InvalidInstanceID::NotFound).exactly(10).times
|
366
|
+
allow(aws).to receive(:backoff_sleep).at_most(10).times
|
367
|
+
expect(wait_for_status).to eq(instance_set)
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
describe '#add_tags' do
|
373
|
+
let( :aws_instance ) { double('aws_instance', :add_tag => nil) }
|
374
|
+
subject(:add_tags) { aws.add_tags }
|
375
|
+
|
376
|
+
it 'returns nil' do
|
377
|
+
@hosts.each {|host| host['instance'] = aws_instance}
|
378
|
+
expect(add_tags).to be_nil
|
379
|
+
end
|
380
|
+
|
381
|
+
it 'handles a single host' do
|
382
|
+
@hosts[0]['instance'] = aws_instance
|
383
|
+
@hosts = [@hosts[0]]
|
384
|
+
expect(add_tags).to be_nil
|
385
|
+
end
|
386
|
+
|
387
|
+
context 'with multiple hosts' do
|
388
|
+
before :each do
|
389
|
+
@hosts.each {|host| host['instance'] = aws_instance}
|
390
|
+
end
|
391
|
+
|
392
|
+
it 'handles host_tags hash on host object' do
|
393
|
+
# set :host_tags on first host
|
394
|
+
aws.instance_eval {
|
395
|
+
@hosts[0][:host_tags] = {'test_tag' => 'test_value'}
|
396
|
+
}
|
397
|
+
expect(aws_instance).to receive(:add_tag).with('test_tag', hash_including(:value => 'test_value')).at_least(:once)
|
398
|
+
expect(add_tags).to be_nil
|
399
|
+
end
|
400
|
+
|
401
|
+
it 'adds tag for jenkins_build_url' do
|
402
|
+
aws.instance_eval('@options[:jenkins_build_url] = "my_build_url"')
|
403
|
+
expect(aws_instance).to receive(:add_tag).with('jenkins_build_url', hash_including(:value => 'my_build_url')).at_least(:once)
|
404
|
+
expect(add_tags).to be_nil
|
405
|
+
end
|
406
|
+
|
407
|
+
it 'adds tag for Name' do
|
408
|
+
expect(aws_instance).to receive(:add_tag).with('Name', hash_including(:value => /vm/)).at_least(@hosts.size).times
|
409
|
+
expect(add_tags).to be_nil
|
410
|
+
end
|
411
|
+
|
412
|
+
it 'adds tag for department' do
|
413
|
+
aws.instance_eval('@options[:department] = "my_department"')
|
414
|
+
expect(aws_instance).to receive(:add_tag).with('department', hash_including(:value => 'my_department')).at_least(:once)
|
415
|
+
expect(add_tags).to be_nil
|
416
|
+
end
|
417
|
+
|
418
|
+
it 'adds tag for project' do
|
419
|
+
aws.instance_eval('@options[:project] = "my_project"')
|
420
|
+
expect(aws_instance).to receive(:add_tag).with('project', hash_including(:value => 'my_project')).at_least(:once)
|
421
|
+
expect(add_tags).to be_nil
|
422
|
+
end
|
423
|
+
|
424
|
+
it 'adds tag for created_by' do
|
425
|
+
aws.instance_eval('@options[:created_by] = "my_created_by"')
|
426
|
+
expect(aws_instance).to receive(:add_tag).with('created_by', hash_including(:value => 'my_created_by')).at_least(:once)
|
427
|
+
expect(add_tags).to be_nil
|
428
|
+
end
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
describe '#populate_dns' do
|
433
|
+
let( :vpc_instance ) { {ip_address: nil, private_ip_address: "vpc_private_ip", dns_name: "vpc_dns_name"} }
|
434
|
+
let( :ec2_instance ) { {ip_address: "ec2_public_ip", private_ip_address: "ec2_private_ip", dns_name: "ec2_dns_name"} }
|
435
|
+
subject(:populate_dns) { aws.populate_dns }
|
436
|
+
|
437
|
+
context 'on a public EC2 instance' do
|
438
|
+
before :each do
|
439
|
+
@hosts.each {|host| host['instance'] = make_instance ec2_instance}
|
440
|
+
end
|
441
|
+
|
442
|
+
it 'sets host ip to instance.ip_address' do
|
443
|
+
populate_dns
|
444
|
+
hosts = aws.instance_variable_get( :@hosts )
|
445
|
+
hosts.each do |host|
|
446
|
+
expect(host['ip']).to eql(ec2_instance[:ip_address])
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
it 'sets host private_ip to instance.private_ip_address' do
|
451
|
+
populate_dns
|
452
|
+
hosts = aws.instance_variable_get( :@hosts )
|
453
|
+
hosts.each do |host|
|
454
|
+
expect(host['private_ip']).to eql(ec2_instance[:private_ip_address])
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
it 'sets host dns_name to instance.dns_name' do
|
459
|
+
populate_dns
|
460
|
+
hosts = aws.instance_variable_get( :@hosts )
|
461
|
+
hosts.each do |host|
|
462
|
+
expect(host['dns_name']).to eql(ec2_instance[:dns_name])
|
463
|
+
end
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
467
|
+
context 'on a VPC based instance' do
|
468
|
+
before :each do
|
469
|
+
@hosts.each {|host| host['instance'] = make_instance vpc_instance}
|
470
|
+
end
|
471
|
+
|
472
|
+
it 'sets host ip to instance.private_ip_address' do
|
473
|
+
populate_dns
|
474
|
+
hosts = aws.instance_variable_get( :@hosts )
|
475
|
+
hosts.each do |host|
|
476
|
+
expect(host['ip']).to eql(vpc_instance[:private_ip_address])
|
477
|
+
end
|
478
|
+
end
|
479
|
+
|
480
|
+
it 'sets host private_ip to instance.private_ip_address' do
|
481
|
+
populate_dns
|
482
|
+
hosts = aws.instance_variable_get( :@hosts )
|
483
|
+
hosts.each do |host|
|
484
|
+
expect(host['private_ip']).to eql(vpc_instance[:private_ip_address])
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
488
|
+
it 'sets host dns_name to instance.dns_name' do
|
489
|
+
populate_dns
|
490
|
+
hosts = aws.instance_variable_get( :@hosts )
|
491
|
+
hosts.each do |host|
|
492
|
+
expect(host['dns_name']).to eql(vpc_instance[:dns_name])
|
493
|
+
end
|
494
|
+
end
|
495
|
+
end
|
496
|
+
end
|
497
|
+
|
498
|
+
describe '#etc_hosts_entry' do
|
499
|
+
let( :host ) { @hosts[0] }
|
500
|
+
let( :interface ) { :ip }
|
501
|
+
subject(:etc_hosts_entry) { aws.etc_hosts_entry(host, interface) }
|
502
|
+
|
503
|
+
it 'returns a predictable host entry' do
|
504
|
+
expect(aws).to receive(:get_domain_name).and_return('lan')
|
505
|
+
expect(etc_hosts_entry).to eq("ip.address.for.vm1\tvm1 vm1.lan vm1.box.tld\n")
|
506
|
+
end
|
507
|
+
|
508
|
+
context 'when :private_ip is requested' do
|
509
|
+
let( :interface ) { :private_ip }
|
510
|
+
it 'returns host entry for the private_ip' do
|
511
|
+
host = @hosts[0]
|
512
|
+
expect(aws).to receive(:get_domain_name).and_return('lan')
|
513
|
+
expect(etc_hosts_entry).to eq("private.ip.for.vm1\tvm1 vm1.lan vm1.box.tld\n")
|
514
|
+
end
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
describe '#configure_hosts' do
|
519
|
+
subject(:configure_hosts) { aws.configure_hosts }
|
520
|
+
|
521
|
+
it { is_expected.to be_nil }
|
522
|
+
|
523
|
+
context 'calls #set_etc_hosts' do
|
524
|
+
it 'for each host (except the f5 ones)' do
|
525
|
+
non_netdev_hosts = @hosts.select{ |h| !(h['platform'] =~ /f5|netscaler/) }
|
526
|
+
expect(aws).to receive(:set_etc_hosts).exactly(non_netdev_hosts.size).times
|
527
|
+
expect(configure_hosts).to be_nil
|
528
|
+
end
|
529
|
+
|
530
|
+
it 'with predictable host entries' do
|
531
|
+
@hosts = [@hosts[0], @hosts[1]]
|
532
|
+
entries = "127.0.0.1\tlocalhost localhost.localdomain\n"\
|
533
|
+
"private.ip.for.vm1\tvm1 vm1.lan vm1.box.tld\n"\
|
534
|
+
"ip.address.for.vm2\tvm2 vm2.lan vm2.box.tld\n"
|
535
|
+
allow(aws).to receive(:get_domain_name).and_return('lan')
|
536
|
+
expect(aws).to receive(:set_etc_hosts).with(@hosts[0], entries)
|
537
|
+
expect(aws).to receive(:set_etc_hosts).with(@hosts[1], anything)
|
538
|
+
expect(configure_hosts).to be_nil
|
539
|
+
end
|
540
|
+
end
|
541
|
+
end
|
542
|
+
|
543
|
+
describe '#enable_root_on_hosts' do
|
544
|
+
context 'enabling root shall be called once for the ubuntu machine' do
|
545
|
+
it "should enable root once" do
|
546
|
+
allow(aws).to receive(:enable_root_netscaler)
|
547
|
+
expect( aws ).to receive(:copy_ssh_to_root).with( @hosts[3], options ).once()
|
548
|
+
expect( aws ).to receive(:enable_root_login).with( @hosts[3], options).once()
|
549
|
+
aws.enable_root_on_hosts();
|
550
|
+
end
|
551
|
+
end
|
552
|
+
|
553
|
+
it 'enables root once on the f5 host through its code path' do
|
554
|
+
allow(aws).to receive(:enable_root_netscaler)
|
555
|
+
expect( aws ).to receive(:enable_root_f5).with( @hosts[4] ).once()
|
556
|
+
aws.enable_root_on_hosts()
|
557
|
+
end
|
558
|
+
end
|
559
|
+
|
560
|
+
describe '#enable_root_f5' do
|
561
|
+
let( :f5_host ) { @hosts[4] }
|
562
|
+
subject(:enable_root_f5) { aws.enable_root_f5(f5_host) }
|
563
|
+
|
564
|
+
it 'creates a password on the host' do
|
565
|
+
result_mock = Beaker::Result.new(f5_host, '')
|
566
|
+
result_mock.exit_code = 0
|
567
|
+
allow( f5_host ).to receive( :exec ).and_return(result_mock)
|
568
|
+
allow( aws ).to receive( :backoff_sleep )
|
569
|
+
sha_mock = Object.new
|
570
|
+
allow( Digest::SHA256 ).to receive( :new ).and_return(sha_mock)
|
571
|
+
expect( sha_mock ).to receive( :hexdigest ).once()
|
572
|
+
enable_root_f5
|
573
|
+
end
|
574
|
+
|
575
|
+
it 'tries 10x before failing correctly' do
|
576
|
+
result_mock = Beaker::Result.new(f5_host, '')
|
577
|
+
result_mock.exit_code = 2
|
578
|
+
allow( f5_host ).to receive( :exec ).and_return(result_mock)
|
579
|
+
expect( aws ).to receive( :backoff_sleep ).exactly(9).times
|
580
|
+
expect{ enable_root_f5 }.to raise_error( RuntimeError, /unable/ )
|
581
|
+
end
|
582
|
+
end
|
583
|
+
|
584
|
+
describe '#enable_root_netscaler' do
|
585
|
+
let( :ns_host ) { @hosts[5] }
|
586
|
+
subject(:enable_root_netscaler) { aws.enable_root_netscaler(ns_host) }
|
587
|
+
|
588
|
+
it 'set password to instance id of the host' do
|
589
|
+
instance_mock = Object.new
|
590
|
+
allow( instance_mock ).to receive(:id).and_return("i-842018")
|
591
|
+
ns_host["instance"]=instance_mock
|
592
|
+
enable_root_netscaler
|
593
|
+
expect(ns_host['ssh'][:password]).to eql("i-842018")
|
594
|
+
end
|
595
|
+
end
|
596
|
+
|
597
|
+
describe '#set_hostnames' do
|
598
|
+
subject(:set_hostnames) { aws.set_hostnames }
|
599
|
+
it 'returns @hosts' do
|
600
|
+
expect(set_hostnames).to eq(@hosts)
|
601
|
+
end
|
602
|
+
|
603
|
+
context 'for each host' do
|
604
|
+
it 'calls exec' do
|
605
|
+
@hosts.each do |host|
|
606
|
+
expect(host).to receive(:exec).once unless host['platform'] =~ /netscaler/
|
607
|
+
end
|
608
|
+
expect(set_hostnames).to eq(@hosts)
|
609
|
+
end
|
610
|
+
|
611
|
+
it 'passes a Command instance to exec' do
|
612
|
+
@hosts.each do |host|
|
613
|
+
expect(host).to receive(:exec).with( instance_of(Beaker::Command) ).once unless host['platform'] =~ /netscaler/
|
614
|
+
end
|
615
|
+
expect(set_hostnames).to eq(@hosts)
|
616
|
+
end
|
617
|
+
|
618
|
+
it 'sets the the vmhostname to the dns_name for each host' do
|
619
|
+
expect(set_hostnames).to eq(@hosts)
|
620
|
+
@hosts.each do |host|
|
621
|
+
expect(host[:vmhostname]).to eq(host[:dns_name])
|
622
|
+
expect(host[:vmhostname]).to eq(host.hostname)
|
623
|
+
end
|
624
|
+
end
|
625
|
+
|
626
|
+
it 'sets the the vmhostname to the beaker config name for each host' do
|
627
|
+
options[:use_beaker_hostnames] = true
|
628
|
+
@hosts.each do |host|
|
629
|
+
host[:name] = "prettyponyprincess"
|
630
|
+
end
|
631
|
+
expect(set_hostnames).to eq(@hosts)
|
632
|
+
@hosts.each do |host|
|
633
|
+
expect(host[:vmhostname]).to eq(host[:name])
|
634
|
+
expect(host[:vmhostname]).to eq(host.hostname)
|
635
|
+
end
|
636
|
+
end
|
637
|
+
|
638
|
+
end
|
639
|
+
end
|
640
|
+
|
641
|
+
describe '#backoff_sleep' do
|
642
|
+
it "should call sleep 1024 times at attempt 10" do
|
643
|
+
expect_any_instance_of( Object ).to receive(:sleep).with(1024)
|
644
|
+
aws.backoff_sleep(10)
|
645
|
+
end
|
646
|
+
end
|
647
|
+
|
648
|
+
describe '#public_key' do
|
649
|
+
subject(:public_key) { aws.public_key }
|
650
|
+
|
651
|
+
it "retrieves contents from local ~/.ssh/id_rsa.pub file" do
|
652
|
+
# Stub calls to file read/exists
|
653
|
+
key_value = 'foobar_Rsa'
|
654
|
+
allow(File).to receive(:exist?).with(/id_dsa.pub/) { false }
|
655
|
+
allow(File).to receive(:exist?).with(/id_dsa/) { false }
|
656
|
+
allow(File).to receive(:exist?).with(/id_rsa.pub/) { true }
|
657
|
+
allow(File).to receive(:exist?).with(/id_rsa/) { true }
|
658
|
+
allow(File).to receive(:read).with(/id_rsa.pub/) { key_value }
|
659
|
+
|
660
|
+
# Should return contents of allow( previously ).to receivebed id_rsa.pub
|
661
|
+
expect(public_key).to be === key_value
|
662
|
+
end
|
663
|
+
|
664
|
+
it "retrieves contents from local ~/.ssh/id_dsa.pub file" do
|
665
|
+
# Stub calls to file read/exists
|
666
|
+
key_value = 'foobar_Dsa'
|
667
|
+
allow(File).to receive(:exist?).with(/id_rsa.pub/) { false }
|
668
|
+
allow(File).to receive(:exist?).with(/id_rsa/) { false }
|
669
|
+
allow(File).to receive(:exist?).with(/id_dsa.pub/) { true }
|
670
|
+
allow(File).to receive(:exist?).with(/id_dsa/) { true }
|
671
|
+
allow(File).to receive(:read).with(/id_dsa.pub/) { key_value }
|
672
|
+
|
673
|
+
expect(public_key).to be === key_value
|
674
|
+
end
|
675
|
+
|
676
|
+
it "should return an error if the files do not exist" do
|
677
|
+
expect { public_key }.to raise_error(RuntimeError, /Expected to find a public key/)
|
678
|
+
end
|
679
|
+
|
680
|
+
it "uses options-provided keys" do
|
681
|
+
opts = aws.instance_variable_get( :@options )
|
682
|
+
opts[:ssh][:keys] = ['fake_key1', 'fake_key2']
|
683
|
+
aws.instance_variable_set( :@options, opts )
|
684
|
+
|
685
|
+
key_value = 'foobar_Custom2'
|
686
|
+
allow(File).to receive(:exist?).with(anything) { false }
|
687
|
+
allow(File).to receive(:exist?).with(/fake_key2/) { true }
|
688
|
+
allow(File).to receive(:read).with(/fake_key2/) { key_value }
|
689
|
+
|
690
|
+
expect(public_key).to be === key_value
|
691
|
+
end
|
692
|
+
end
|
693
|
+
|
694
|
+
describe '#key_name' do
|
695
|
+
it 'returns a key name from the local hostname' do
|
696
|
+
# Mock out the hostname and local user calls
|
697
|
+
expect( Socket ).to receive(:gethostname) { "foobar" }
|
698
|
+
expect( aws ).to receive(:local_user) { "bob" }
|
699
|
+
|
700
|
+
# Should match the expected composite key name
|
701
|
+
expect(aws.key_name).to match(/^Beaker-bob-foobar-/)
|
702
|
+
end
|
703
|
+
|
704
|
+
it 'uses the generated random string from :aws_keyname_modifier' do
|
705
|
+
expect(aws.key_name).to match(/#{options[:aws_keyname_modifier]}/)
|
706
|
+
end
|
707
|
+
|
708
|
+
it 'uses nanosecond time value to make key name collision harder' do
|
709
|
+
options[:timestamp] = Time.now
|
710
|
+
nanosecond_value = options[:timestamp].strftime("%N")
|
711
|
+
expect(aws.key_name).to match(/#{nanosecond_value}/)
|
712
|
+
end
|
713
|
+
end
|
714
|
+
|
715
|
+
describe '#local_user' do
|
716
|
+
it 'returns ENV["USER"]' do
|
717
|
+
stub_const('ENV', ENV.to_hash.merge('USER' => 'SuperUser'))
|
718
|
+
expect(aws.local_user).to eq("SuperUser")
|
719
|
+
end
|
720
|
+
end
|
721
|
+
|
722
|
+
describe '#ensure_key_pair' do
|
723
|
+
let( :region ) { double('region', :name => 'test_region_name') }
|
724
|
+
subject(:ensure_key_pair) { aws.ensure_key_pair(region) }
|
725
|
+
let( :key_name ) { "Beaker-rspec-SUT" }
|
726
|
+
|
727
|
+
it 'deletes the given keypair, then recreates it' do
|
728
|
+
allow( aws ).to receive( :key_name ).and_return(key_name)
|
729
|
+
|
730
|
+
expect( aws ).to receive( :delete_key_pair ).with( region, key_name).once.ordered
|
731
|
+
expect( aws ).to receive( :create_new_key_pair ).with( region, key_name).once.ordered
|
732
|
+
ensure_key_pair
|
733
|
+
end
|
734
|
+
end
|
735
|
+
|
736
|
+
describe '#delete_key_pair_all_regions' do
|
737
|
+
it 'calls delete_key_pair over all regions' do
|
738
|
+
key_name = 'kname_test1538'
|
739
|
+
allow(aws).to receive( :key_name ).and_return(key_name)
|
740
|
+
regions = []
|
741
|
+
regions << double('region', :key_pairs => 'pair1', :name => 'name1')
|
742
|
+
regions << double('region', :key_pairs => 'pair2', :name => 'name2')
|
743
|
+
ec2_mock = Object.new
|
744
|
+
allow(ec2_mock).to receive( :regions ).and_return(regions)
|
745
|
+
aws.instance_variable_set( :@ec2, ec2_mock )
|
746
|
+
region_keypairs_hash_mock = {}
|
747
|
+
region_keypairs_hash_mock[double('region')] = ['key1', 'key2', 'key3']
|
748
|
+
region_keypairs_hash_mock[double('region')] = ['key4', 'key5', 'key6']
|
749
|
+
allow( aws ).to receive( :my_key_pairs ).and_return( region_keypairs_hash_mock )
|
750
|
+
|
751
|
+
region_keypairs_hash_mock.each_pair do |region, keyname_array|
|
752
|
+
keyname_array.each do |keyname|
|
753
|
+
expect( aws ).to receive( :delete_key_pair ).with( region, keyname )
|
754
|
+
end
|
755
|
+
end
|
756
|
+
aws.delete_key_pair_all_regions
|
757
|
+
end
|
758
|
+
end
|
759
|
+
|
760
|
+
describe '#my_key_pairs' do
|
761
|
+
let( :region ) { double('region', :name => 'test_region_name') }
|
762
|
+
|
763
|
+
it 'uses the default keyname if no filter is given' do
|
764
|
+
default_keyname_answer = 'test_pair_6193'
|
765
|
+
allow( aws ).to receive( :key_name ).and_return( default_keyname_answer )
|
766
|
+
|
767
|
+
kp_mock_1 = double('keypair')
|
768
|
+
kp_mock_2 = double('keypair')
|
769
|
+
regions = []
|
770
|
+
regions << double('region', :key_pairs => kp_mock_1, :name => 'name1')
|
771
|
+
regions << double('region', :key_pairs => kp_mock_2, :name => 'name2')
|
772
|
+
ec2_mock = Object.new
|
773
|
+
allow( ec2_mock ).to receive( :regions ).and_return( regions )
|
774
|
+
aws.instance_variable_set( :@ec2, ec2_mock )
|
775
|
+
|
776
|
+
kp_mock = double('keypair')
|
777
|
+
allow( region ).to receive( :key_pairs ).and_return( kp_mock )
|
778
|
+
expect( kp_mock_1 ).to receive( :filter ).with( 'key-name', default_keyname_answer ).and_return( [] )
|
779
|
+
expect( kp_mock_2 ).to receive( :filter ).with( 'key-name', default_keyname_answer ).and_return( [] )
|
780
|
+
|
781
|
+
aws.my_key_pairs()
|
782
|
+
end
|
783
|
+
|
784
|
+
it 'uses the filter passed if given' do
|
785
|
+
default_keyname_answer = 'test_pair_6194'
|
786
|
+
allow( aws ).to receive( :key_name ).and_return( default_keyname_answer )
|
787
|
+
name_filter = 'filter_pair_1597'
|
788
|
+
filter_star = "#{name_filter}-*"
|
789
|
+
|
790
|
+
kp_mock_1 = double('keypair')
|
791
|
+
kp_mock_2 = double('keypair')
|
792
|
+
regions = []
|
793
|
+
regions << double('region', :key_pairs => kp_mock_1, :name => 'name1')
|
794
|
+
regions << double('region', :key_pairs => kp_mock_2, :name => 'name2')
|
795
|
+
ec2_mock = Object.new
|
796
|
+
allow( ec2_mock ).to receive( :regions ).and_return( regions )
|
797
|
+
aws.instance_variable_set( :@ec2, ec2_mock )
|
798
|
+
|
799
|
+
kp_mock = double('keypair')
|
800
|
+
allow( region ).to receive( :key_pairs ).and_return( kp_mock )
|
801
|
+
expect( kp_mock_1 ).to receive( :filter ).with( 'key-name', filter_star ).and_return( [] )
|
802
|
+
expect( kp_mock_2 ).to receive( :filter ).with( 'key-name', filter_star ).and_return( [] )
|
803
|
+
|
804
|
+
aws.my_key_pairs(name_filter)
|
805
|
+
end
|
806
|
+
end
|
807
|
+
|
808
|
+
describe '#delete_key_pair' do
|
809
|
+
let( :region ) { double('region', :name => 'test_region_name') }
|
810
|
+
|
811
|
+
it 'calls delete on a keypair if it exists' do
|
812
|
+
pair_name = 'pair1'
|
813
|
+
kp_mock = double('keypair', :exists? => true)
|
814
|
+
expect( kp_mock ).to receive( :delete ).once
|
815
|
+
pairs = { pair_name => kp_mock }
|
816
|
+
allow( region ).to receive( :key_pairs ).and_return( pairs )
|
817
|
+
aws.delete_key_pair(region, pair_name)
|
818
|
+
end
|
819
|
+
|
820
|
+
it 'skips delete on a keypair if it does not exist' do
|
821
|
+
pair_name = 'pair1'
|
822
|
+
kp_mock = double('keypair', :exists? => false)
|
823
|
+
expect( kp_mock ).to receive( :delete ).never
|
824
|
+
pairs = { pair_name => kp_mock }
|
825
|
+
allow( region ).to receive( :key_pairs ).and_return( pairs )
|
826
|
+
aws.delete_key_pair(region, pair_name)
|
827
|
+
end
|
828
|
+
end
|
829
|
+
|
830
|
+
describe '#create_new_key_pair' do
|
831
|
+
let(:region) { double('region', :name => 'test_region_name') }
|
832
|
+
let(:ssh_string) { 'ssh_string_test_0867' }
|
833
|
+
let(:pairs) { double('keypairs') }
|
834
|
+
let(:pair) { double('keypair') }
|
835
|
+
let(:pair_name) { 'pair_name_1555432' }
|
836
|
+
|
837
|
+
before :each do
|
838
|
+
allow(aws).to receive(:public_key).and_return(ssh_string)
|
839
|
+
expect(pairs).to receive(:import).with(pair_name, ssh_string)
|
840
|
+
expect(pairs).to receive(:[]).with(pair_name).and_return(pair)
|
841
|
+
expect(region).to receive(:key_pairs).and_return(pairs).twice
|
842
|
+
end
|
843
|
+
|
844
|
+
it 'imports the key given from public_key' do
|
845
|
+
expect(pair).to receive(:exists?).and_return(true)
|
846
|
+
aws.create_new_key_pair(region, pair_name)
|
847
|
+
end
|
848
|
+
|
849
|
+
it 'raises an exception if subsequent keypair check is false' do
|
850
|
+
expect(pair).to receive(:exists?).and_return(false).exactly(5).times
|
851
|
+
expect(aws).to receive(:backoff_sleep).exactly(5).times
|
852
|
+
expect { aws.create_new_key_pair(region, pair_name) }.
|
853
|
+
to raise_error(RuntimeError,
|
854
|
+
"AWS key pair #{pair_name} can not be queried, even after import")
|
855
|
+
end
|
856
|
+
end
|
857
|
+
|
858
|
+
describe '#group_id' do
|
859
|
+
it 'should return a predicatable group_id from a port list' do
|
860
|
+
expect(aws.group_id([22, 1024])).to eq("Beaker-2799478787")
|
861
|
+
end
|
862
|
+
|
863
|
+
it 'should return a predicatable group_id from an empty list' do
|
864
|
+
expect { aws.group_id([]) }.to raise_error(ArgumentError, "Ports list cannot be nil or empty")
|
865
|
+
end
|
866
|
+
end
|
867
|
+
|
868
|
+
describe '#ensure_group' do
|
869
|
+
let( :vpc ) { double('vpc') }
|
870
|
+
let( :ports ) { [22, 80, 8080] }
|
871
|
+
subject(:ensure_group) { aws.ensure_group(vpc, ports) }
|
872
|
+
|
873
|
+
context 'for an existing group' do
|
874
|
+
before :each do
|
875
|
+
@group = double(:nil? => false)
|
876
|
+
end
|
877
|
+
|
878
|
+
it 'returns group from vpc lookup' do
|
879
|
+
expect(vpc).to receive_message_chain('security_groups.filter.first').and_return(@group)
|
880
|
+
expect(ensure_group).to eq(@group)
|
881
|
+
end
|
882
|
+
|
883
|
+
context 'during group lookup' do
|
884
|
+
it 'performs group_id lookup for ports' do
|
885
|
+
expect(aws).to receive(:group_id).with(ports)
|
886
|
+
expect(vpc).to receive_message_chain('security_groups.filter.first').and_return(@group)
|
887
|
+
expect(ensure_group).to eq(@group)
|
888
|
+
end
|
889
|
+
|
890
|
+
it 'filters on group_id' do
|
891
|
+
expect(vpc).to receive(:security_groups).and_return(vpc)
|
892
|
+
expect(vpc).to receive(:filter).with('group-name', 'Beaker-1521896090').and_return(vpc)
|
893
|
+
expect(vpc).to receive(:first).and_return(@group)
|
894
|
+
expect(ensure_group).to eq(@group)
|
895
|
+
end
|
896
|
+
end
|
897
|
+
end
|
898
|
+
|
899
|
+
context 'when group does not exist' do
|
900
|
+
it 'creates group if group.nil?' do
|
901
|
+
group = double(:nil? => true)
|
902
|
+
expect(aws).to receive(:create_group).with(vpc, ports).and_return(group)
|
903
|
+
expect(vpc).to receive_message_chain('security_groups.filter.first').and_return(group)
|
904
|
+
expect(ensure_group).to eq(group)
|
905
|
+
end
|
906
|
+
end
|
907
|
+
end
|
908
|
+
|
909
|
+
describe '#create_group' do
|
910
|
+
let( :rv ) { double('rv') }
|
911
|
+
let( :ports ) { [22, 80, 8080] }
|
912
|
+
subject(:create_group) { aws.create_group(rv, ports) }
|
913
|
+
|
914
|
+
before :each do
|
915
|
+
@group = double(:nil? => false)
|
916
|
+
end
|
917
|
+
|
918
|
+
it 'returns a newly created group' do
|
919
|
+
allow(rv).to receive_message_chain('security_groups.create').and_return(@group)
|
920
|
+
allow(@group).to receive(:authorize_ingress).at_least(:once)
|
921
|
+
expect(create_group).to eq(@group)
|
922
|
+
end
|
923
|
+
|
924
|
+
it 'requests group_id for ports given' do
|
925
|
+
expect(aws).to receive(:group_id).with(ports)
|
926
|
+
allow(rv).to receive_message_chain('security_groups.create').and_return(@group)
|
927
|
+
allow(@group).to receive(:authorize_ingress).at_least(:once)
|
928
|
+
expect(create_group).to eq(@group)
|
929
|
+
end
|
930
|
+
|
931
|
+
it 'creates group with expected arguments' do
|
932
|
+
group_name = "Beaker-1521896090"
|
933
|
+
group_desc = "Custom Beaker security group for #{ports.to_a}"
|
934
|
+
expect(rv).to receive_message_chain('security_groups.create')
|
935
|
+
.with(group_name, :description => group_desc)
|
936
|
+
.and_return(@group)
|
937
|
+
allow(@group).to receive(:authorize_ingress).at_least(:once)
|
938
|
+
expect(create_group).to eq(@group)
|
939
|
+
end
|
940
|
+
|
941
|
+
it 'authorizes requested ports for group' do
|
942
|
+
expect(rv).to receive_message_chain('security_groups.create').and_return(@group)
|
943
|
+
ports.each do |port|
|
944
|
+
expect(@group).to receive(:authorize_ingress).with(:tcp, port).once
|
945
|
+
end
|
946
|
+
expect(create_group).to eq(@group)
|
947
|
+
end
|
948
|
+
end
|
949
|
+
|
950
|
+
describe '#load_fog_credentials' do
|
951
|
+
# Receive#and_call_original below allows us to test the core load_fog_credentials method
|
952
|
+
let(:creds) { {:access_key => 'awskey', :secret_key => 'awspass'} }
|
953
|
+
let(:dot_fog) { '.fog' }
|
954
|
+
subject(:load_fog_credentials) { aws.load_fog_credentials(dot_fog) }
|
955
|
+
|
956
|
+
it 'returns loaded fog credentials' do
|
957
|
+
fog_hash = {:default => {:aws_access_key_id => 'awskey', :aws_secret_access_key => 'awspass'}}
|
958
|
+
expect(aws).to receive(:load_fog_credentials).and_call_original
|
959
|
+
expect(YAML).to receive(:load_file).and_return(fog_hash)
|
960
|
+
expect(load_fog_credentials).to eq(creds)
|
961
|
+
end
|
962
|
+
|
963
|
+
context 'raises errors' do
|
964
|
+
it 'if missing access_key credential' do
|
965
|
+
fog_hash = {:default => {:aws_secret_access_key => 'awspass'}}
|
966
|
+
err_text = "You must specify an aws_access_key_id in your .fog file (#{dot_fog}) for ec2 instances!"
|
967
|
+
expect(aws).to receive(:load_fog_credentials).and_call_original
|
968
|
+
expect(YAML).to receive(:load_file).and_return(fog_hash)
|
969
|
+
expect { load_fog_credentials }.to raise_error(err_text)
|
970
|
+
end
|
971
|
+
|
972
|
+
it 'if missing secret_key credential' do
|
973
|
+
dot_fog = '.fog'
|
974
|
+
fog_hash = {:default => {:aws_access_key_id => 'awskey'}}
|
975
|
+
err_text = "You must specify an aws_secret_access_key in your .fog file (#{dot_fog}) for ec2 instances!"
|
976
|
+
expect(aws).to receive(:load_fog_credentials).and_call_original
|
977
|
+
expect(YAML).to receive(:load_file).and_return(fog_hash)
|
978
|
+
expect { load_fog_credentials }.to raise_error(err_text)
|
979
|
+
end
|
980
|
+
end
|
981
|
+
end
|
982
|
+
|
983
|
+
describe 'test_split_install' do
|
984
|
+
it 'does not add port 8143 if master, dashboard and database are on the same host' do
|
985
|
+
@hosts = [@hosts[0]]
|
986
|
+
@hosts[0][:roles] = ["master", "dashboard", "database"]
|
987
|
+
allow(aws).to receive(:test_split_install)
|
988
|
+
expect(@hosts[0]).not_to have_key(:additional_ports)
|
989
|
+
aws
|
990
|
+
end
|
991
|
+
|
992
|
+
it 'does not add port 8143 if host does not have master, dashboard or database at all' do
|
993
|
+
@hosts = [@hosts[0]]
|
994
|
+
@hosts[0][:roles] = ["agent", "frictionless"]
|
995
|
+
allow(aws).to receive(:test_split_install)
|
996
|
+
expect(@hosts[0]).not_to have_key(:additional_ports)
|
997
|
+
aws
|
998
|
+
end
|
999
|
+
|
1000
|
+
it 'adds port 8143 to all the hosts for split install that has either master, dashboard or database' do
|
1001
|
+
@hosts = [@hosts[0], @hosts[1], @hosts[2], @hosts[3]]
|
1002
|
+
@hosts[0][:roles] = ["master"]
|
1003
|
+
@hosts[1][:roles] = ["dashboard"]
|
1004
|
+
@hosts[2][:roles] = ["database"]
|
1005
|
+
@hosts[3][:roles] = ["agent"]
|
1006
|
+
allow(aws).to receive(:test_split_install)
|
1007
|
+
expect(@hosts[0]).to have_key(:additional_ports)
|
1008
|
+
expect(@hosts[0][:additional_ports]).to include(8143)
|
1009
|
+
expect(@hosts[1]).to have_key(:additional_ports)
|
1010
|
+
expect(@hosts[1][:additional_ports]).to include(8143)
|
1011
|
+
expect(@hosts[2]).to have_key(:additional_ports)
|
1012
|
+
expect(@hosts[2][:additional_ports]).to include(8143)
|
1013
|
+
expect(@hosts[3]).not_to have_key(:additional_ports)
|
1014
|
+
aws
|
1015
|
+
end
|
1016
|
+
end
|
1017
|
+
end
|
1018
|
+
end
|