kitchen-ec2 2.2.2 → 2.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.
@@ -1,797 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Author:: Tyler Ball (<tball@chef.io>)
4
- #
5
- # Copyright:: 2015-2018, Fletcher Nichol
6
- # Copyright:: 2016-2018, Chef Software, Inc.
7
- #
8
- # Licensed under the Apache License, Version 2.0 (the "License");
9
- # you may not use this file except in compliance with the License.
10
- # You may obtain a copy of the License at
11
- #
12
- # http://www.apache.org/licenses/LICENSE-2.0
13
- #
14
- # Unless required by applicable law or agreed to in writing, software
15
- # distributed under the License is distributed on an "AS IS" BASIS,
16
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
- # See the License for the specific language governing permissions and
18
- # limitations under the License.
19
-
20
- require "kitchen/driver/ec2"
21
- require "kitchen/provisioner/dummy"
22
- require "kitchen/transport/dummy"
23
- require "kitchen/verifier/dummy"
24
-
25
- describe Kitchen::Driver::Ec2 do
26
-
27
- let(:logged_output) { StringIO.new }
28
- let(:logger) { Logger.new(logged_output) }
29
- let(:config) do
30
- {
31
- :aws_ssh_key_id => "key",
32
- :image_id => "ami-1234567",
33
- :block_duration_minutes => 60,
34
- :subnet_id => "subnet-1234",
35
- :security_group_ids => ["sg-56789"],
36
- }
37
- end
38
- let(:platform) { Kitchen::Platform.new(:name => "fooos-99") }
39
- let(:transport) { Kitchen::Transport::Dummy.new }
40
- let(:provisioner) { Kitchen::Provisioner::Dummy.new }
41
- let(:generator) { instance_double(Kitchen::Driver::Aws::InstanceGenerator) }
42
- # There is too much name overlap I let creep in - my `client` is actually
43
- # a wrapper around the actual ec2 client
44
- let(:actual_client) { double("actual ec2 client") }
45
- let(:client) { double(Kitchen::Driver::Aws::Client, :client => actual_client) }
46
- let(:server) { double("aws server object") }
47
- let(:state) { {} }
48
-
49
- let(:driver) { Kitchen::Driver::Ec2.new(config) }
50
-
51
- let(:instance) do
52
- instance_double(
53
- Kitchen::Instance,
54
- :logger => logger,
55
- :transport => transport,
56
- :provisioner => provisioner,
57
- :platform => platform,
58
- :to_str => "str"
59
- )
60
- end
61
-
62
- before do
63
- allow(Kitchen::Driver::Aws::InstanceGenerator).to receive(:new).and_return(generator)
64
- allow(Kitchen::Driver::Aws::Client).to receive(:new).and_return(client)
65
- allow(driver).to receive(:windows_os?).and_return(false)
66
- allow(driver).to receive(:instance).and_return(instance)
67
- end
68
-
69
- it "driver api_version is 2" do
70
- expect(driver.diagnose_plugin[:api_version]).to eq(2)
71
- end
72
-
73
- it "plugin_version is set to Kitchen::Vagrant::VERSION" do
74
- expect(driver.diagnose_plugin[:version]).to eq(
75
- Kitchen::Driver::EC2_VERSION)
76
- end
77
-
78
- describe "default_config" do
79
- context "Windows" do
80
- let(:resource) { instance_double(::Aws::EC2::Resource, :image => image) }
81
- before do
82
- allow(driver).to receive(:windows_os?).and_return(true)
83
- allow(client).to receive(:resource).and_return(resource)
84
- allow(instance).to receive(:name).and_return("instance_name")
85
- end
86
- context "Windows 2016" do
87
- let(:image) do
88
- FakeImage.new(:name => "Windows_Server-2016-English-Full-Base-2017.01.11")
89
- end
90
- it "sets :user_data to something" do
91
- expect(driver[:user_data]).to include
92
- '$logfile=C:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Log\\kitchen-ec2.log'
93
- end
94
- end
95
- context "Windows 2012R2" do
96
- let(:image) do
97
- FakeImage.new(:name => "Windows_Server-2012-R2_RTM-English-64Bit-Base-2017.01.11")
98
- end
99
- it "sets :user_data to something" do
100
- expect(driver[:user_data]).to include
101
- '$logfile=C:\\Program Files\\Amazon\\Ec2ConfigService\\Logs\\kitchen-ec2.log'
102
- end
103
- end
104
- end
105
- end
106
-
107
- describe "#hostname" do
108
- let(:public_dns_name) { nil }
109
- let(:private_dns_name) { nil }
110
- let(:public_ip_address) { nil }
111
- let(:private_ip_address) { nil }
112
- let(:server) do
113
- double("server",
114
- :public_dns_name => public_dns_name,
115
- :private_dns_name => private_dns_name,
116
- :public_ip_address => public_ip_address,
117
- :private_ip_address => private_ip_address
118
- )
119
- end
120
-
121
- it "returns nil if all sources are nil" do
122
- expect(driver.hostname(server)).to eq(nil)
123
- end
124
-
125
- it "raises an error if provided an unknown interface" do
126
- expect { driver.hostname(server, "foobar") }.to raise_error(Kitchen::UserError)
127
- end
128
-
129
- shared_examples "an interface type provided" do
130
- it "returns public_dns_name when requested" do
131
- expect(driver.hostname(server, "dns")).to eq(public_dns_name)
132
- end
133
- it "returns public_ip_address when requested" do
134
- expect(driver.hostname(server, "public")).to eq(public_ip_address)
135
- end
136
- it "returns private_ip_address when requested" do
137
- expect(driver.hostname(server, "private")).to eq(private_ip_address)
138
- end
139
- it "returns private_dns_name when requested" do
140
- expect(driver.hostname(server, "private_dns")).to eq(private_dns_name)
141
- end
142
- end
143
-
144
- context "private_dns_name is populated" do
145
- let(:private_dns_name) { "private_dns_name" }
146
-
147
- it "returns the private_dns_name" do
148
- expect(driver.hostname(server)).to eq(private_dns_name)
149
- end
150
-
151
- include_examples "an interface type provided"
152
- end
153
-
154
- context "private_ip_address is populated" do
155
- let(:private_dns_name) { "private_dns_name" }
156
- let(:private_ip_address) { "10.0.0.1" }
157
-
158
- it "returns the private_ip_address" do
159
- expect(driver.hostname(server)).to eq(private_ip_address)
160
- end
161
-
162
- include_examples "an interface type provided"
163
- end
164
-
165
- context "public_ip_address is populated" do
166
- let(:private_dns_name) { "private_dns_name" }
167
- let(:private_ip_address) { "10.0.0.1" }
168
- let(:public_ip_address) { "127.0.0.1" }
169
-
170
- it "returns the public_ip_address" do
171
- expect(driver.hostname(server)).to eq(public_ip_address)
172
- end
173
-
174
- include_examples "an interface type provided"
175
- end
176
-
177
- context "public_dns_name is populated" do
178
- let(:private_dns_name) { "private_dns_name" }
179
- let(:private_ip_address) { "10.0.0.1" }
180
- let(:public_ip_address) { "127.0.0.1" }
181
- let(:public_dns_name) { "public_dns_name" }
182
-
183
- it "returns the public_dns_name" do
184
- expect(driver.hostname(server)).to eq(public_dns_name)
185
- end
186
-
187
- include_examples "an interface type provided"
188
- end
189
-
190
- context "public_dns_name returns as empty string" do
191
- let(:public_dns_name) { "" }
192
- it "returns nil" do
193
- expect(driver.hostname(server)).to eq(nil)
194
- end
195
-
196
- context "and private_ip_address is populated" do
197
- let(:private_ip_address) { "10.0.0.1" }
198
- it "returns the private_ip_address" do
199
- expect(driver.hostname(server)).to eq(private_ip_address)
200
- end
201
-
202
- context "and private_dns_name is populated" do
203
- let(:private_dns_name) { "private_dns_name" }
204
- it "returns the private_ip_address" do
205
- expect(driver.hostname(server)).to eq(private_ip_address)
206
- end
207
- end
208
- end
209
- end
210
- end
211
-
212
- describe "#submit_server" do
213
- before do
214
- expect(driver).to receive(:instance).at_least(:once).and_return(instance)
215
- end
216
-
217
- it "submits the server request" do
218
- expect(generator).to receive(:ec2_instance_data).and_return({})
219
- expect(client).to receive(:create_instance).with(:min_count => 1, :max_count => 1)
220
- driver.submit_server
221
- end
222
- end
223
-
224
- describe "submit_server with terminate shutdown behaviour" do
225
- before do
226
- config[:instance_initiated_shutdown_behavior] = "terminate"
227
- expect(driver).to receive(:instance).at_least(:once).and_return(instance)
228
- end
229
-
230
- it "submits the server request" do
231
- expect(generator).to receive(:ec2_instance_data).and_return(
232
- :instance_initiated_shutdown_behavior => "terminate"
233
- )
234
- expect(client).to receive(:create_instance).with(
235
- :min_count => 1, :max_count => 1, :instance_initiated_shutdown_behavior => "terminate"
236
- )
237
- driver.submit_server
238
- end
239
- end
240
-
241
- describe "#submit_spot" do
242
- let(:state) { {} }
243
- let(:response) do
244
- { :spot_instance_requests => [{ :spot_instance_request_id => "id" }] }
245
- end
246
-
247
- before do
248
- expect(driver).to receive(:instance).at_least(:once).and_return(instance)
249
- allow(Time).to receive(:now).and_return(Time.now)
250
- end
251
-
252
- it "submits the server request" do
253
- expect(generator).to receive(:ec2_instance_data).and_return({})
254
- expect(actual_client).to receive(:request_spot_instances).with(
255
- :spot_price => "",
256
- :launch_specification => {},
257
- :valid_until => Time.now + (config[:retryable_tries] * config[:retryable_sleep]),
258
- :block_duration_minutes => 60
259
- ).and_return(response)
260
- expect(actual_client).to receive(:wait_until)
261
- expect(client).to receive(:get_instance_from_spot_request).with("id")
262
- driver.submit_spot(state)
263
- expect(state).to eq(:spot_request_id => "id")
264
- end
265
- end
266
-
267
- describe "#tag_server" do
268
- context "with no tags specified" do
269
- it "does not raise" do
270
- config[:tags] = nil
271
- expect { driver.tag_server(server) }.not_to raise_error
272
- end
273
- end
274
-
275
- context "with standard string tags" do
276
- it "tags the server" do
277
- config[:tags] = { :key1 => "value1", :key2 => "value2" }
278
- expect(server).to receive(:create_tags).with(
279
- :tags => [
280
- { :key => :key1, :value => "value1" },
281
- { :key => :key2, :value => "value2" },
282
- ]
283
- )
284
- driver.tag_server(server)
285
- end
286
- end
287
-
288
- context "with a tag that includes a Integer value" do
289
- it "tags the server" do
290
- config[:tags] = { :key1 => "value1", :key2 => 1 }
291
- expect(server).to receive(:create_tags).with(
292
- :tags => [
293
- { :key => :key1, :value => "value1" },
294
- { :key => :key2, :value => "1" },
295
- ]
296
- )
297
- driver.tag_server(server)
298
- end
299
- end
300
-
301
- context "with a tag that includes a Nil value" do
302
- it "tags the server" do
303
- config[:tags] = { :key1 => "value1", :key2 => nil }
304
- expect(server).to receive(:create_tags).with(
305
- :tags => [
306
- { :key => :key1, :value => "value1" },
307
- { :key => :key2, :value => "" },
308
- ]
309
- )
310
- driver.tag_server(server)
311
- end
312
- end
313
- end
314
-
315
- describe "#tag_volumes" do
316
- let(:volume) { double("aws volume resource") }
317
- before do
318
- allow(server).to receive(:volumes).and_return([volume])
319
- end
320
- context "with standard string tags" do
321
- it "tags the instance volumes" do
322
- config[:tags] = { :key1 => "value1", :key2 => "value2" }
323
- expect(volume).to receive(:create_tags).with(
324
- :tags => [
325
- { :key => :key1, :value => "value1" },
326
- { :key => :key2, :value => "value2" },
327
- ]
328
- )
329
- driver.tag_volumes(server)
330
- end
331
- end
332
-
333
- context "with a tag that includes a Integer value" do
334
- it "tags the instance volumes" do
335
- config[:tags] = { :key1 => "value1", :key2 => 2 }
336
- expect(volume).to receive(:create_tags).with(
337
- :tags => [
338
- { :key => :key1, :value => "value1" },
339
- { :key => :key2, :value => "2" },
340
- ]
341
- )
342
- driver.tag_volumes(server)
343
- end
344
- end
345
-
346
- context "with a tag that includes a Nil value" do
347
- it "tags the instance volumes" do
348
- config[:tags] = { :key1 => "value1", :key2 => nil }
349
- expect(volume).to receive(:create_tags).with(
350
- :tags => [
351
- { :key => :key1, :value => "value1" },
352
- { :key => :key2, :value => "" },
353
- ]
354
- )
355
- driver.tag_volumes(server)
356
- end
357
- end
358
- end
359
-
360
- describe "#wait_until_ready" do
361
- let(:hostname) { "0.0.0.0" }
362
- let(:msg) { "to become ready" }
363
- let(:aws_instance) { double("aws instance") }
364
-
365
- before do
366
- config[:interface] = :i
367
- expect(driver).to receive(:wait_with_destroy).with(server, state, msg).and_yield(aws_instance)
368
- expect(driver).to receive(:hostname).with(aws_instance, :i).and_return(hostname)
369
- end
370
-
371
- after do
372
- expect(state[:hostname]).to eq(hostname)
373
- end
374
-
375
- it "first checks instance existence" do
376
- expect(aws_instance).to receive(:exists?).and_return(false)
377
- expect(driver.wait_until_ready(server, state)).to eq(false)
378
- end
379
-
380
- it "second checks instance state" do
381
- expect(aws_instance).to receive(:exists?).and_return(true)
382
- expect(aws_instance).to receive_message_chain("state.name").and_return("nope")
383
- expect(driver.wait_until_ready(server, state)).to eq(false)
384
- end
385
-
386
- it "third checks hostname" do
387
- expect(aws_instance).to receive(:exists?).and_return(true)
388
- expect(aws_instance).to receive_message_chain("state.name").and_return("running")
389
- expect(driver.wait_until_ready(server, state)).to eq(false)
390
- end
391
-
392
- context "when it exists, has a valid state and a valid hostname" do
393
- let(:hostname) { "host" }
394
-
395
- it "returns true" do
396
- expect(aws_instance).to receive(:exists?).and_return(true)
397
- expect(aws_instance).to receive_message_chain("state.name").and_return("running")
398
- expect(driver.wait_until_ready(server, state)).to eq(true)
399
- end
400
- end
401
- end
402
-
403
- describe "#wait_until_volumes_ready" do
404
- let(:aws_instance) { double("aws instance") }
405
- let(:msg) { "volumes to be ready" }
406
- let(:volume) { double("aws volume resource") }
407
-
408
- before do
409
- expect(driver).to receive(:wait_with_destroy).with(server, state, msg).and_yield(aws_instance)
410
- end
411
- it "first checks instance existence" do
412
- expect(aws_instance).to receive(:exists?).and_return(false)
413
- expect(driver.wait_until_volumes_ready(server, state)).to eq(false)
414
- end
415
- it "second, it checks for prescence of described volumes" do
416
- expect(aws_instance).to receive(:exists?).and_return(true)
417
- expect(actual_client).to receive_message_chain(:describe_volumes, :volumes, :length
418
- ).and_return(0)
419
- expect(aws_instance).to receive(:volumes).and_return([])
420
- expect(driver.wait_until_volumes_ready(server, state)).to eq(false)
421
- end
422
- it "third, it compares the described volumes and instance volumes" do
423
- expect(aws_instance).to receive(:exists?).and_return(true)
424
- expect(actual_client).to receive_message_chain(:describe_volumes, :volumes, :length
425
- ).and_return(2)
426
- expect(aws_instance).to receive(:volumes).and_return([volume])
427
- expect(driver.wait_until_volumes_ready(server, state)).to eq(false)
428
- end
429
- context "when it exists, and both client and instance agree on volumes" do
430
- it "returns true" do
431
- expect(aws_instance).to receive(:exists?).and_return(true)
432
- expect(actual_client).to receive_message_chain(:describe_volumes, :volumes, :length
433
- ).and_return(1)
434
- expect(aws_instance).to receive(:volumes).and_return([volume])
435
- expect(driver.wait_until_volumes_ready(server, state)).to eq(true)
436
- end
437
- end
438
- end
439
-
440
- describe "#fetch_windows_admin_password" do
441
- let(:msg) { "to fetch windows admin password" }
442
- let(:aws_instance) { double("aws instance") }
443
- let(:server_id) { "server_id" }
444
- let(:encrypted_password) { "alksdofw" }
445
- let(:data) { double("data", :password_data => encrypted_password) }
446
- let(:password) { "password" }
447
- let(:transport) { { :ssh_key => "foo" } }
448
-
449
- before do
450
- state[:server_id] = server_id
451
- expect(driver).to receive(:wait_with_destroy).with(server, state, msg).and_yield(aws_instance)
452
- end
453
-
454
- after do
455
- expect(state[:password]).to eq(password)
456
- end
457
-
458
- it "fetches and decrypts the windows password" do
459
- expect(server).to receive_message_chain("client.get_password_data").with(
460
- :instance_id => server_id
461
- ).and_return(data)
462
- expect(server).to receive(:decrypt_windows_password).
463
- with(File.expand_path("foo")).
464
- and_return(password)
465
- driver.fetch_windows_admin_password(server, state)
466
- end
467
-
468
- end
469
-
470
- describe "#wait_with_destroy" do
471
- let(:tries) { 111 }
472
- let(:sleep) { 222 }
473
- let(:msg) { "msg" }
474
- given_block = lambda { ; }
475
-
476
- before do
477
- config[:retryable_sleep] = sleep
478
- config[:retryable_tries] = tries
479
- end
480
-
481
- it "calls wait and exits successfully if there is no error" do
482
- expect(server).to receive(:wait_until) do |args, &block|
483
- expect(args[:max_attempts]).to eq(tries)
484
- expect(args[:delay]).to eq(sleep)
485
- expect(block).to eq(given_block)
486
- expect(driver).to receive(:info).with(/#{msg}/)
487
- args[:before_attempt].call(0)
488
- end
489
- driver.wait_with_destroy(server, state, msg, &given_block)
490
- end
491
-
492
- it "attempts to destroy the instance if the waiter fails" do
493
- expect(server).to receive(:wait_until).and_raise(::Aws::Waiters::Errors::WaiterFailed)
494
- expect(driver).to receive(:destroy).with(state)
495
- expect(driver).to receive(:error).with(/#{msg}/)
496
- expect do
497
- driver.wait_with_destroy(server, state, msg, &given_block)
498
- end.to raise_error(::Aws::Waiters::Errors::WaiterFailed)
499
- end
500
- end
501
-
502
- describe "#create_key" do
503
- context "creates a key pair via the ec2 API, saves the generated key locally" do
504
- before do
505
- config[:kitchen_root] = "/kitchen"
506
- config.delete(:aws_ssh_key_id)
507
- allow(instance).to receive(:name).and_return("instance_name")
508
-
509
- expect(actual_client).to receive(:create_key_pair).with(key_name: /kitchen-/).and_return(double(key_name: "expected-key-name", key_material: "RSA PRIVATE KEY"))
510
- fake_file = double()
511
- allow(File).to receive(:open).and_call_original
512
- expect(File).to receive(:open).with("/kitchen/.kitchen/instance_name.pem", kind_of(Numeric), kind_of(Numeric)).and_yield(fake_file)
513
- expect(fake_file).to receive(:write).with("RSA PRIVATE KEY")
514
- end
515
-
516
- it "generates a temporary SSH key pair for the instance" do
517
- driver.send(:create_key, state)
518
- expect(state[:auto_key_id]).to eq("expected-key-name")
519
- expect(state[:ssh_key]).to eq("/kitchen/.kitchen/instance_name.pem")
520
- end
521
- end
522
- end
523
-
524
- describe "#create" do
525
- let(:server) { double("aws server object", :id => id, :image_id => "ami-3f807145") }
526
- let(:id) { "i-12345" }
527
-
528
- it "returns if the instance is already created" do
529
- state[:server_id] = id
530
- expect(driver.create(state)).to eq(nil)
531
- end
532
-
533
- image_data = Aws::EC2::Types::Image.new(:root_device_type => "ebs")
534
- ec2_stub = Aws::EC2::Types::DescribeImagesResult.new
535
- ec2_stub.images = [image_data]
536
-
537
- shared_examples "common create" do
538
- it "successfully creates and tags the instance" do
539
- expect(server).to receive(:wait_until_exists)
540
- expect(driver).to receive(:update_username)
541
- expect(driver).to receive(:tag_server).with(server)
542
- expect(driver).to receive(:tag_volumes).with(server)
543
- expect(driver).to receive(:wait_until_volumes_ready).with(server, state)
544
- expect(driver).to receive(:wait_until_ready).with(server, state)
545
- allow(actual_client).to receive(:describe_images).with({ :image_ids => [server.image_id] }).and_return(ec2_stub)
546
- expect(transport).to receive_message_chain("connection.wait_until_ready")
547
- driver.create(state)
548
- expect(state[:server_id]).to eq(id)
549
- end
550
- end
551
-
552
- context "chef provisioner" do
553
- let(:provisioner) { double("chef provisioner", :name => "chef_solo") }
554
-
555
- before do
556
- expect(driver).to receive(:create_ec2_json).with(state)
557
- expect(driver).to receive(:submit_server).and_return(server)
558
- end
559
-
560
- include_examples "common create"
561
- end
562
-
563
- context "non-windows on-demand instance" do
564
- before do
565
- expect(driver).to receive(:submit_server).and_return(server)
566
- end
567
-
568
- include_examples "common create"
569
- end
570
-
571
- context "config is for a spot instance" do
572
- before do
573
- config[:spot_price] = 1
574
- expect(driver).to receive(:submit_spot).with(state).and_return(server)
575
- end
576
-
577
- include_examples "common create"
578
- end
579
-
580
- context "instance is not ebs-backed" do
581
- before do
582
- ec2_stub.images[0].root_device_type = "instance-store"
583
- end
584
-
585
- it "does not tag volumes or wait for volumes to be ready" do
586
- expect(driver).to_not receive(:tag_volumes).with(server)
587
- expect(driver).to_not receive(:wait_until_volumes_ready).with(server, state)
588
- end
589
-
590
- after do
591
- ec2_stub.images[0].root_device_type = "ebs"
592
- end
593
- end
594
-
595
- context "instance is a windows machine" do
596
- before do
597
- expect(driver).to receive(:windows_os?).and_return(true)
598
- expect(transport).to receive(:[]).with(:username).and_return("administrator")
599
- expect(transport).to receive(:[]).with(:password).and_return(nil)
600
- expect(driver).to receive(:submit_server).and_return(server)
601
- expect(driver).to receive(:fetch_windows_admin_password).with(server, state)
602
- end
603
-
604
- include_examples "common create"
605
- end
606
-
607
- context "instance is not a standard platform" do
608
- let(:state) { {} }
609
- before do
610
- expect(driver).to receive(:actual_platform).and_return(nil)
611
- end
612
-
613
- it "doesn't set the state username" do
614
- driver.update_username(state)
615
- expect(state).to eq({})
616
- end
617
- end
618
-
619
- context "with no security group specified" do
620
- before do
621
- config.delete(:security_group_ids)
622
- expect(driver).to receive(:submit_server).and_return(server)
623
- allow(instance).to receive(:name).and_return("instance_name")
624
- end
625
-
626
- context "with a subnet configured" do
627
- before do
628
- expect(actual_client).to receive(:describe_subnets).with(filters: [{ name: "subnet-id", values: ["subnet-1234"] }]).and_return(double(subnets: [double(vpc_id: "vpc-1")]))
629
- expect(actual_client).to receive(:create_security_group).with(group_name: /kitchen-/, description: /Test Kitchen for/, vpc_id: "vpc-1").and_return(double(group_id: "sg-9876"))
630
- expect(actual_client).to receive(:authorize_security_group_ingress).with(group_id: "sg-9876", ip_permissions: [
631
- { ip_protocol: "tcp", from_port: 22, to_port: 22, ip_ranges: [{ cidr_ip: "0.0.0.0/0" }] },
632
- { ip_protocol: "tcp", from_port: 5985, to_port: 5985, ip_ranges: [{ cidr_ip: "0.0.0.0/0" }] },
633
- { ip_protocol: "tcp", from_port: 5986, to_port: 5986, ip_ranges: [{ cidr_ip: "0.0.0.0/0" }] },
634
- ])
635
- end
636
-
637
- include_examples "common create"
638
- end
639
-
640
- context "with a default VPC" do
641
- before do
642
- config.delete(:subnet_id)
643
- expect(actual_client).to receive(:describe_vpcs).with(filters: [{ name: "isDefault", values: ["true"] }]).and_return(double(vpcs: [double(vpc_id: "vpc-1")]))
644
- expect(actual_client).to receive(:create_security_group).with(group_name: /kitchen-/, description: /Test Kitchen for/, vpc_id: "vpc-1").and_return(double(group_id: "sg-9876"))
645
- expect(actual_client).to receive(:authorize_security_group_ingress).with(group_id: "sg-9876", ip_permissions: [
646
- { ip_protocol: "tcp", from_port: 22, to_port: 22, ip_ranges: [{ cidr_ip: "0.0.0.0/0" }] },
647
- { ip_protocol: "tcp", from_port: 5985, to_port: 5985, ip_ranges: [{ cidr_ip: "0.0.0.0/0" }] },
648
- { ip_protocol: "tcp", from_port: 5986, to_port: 5986, ip_ranges: [{ cidr_ip: "0.0.0.0/0" }] },
649
- ])
650
- end
651
-
652
- include_examples "common create"
653
- end
654
-
655
- context "without a default VPC" do
656
- before do
657
- config.delete(:subnet_id)
658
- expect(actual_client).to receive(:describe_vpcs).with(filters: [{ name: "isDefault", values: ["true"] }]).and_return(double(vpcs: []))
659
- expect(actual_client).to receive(:create_security_group).with(group_name: /kitchen-/, description: /Test Kitchen for/).and_return(double(group_id: "sg-9876"))
660
- expect(actual_client).to receive(:authorize_security_group_ingress).with(group_id: "sg-9876", ip_permissions: [
661
- { ip_protocol: "tcp", from_port: 22, to_port: 22, ip_ranges: [{ cidr_ip: "0.0.0.0/0" }] },
662
- { ip_protocol: "tcp", from_port: 5985, to_port: 5985, ip_ranges: [{ cidr_ip: "0.0.0.0/0" }] },
663
- { ip_protocol: "tcp", from_port: 5986, to_port: 5986, ip_ranges: [{ cidr_ip: "0.0.0.0/0" }] },
664
- ])
665
- end
666
-
667
- include_examples "common create"
668
- end
669
- end
670
-
671
- context "with no security group but filter specified" do
672
- before do
673
- config.delete(:security_group_ids)
674
- config[:security_group_filter] = { tag: "SomeTag", value: "SomeValue" }
675
- expect(driver).not_to receive(:create_security_group)
676
- expect(driver).to receive(:submit_server).and_return(server)
677
- allow(instance).to receive(:name).and_return("instance_name")
678
- end
679
-
680
- include_examples "common create"
681
- end
682
-
683
- context "and AWS SSH keys" do
684
- before do
685
- allow(driver).to receive(:submit_server).and_return(server)
686
- allow(instance).to receive(:name).and_return("instance_name")
687
- end
688
-
689
- context "with no AWS-managed ssh key pair configured, creates a key pair to use" do
690
- before do
691
- config[:aws_ssh_key_id] = nil
692
- expect(driver).to receive(:create_key)
693
- state[:auto_key_id] = "autogenerated_by_create_key"
694
- end
695
-
696
- after do
697
- expect(config[:aws_ssh_key_id]).to eq("autogenerated_by_create_key")
698
- end
699
-
700
- include_examples "common create"
701
- end
702
-
703
- context "with AWS-managed ssh key pair disabled, does not create a key pair or pass a key id" do
704
- before do
705
- config[:aws_ssh_key_id] = "_disable"
706
- expect(driver).to_not receive(:create_key)
707
- end
708
-
709
- after do
710
- expect(config[:aws_ssh_key_id]).to be_nil
711
- end
712
-
713
- include_examples "common create"
714
- end
715
-
716
- context "with AWS ssh key pair set, uses set key and does not create a key pair" do
717
- before do
718
- config[:aws_ssh_key_id] = "use_this_key_please"
719
- expect(driver).to_not receive(:create_key)
720
- end
721
-
722
- after do
723
- expect(config[:aws_ssh_key_id]).to eq("use_this_key_please")
724
- end
725
-
726
- include_examples "common create"
727
- end
728
- end
729
- end
730
-
731
- describe "#destroy" do
732
- context "when state[:server_id] is nil" do
733
- it "returns nil" do
734
- expect(driver.destroy(state)).to eq(nil)
735
- end
736
- end
737
-
738
- context "when state has a normal server_id" do
739
- let(:state) { { :server_id => "id", :hostname => "name" } }
740
-
741
- context "the server is already destroyed" do
742
- it "does nothing" do
743
- expect(client).to receive(:get_instance).with("id").and_return nil
744
- driver.destroy(state)
745
- expect(state).to eq({})
746
- end
747
- end
748
-
749
- it "destroys the server" do
750
- expect(client).to receive(:get_instance).with("id").and_return(server)
751
- expect(instance).to receive_message_chain("transport.connection.close")
752
- expect(server).to receive(:terminate)
753
- driver.destroy(state)
754
- expect(state).to eq({})
755
- end
756
- end
757
-
758
- context "when state has a spot request" do
759
- let(:state) { { :server_id => "id", :hostname => "name", :spot_request_id => "spot" } }
760
-
761
- it "destroys the server" do
762
- expect(client).to receive(:get_instance).with("id").and_return(server)
763
- expect(instance).to receive_message_chain("transport.connection.close")
764
- expect(server).to receive(:terminate)
765
- expect(actual_client).to receive(:cancel_spot_instance_requests).with(
766
- :spot_instance_request_ids => ["spot"]
767
- )
768
- driver.destroy(state)
769
- expect(state).to eq({})
770
- end
771
- end
772
-
773
- context "when the state has an automatic security group" do
774
- let(:state) { { auto_security_group_id: "sg-asdf" } }
775
-
776
- it "destroys the security group" do
777
- expect(actual_client).to receive(:delete_security_group).with(group_id: "sg-asdf")
778
- driver.destroy(state)
779
- expect(state).to eq({})
780
- end
781
- end
782
-
783
- context "when the state has an automatic key pair" do
784
- let(:state) { { auto_key_id: "kitchen-asdf" } }
785
-
786
- it "destroys the key pair" do
787
- config[:kitchen_root] = "/kitchen"
788
- allow(instance).to receive(:name).and_return("instance_name")
789
- expect(actual_client).to receive(:delete_key_pair).with(key_name: "kitchen-asdf")
790
- expect(File).to receive(:unlink).with("/kitchen/.kitchen/instance_name.pem")
791
- driver.destroy(state)
792
- expect(state).to eq({})
793
- end
794
- end
795
- end
796
-
797
- end