kitchen-ec2 2.2.2 → 2.3.0

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