kitchen-ec2 3.6.0 → 3.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/kitchen/driver/aws/client.rb +0 -1
- data/lib/kitchen/driver/aws/instance_generator.rb +18 -5
- data/lib/kitchen/driver/aws/standard_platform.rb +2 -2
- data/lib/kitchen/driver/aws/standard_platform/amazon.rb +1 -1
- data/lib/kitchen/driver/aws/standard_platform/amazon2.rb +1 -1
- data/lib/kitchen/driver/aws/standard_platform/centos.rb +26 -3
- data/lib/kitchen/driver/aws/standard_platform/debian.rb +3 -3
- data/lib/kitchen/driver/aws/standard_platform/fedora.rb +1 -1
- data/lib/kitchen/driver/aws/standard_platform/freebsd.rb +1 -1
- data/lib/kitchen/driver/aws/standard_platform/rhel.rb +8 -1
- data/lib/kitchen/driver/aws/standard_platform/ubuntu.rb +1 -1
- data/lib/kitchen/driver/aws/standard_platform/windows.rb +1 -1
- data/lib/kitchen/driver/ec2.rb +84 -126
- data/lib/kitchen/driver/ec2_version.rb +1 -2
- metadata +7 -133
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aac8aebec145ee67e00276453fd2f8a1aaae0466d58bec03ffdc8b368f001118
|
4
|
+
data.tar.gz: f14c9b4f85a0ebd1bf5c6398efc54b93e195e465ef4fc1c944688f96f53f1d39
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d1e8f020cde0872c27abade96517dae1dcafa5d50aa4b08245ec928adfc024e309cc1977e5bdaebb30f3dfcea1f463ee01dabfe62baf4a0640b8bce527aa80b4
|
7
|
+
data.tar.gz: 958a08022889c1bef5e0becc8cd75d53b5a0cd68445043c0c934bdc9a03822afcd9cc6f6dc49f15fe63928933f61f6d383d3b3bd3b7ad278d851f2c4957726a1
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
1
|
#
|
3
2
|
# Author:: Tyler Ball (<tball@chef.io>)
|
4
3
|
#
|
@@ -17,7 +16,7 @@
|
|
17
16
|
# See the License for the specific language governing permissions and
|
18
17
|
# limitations under the License.
|
19
18
|
|
20
|
-
require "base64"
|
19
|
+
require "base64" unless defined?(Base64)
|
21
20
|
require "aws-sdk-ec2"
|
22
21
|
|
23
22
|
module Kitchen
|
@@ -59,7 +58,7 @@ module Kitchen
|
|
59
58
|
raise "The subnet tagged '#{config[:subnet_filter][:tag]}:#{config[:subnet_filter][:value]}' does not exist!" unless subnets.any?
|
60
59
|
|
61
60
|
# => Select the least-populated subnet if we have multiple matches
|
62
|
-
subnet = subnets.
|
61
|
+
subnet = subnets.max_by { |s| s[:available_ip_address_count] }
|
63
62
|
vpc_id = subnet.vpc_id
|
64
63
|
config[:subnet_id] = subnet.subnet_id
|
65
64
|
end
|
@@ -115,11 +114,25 @@ module Kitchen
|
|
115
114
|
key_name: config[:aws_ssh_key_id],
|
116
115
|
subnet_id: config[:subnet_id],
|
117
116
|
private_ip_address: config[:private_ip_address],
|
117
|
+
min_count: 1,
|
118
|
+
max_count: 1,
|
118
119
|
}
|
119
120
|
|
121
|
+
if config[:tags] && !config[:tags].empty?
|
122
|
+
tags = config[:tags].map do |k, v|
|
123
|
+
# we convert the value to a string because
|
124
|
+
# nils should be passed as an empty String
|
125
|
+
# and Integers need to be represented as Strings
|
126
|
+
{ key: k, value: v.to_s }
|
127
|
+
end
|
128
|
+
instance_tag_spec = { resource_type: "instance", tags: tags }
|
129
|
+
volume_tag_spec = { resource_type: "volume", tags: tags }
|
130
|
+
i[:tag_specifications] = [instance_tag_spec, volume_tag_spec]
|
131
|
+
end
|
132
|
+
|
120
133
|
availability_zone = config[:availability_zone]
|
121
134
|
if availability_zone
|
122
|
-
if
|
135
|
+
if /^[a-z]$/i.match?(availability_zone)
|
123
136
|
availability_zone = "#{config[:region]}#{availability_zone}"
|
124
137
|
end
|
125
138
|
i[:placement] = { availability_zone: availability_zone.downcase }
|
@@ -162,7 +175,7 @@ module Kitchen
|
|
162
175
|
end
|
163
176
|
availability_zone = config[:availability_zone]
|
164
177
|
if availability_zone
|
165
|
-
if
|
178
|
+
if /^[a-z]$/i.match?(availability_zone)
|
166
179
|
availability_zone = "#{config[:region]}#{availability_zone}"
|
167
180
|
end
|
168
181
|
i[:placement] = { availability_zone: availability_zone.downcase }
|
@@ -210,10 +210,10 @@ module Kitchen
|
|
210
210
|
images = images.sort_by(&:creation_date).reverse
|
211
211
|
# P5: We prefer x86_64 over i386 (if available)
|
212
212
|
images = prefer(images) { |image| image.architecture == "x86_64" }
|
213
|
-
# P4: We prefer
|
213
|
+
# P4: We prefer (SSD) (if available)
|
214
214
|
images = prefer(images) do |image|
|
215
215
|
image.block_device_mappings.any? do |b|
|
216
|
-
b.device_name == image.root_device_name && b.ebs && b.ebs.volume_type ==
|
216
|
+
b.device_name == image.root_device_name && b.ebs && %w{gp3 gp2}.any? { |t| b.ebs.volume_type == t }
|
217
217
|
end
|
218
218
|
end
|
219
219
|
# P3: We prefer ebs over instance_store (if available)
|
@@ -23,6 +23,14 @@ module Kitchen
|
|
23
23
|
class Centos < StandardPlatform
|
24
24
|
StandardPlatform.platforms["centos"] = self
|
25
25
|
|
26
|
+
CENTOS_OWNER_ID = "125523088429".freeze
|
27
|
+
PRODUCT_CODES = {
|
28
|
+
"6" => "6x5jmcajty9edm3f211pqjfn2",
|
29
|
+
"7" => "aw0evgkw8e5c1q413zgy5pjce",
|
30
|
+
# It appears that v8 is not published to the
|
31
|
+
# AWS marketplace and hence does not have a product code
|
32
|
+
}.freeze
|
33
|
+
|
26
34
|
# default username for this platform's ami
|
27
35
|
# @return [String]
|
28
36
|
def username
|
@@ -34,10 +42,25 @@ module Kitchen
|
|
34
42
|
end
|
35
43
|
|
36
44
|
def image_search
|
45
|
+
# Version 8+ are published directly, not to the AWS marketplace. Use OWNER ID.
|
37
46
|
search = {
|
38
|
-
"owner-
|
39
|
-
"name" => ["CentOS
|
47
|
+
"owner-id" => CENTOS_OWNER_ID,
|
48
|
+
"name" => ["CentOS #{version}*", "CentOS-#{version}*-GA-*"],
|
40
49
|
}
|
50
|
+
|
51
|
+
if version && version.split(".").first.to_i < 8
|
52
|
+
# Versions <8 are published to the AWS marketplace and use a different naming convention
|
53
|
+
search = {
|
54
|
+
"owner-alias" => "aws-marketplace",
|
55
|
+
"name" => ["CentOS Linux #{version}*", "CentOS-#{version}*-GA-*"],
|
56
|
+
}
|
57
|
+
# For versions published to aws-marketplace, additionally filter on product code to
|
58
|
+
# avoid non-official AMIs. Can't use CentOS owner ID here, as the owner ID is that of aws marketplace.
|
59
|
+
# https://github.com/test-kitchen/kitchen-ec2/issues/456
|
60
|
+
PRODUCT_CODES.keys.each do |major_version|
|
61
|
+
search["product-code"] = PRODUCT_CODES[major_version] if version.start_with?(major_version)
|
62
|
+
end
|
63
|
+
end
|
41
64
|
search["architecture"] = architecture if architecture
|
42
65
|
search
|
43
66
|
end
|
@@ -52,7 +75,7 @@ module Kitchen
|
|
52
75
|
end
|
53
76
|
|
54
77
|
def self.from_image(driver, image)
|
55
|
-
if
|
78
|
+
if /centos/i.match?(image.name)
|
56
79
|
image.name =~ /\b(\d+(\.\d+)?)\b/i
|
57
80
|
new(driver, "centos", (Regexp.last_match || [])[1], image.architecture)
|
58
81
|
end
|
@@ -23,8 +23,8 @@ module Kitchen
|
|
23
23
|
class Debian < StandardPlatform
|
24
24
|
StandardPlatform.platforms["debian"] = self
|
25
25
|
|
26
|
-
#
|
27
|
-
# and
|
26
|
+
# 11/12 are listed last since we default to the first item in the hash
|
27
|
+
# and 11/12 are not released yet. When they're released move them up
|
28
28
|
DEBIAN_CODENAMES = {
|
29
29
|
10 => "buster",
|
30
30
|
9 => "stretch",
|
@@ -60,7 +60,7 @@ module Kitchen
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def self.from_image(driver, image)
|
63
|
-
if
|
63
|
+
if /debian/i.match?(image.name)
|
64
64
|
image.name =~ /\b(\d+|#{DEBIAN_CODENAMES.values.join("|")})\b/i
|
65
65
|
version = (Regexp.last_match || [])[1]
|
66
66
|
if version && version.to_i == 0
|
@@ -45,11 +45,18 @@ module Kitchen
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def self.from_image(driver, image)
|
48
|
-
if
|
48
|
+
if /rhel/i.match?(image.name)
|
49
49
|
image.name =~ /\b(\d+(\.\d+)?)/i
|
50
50
|
new(driver, "rhel", (Regexp.last_match || [])[1], image.architecture)
|
51
51
|
end
|
52
52
|
end
|
53
|
+
|
54
|
+
def sort_by_version(images)
|
55
|
+
# First do a normal version sort
|
56
|
+
super(images)
|
57
|
+
# Now sort again, shunning Beta releases.
|
58
|
+
prefer(images) { |image| !image.name.match(/_Beta-/i) }
|
59
|
+
end
|
53
60
|
end
|
54
61
|
end
|
55
62
|
end
|
@@ -70,7 +70,7 @@ module Kitchen
|
|
70
70
|
end
|
71
71
|
|
72
72
|
def self.from_image(driver, image)
|
73
|
-
if
|
73
|
+
if /Windows/i.match?(image.name)
|
74
74
|
# 2008 R2 SP2
|
75
75
|
if image.name =~ /(\b\d+)\W*(r\d+)?/i
|
76
76
|
major, revision = (Regexp.last_match || [])[1], (Regexp.last_match || [])[2]
|
data/lib/kitchen/driver/ec2.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
1
|
#
|
3
2
|
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
4
3
|
#
|
@@ -17,8 +16,8 @@
|
|
17
16
|
# See the License for the specific language governing permissions and
|
18
17
|
# limitations under the License.
|
19
18
|
|
20
|
-
require "benchmark"
|
21
|
-
require "json"
|
19
|
+
require "benchmark" unless defined?(Benchmark)
|
20
|
+
require "json" unless defined?(JSON)
|
22
21
|
require "kitchen"
|
23
22
|
require_relative "ec2_version"
|
24
23
|
require_relative "aws/client"
|
@@ -35,10 +34,10 @@ require_relative "aws/standard_platform/ubuntu"
|
|
35
34
|
require_relative "aws/standard_platform/windows"
|
36
35
|
require "aws-sdk-ec2"
|
37
36
|
require "aws-sdk-core/waiters/errors"
|
38
|
-
require "retryable"
|
39
|
-
require "time"
|
40
|
-
require "etc"
|
41
|
-
require "socket"
|
37
|
+
require "retryable" unless defined?(Retryable)
|
38
|
+
require "time" unless defined?(Time)
|
39
|
+
require "etc" unless defined?(Etc)
|
40
|
+
require "socket" unless defined?(Socket)
|
42
41
|
|
43
42
|
module Kitchen
|
44
43
|
|
@@ -57,7 +56,8 @@ module Kitchen
|
|
57
56
|
default_config :shared_credentials_profile, ENV["AWS_PROFILE"]
|
58
57
|
default_config :availability_zone, nil
|
59
58
|
default_config :instance_type, &:default_instance_type
|
60
|
-
default_config :ebs_optimized,
|
59
|
+
default_config :ebs_optimized, false
|
60
|
+
default_config :delete_on_termination, true
|
61
61
|
default_config :security_group_ids, nil
|
62
62
|
default_config :security_group_filter, nil
|
63
63
|
default_config :security_group_cidr_ip, "0.0.0.0/0"
|
@@ -227,7 +227,7 @@ module Kitchen
|
|
227
227
|
|
228
228
|
if config[:spot_price]
|
229
229
|
# Spot instance when a price is set
|
230
|
-
server = with_request_limit_backoff(state) { submit_spots
|
230
|
+
server = with_request_limit_backoff(state) { submit_spots }
|
231
231
|
else
|
232
232
|
# On-demand instance
|
233
233
|
server = with_request_limit_backoff(state) { submit_server }
|
@@ -238,32 +238,16 @@ module Kitchen
|
|
238
238
|
server.wait_until_exists(before_attempt: logging_proc)
|
239
239
|
end
|
240
240
|
|
241
|
+
state[:server_id] = server.id
|
242
|
+
info("EC2 instance <#{state[:server_id]}> created.")
|
243
|
+
|
241
244
|
# See https://github.com/aws/aws-sdk-ruby/issues/859
|
242
|
-
#
|
243
|
-
# Waiting can also fail, so we have to also retry on that. If it means we re-tag the
|
244
|
-
# instance, so be it.
|
245
|
-
# Tagging an instance is possible before volumes are attached. Tagging the volumes after
|
246
|
-
# instance creation is consistent.
|
245
|
+
# Waiting can fail, so we have to retry on that.
|
247
246
|
Retryable.retryable(
|
248
247
|
tries: 10,
|
249
248
|
sleep: lambda { |n| [2**n, 30].min },
|
250
249
|
on: ::Aws::EC2::Errors::InvalidInstanceIDNotFound
|
251
250
|
) do |r, _|
|
252
|
-
info("Attempting to tag the instance, #{r} retries")
|
253
|
-
tag_server(server)
|
254
|
-
|
255
|
-
# Get information about the AMI (image) used to create the image.
|
256
|
-
image_data = ec2.client.describe_images({ image_ids: [server.image_id] })[0][0]
|
257
|
-
|
258
|
-
state[:server_id] = server.id
|
259
|
-
info("EC2 instance <#{state[:server_id]}> created.")
|
260
|
-
|
261
|
-
# instance-store backed images do not have attached volumes, so only
|
262
|
-
# wait for the volumes to be ready if the instance EBS-backed.
|
263
|
-
if image_data.root_device_type == "ebs"
|
264
|
-
wait_until_volumes_ready(server, state)
|
265
|
-
tag_volumes(server)
|
266
|
-
end
|
267
251
|
wait_until_ready(server, state)
|
268
252
|
end
|
269
253
|
|
@@ -277,7 +261,7 @@ module Kitchen
|
|
277
261
|
|
278
262
|
info("EC2 instance <#{state[:server_id]}> ready (hostname: #{state[:hostname]}).")
|
279
263
|
instance.transport.connection(state).wait_until_ready
|
280
|
-
create_ec2_json(state) if instance.provisioner.name
|
264
|
+
create_ec2_json(state) if /chef/i.match?(instance.provisioner.name)
|
281
265
|
debug("ec2:create '#{state[:hostname]}'")
|
282
266
|
rescue Exception
|
283
267
|
# Clean up any auto-created security groups or keys on the way out.
|
@@ -297,13 +281,6 @@ module Kitchen
|
|
297
281
|
warn("Received #{e}, instance was probably already destroyed. Ignoring")
|
298
282
|
end
|
299
283
|
end
|
300
|
-
if state[:spot_request_id]
|
301
|
-
debug("Deleting spot request <#{state[:server_id]}>")
|
302
|
-
ec2.client.cancel_spot_instance_requests(
|
303
|
-
spot_instance_request_ids: [state[:spot_request_id]]
|
304
|
-
)
|
305
|
-
state.delete(:spot_request_id)
|
306
|
-
end
|
307
284
|
# If we are going to clean up an automatic security group, we need
|
308
285
|
# to wait for the instance to shut down. This slightly breaks the
|
309
286
|
# subsystem encapsulation, sorry not sorry.
|
@@ -342,17 +319,14 @@ module Kitchen
|
|
342
319
|
end
|
343
320
|
|
344
321
|
def default_instance_type
|
345
|
-
@instance_type ||=
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
"t1.micro"
|
354
|
-
end
|
355
|
-
end
|
322
|
+
@instance_type ||= if image && image.virtualization_type == "hvm"
|
323
|
+
info("instance_type not specified. Using free tier t2.micro instance ...")
|
324
|
+
"t2.micro"
|
325
|
+
else
|
326
|
+
info("instance_type not specified. Using free tier t1.micro instance since" \
|
327
|
+
" image is paravirtual (pick an hvm image to use the superior t2.micro!) ...")
|
328
|
+
"t1.micro"
|
329
|
+
end
|
356
330
|
end
|
357
331
|
|
358
332
|
# The actual platform is the platform detected from the image
|
@@ -409,15 +383,14 @@ module Kitchen
|
|
409
383
|
@instance_generator = Aws::InstanceGenerator.new(config, ec2, instance.logger)
|
410
384
|
end
|
411
385
|
|
412
|
-
#
|
386
|
+
# AWS helper for creating the instance
|
413
387
|
def submit_server
|
414
388
|
instance_data = instance_generator.ec2_instance_data
|
415
389
|
debug("Creating EC2 instance in region #{config[:region]} with properties:")
|
416
390
|
instance_data.each do |key, value|
|
417
391
|
debug("- #{key} = #{value.inspect}")
|
418
392
|
end
|
419
|
-
|
420
|
-
instance_data[:max_count] = 1
|
393
|
+
|
421
394
|
ec2.create_instance(instance_data)
|
422
395
|
end
|
423
396
|
|
@@ -445,10 +418,34 @@ module Kitchen
|
|
445
418
|
configs
|
446
419
|
end
|
447
420
|
|
448
|
-
def submit_spots
|
421
|
+
def submit_spots
|
449
422
|
configs = [config]
|
450
423
|
expanded = []
|
451
|
-
keys = %i{instance_type
|
424
|
+
keys = %i{instance_type}
|
425
|
+
|
426
|
+
unless config[:subnet_filter]
|
427
|
+
# => Use explicitly specified subnets
|
428
|
+
keys << :subnet_id
|
429
|
+
else
|
430
|
+
# => Enable cascading through matching subnets
|
431
|
+
client = ::Aws::EC2::Client.new(region: config[:region])
|
432
|
+
subnets = client.describe_subnets(
|
433
|
+
filters: [
|
434
|
+
{
|
435
|
+
name: "tag:#{config[:subnet_filter][:tag]}",
|
436
|
+
values: [config[:subnet_filter][:value]],
|
437
|
+
},
|
438
|
+
]
|
439
|
+
).subnets
|
440
|
+
raise "A subnet matching '#{config[:subnet_filter][:tag]}:#{config[:subnet_filter][:value]}' does not exist!" unless subnets.any?
|
441
|
+
|
442
|
+
configs = subnets.map do |subnet|
|
443
|
+
new_config = config.clone
|
444
|
+
new_config[:subnet_id] = subnet.subnet_id
|
445
|
+
new_config[:subnet_filter] = nil
|
446
|
+
new_config
|
447
|
+
end
|
448
|
+
end
|
452
449
|
|
453
450
|
keys.each do |key|
|
454
451
|
configs.each do |conf|
|
@@ -460,96 +457,55 @@ module Kitchen
|
|
460
457
|
|
461
458
|
errs = []
|
462
459
|
configs.each do |conf|
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
errs.append(e)
|
468
|
-
end
|
460
|
+
@config = conf
|
461
|
+
return submit_spot
|
462
|
+
rescue => e
|
463
|
+
errs.append(e)
|
469
464
|
end
|
470
465
|
raise ["Could not create a spot instance:", errs].flatten.join("\n")
|
471
466
|
end
|
472
467
|
|
473
|
-
def submit_spot
|
468
|
+
def submit_spot
|
474
469
|
debug("Creating EC2 Spot Instance..")
|
470
|
+
instance_data = instance_generator.ec2_instance_data
|
475
471
|
|
476
|
-
spot_request_id = create_spot_request
|
477
|
-
# deleting the instance cancels the request, but deleting the request
|
478
|
-
# does not affect the instance
|
479
|
-
state[:spot_request_id] = spot_request_id
|
480
|
-
ec2.client.wait_until(
|
481
|
-
:spot_instance_request_fulfilled,
|
482
|
-
spot_instance_request_ids: [spot_request_id]
|
483
|
-
) do |w|
|
484
|
-
w.max_attempts = config[:spot_wait] / config[:retryable_sleep]
|
485
|
-
w.delay = config[:retryable_sleep]
|
486
|
-
w.before_attempt do |attempts|
|
487
|
-
c = attempts * config[:retryable_sleep]
|
488
|
-
t = config[:spot_wait]
|
489
|
-
info "Waited #{c}/#{t}s for spot request <#{spot_request_id}> to become fulfilled."
|
490
|
-
end
|
491
|
-
end
|
492
|
-
ec2.get_instance_from_spot_request(spot_request_id)
|
493
|
-
end
|
494
|
-
|
495
|
-
def create_spot_request
|
496
|
-
request_duration = config[:spot_wait]
|
497
472
|
config_spot_price = config[:spot_price].to_s
|
498
473
|
if %w{ondemand on-demand}.include?(config_spot_price)
|
499
474
|
spot_price = ""
|
500
475
|
else
|
501
476
|
spot_price = config_spot_price
|
502
477
|
end
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
478
|
+
spot_options = {
|
479
|
+
# Must use one-time in order to use instance_interruption_behavior=terminate
|
480
|
+
# spot_instance_type: "one-time", # default
|
481
|
+
# Must use instance_interruption_behavior=terminate in order to use block_duration_minutes
|
482
|
+
# instance_interruption_behavior: "terminate", # default
|
507
483
|
}
|
508
484
|
if config[:block_duration_minutes]
|
509
|
-
|
485
|
+
spot_options[:block_duration_minutes] = config[:block_duration_minutes]
|
510
486
|
end
|
511
|
-
|
512
|
-
|
513
|
-
response[:spot_instance_requests][0][:spot_instance_request_id]
|
514
|
-
end
|
515
|
-
|
516
|
-
def tag_server(server)
|
517
|
-
if config[:tags] && !config[:tags].empty?
|
518
|
-
tags = config[:tags].map do |k, v|
|
519
|
-
# we convert the value to a string because
|
520
|
-
# nils should be passed as an empty String
|
521
|
-
# and Integers need to be represented as Strings
|
522
|
-
{ key: k.to_s, value: v.to_s }
|
523
|
-
end
|
524
|
-
server.create_tags(tags: tags)
|
487
|
+
unless spot_price == "" # i.e. on-demand
|
488
|
+
spot_options[:max_price] = spot_price
|
525
489
|
end
|
526
|
-
end
|
527
490
|
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
end
|
533
|
-
server.volumes.each do |volume|
|
534
|
-
volume.create_tags(tags: tags)
|
535
|
-
end
|
536
|
-
end
|
537
|
-
end
|
491
|
+
instance_data[:instance_market_options] = {
|
492
|
+
market_type: "spot",
|
493
|
+
spot_options: spot_options,
|
494
|
+
}
|
538
495
|
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
(described_volume_count > 0) && (described_volume_count == ready_volume_count)
|
496
|
+
# The preferred way to create a spot instance is via request_spot_instances()
|
497
|
+
# However, it does not allow for tagging to occur at creation time.
|
498
|
+
# create_instances() allows creation of tagged spot instances, but does
|
499
|
+
# not retry if the price could not be satisfied immediately.
|
500
|
+
Retryable.retryable(
|
501
|
+
tries: config[:spot_wait] / config[:retryable_sleep],
|
502
|
+
sleep: lambda { |_n| config[:retryable_sleep] },
|
503
|
+
on: ::Aws::EC2::Errors::SpotMaxPriceTooLow
|
504
|
+
) do |retries|
|
505
|
+
c = retries * config[:retryable_sleep]
|
506
|
+
t = config[:spot_wait]
|
507
|
+
info "Waited #{c}/#{t}s for spot request to become fulfilled."
|
508
|
+
ec2.create_instance(instance_data)
|
553
509
|
end
|
554
510
|
end
|
555
511
|
|
@@ -825,7 +781,9 @@ module Kitchen
|
|
825
781
|
ip_protocol: "tcp",
|
826
782
|
from_port: port,
|
827
783
|
to_port: port,
|
828
|
-
ip_ranges:
|
784
|
+
ip_ranges: Array(config[:security_group_cidr_ip]).map do |cidr_ip|
|
785
|
+
{ cidr_ip: cidr_ip }
|
786
|
+
end,
|
829
787
|
}
|
830
788
|
end
|
831
789
|
)
|
@@ -1,4 +1,3 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
1
|
#
|
3
2
|
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
4
3
|
#
|
@@ -22,6 +21,6 @@ module Kitchen
|
|
22
21
|
module Driver
|
23
22
|
|
24
23
|
# Version string for EC2 Test Kitchen driver
|
25
|
-
EC2_VERSION = "3.
|
24
|
+
EC2_VERSION = "3.9.0".freeze
|
26
25
|
end
|
27
26
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kitchen-ec2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fletcher Nichol
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-04-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: test-kitchen
|
@@ -30,34 +30,6 @@ dependencies:
|
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '3'
|
33
|
-
- !ruby/object:Gem::Dependency
|
34
|
-
name: excon
|
35
|
-
requirement: !ruby/object:Gem::Requirement
|
36
|
-
requirements:
|
37
|
-
- - ">="
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
version: '0'
|
40
|
-
type: :runtime
|
41
|
-
prerelease: false
|
42
|
-
version_requirements: !ruby/object:Gem::Requirement
|
43
|
-
requirements:
|
44
|
-
- - ">="
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
version: '0'
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: multi_json
|
49
|
-
requirement: !ruby/object:Gem::Requirement
|
50
|
-
requirements:
|
51
|
-
- - ">="
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '0'
|
54
|
-
type: :runtime
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
requirements:
|
58
|
-
- - ">="
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
version: '0'
|
61
33
|
- !ruby/object:Gem::Dependency
|
62
34
|
name: aws-sdk-ec2
|
63
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -92,104 +64,6 @@ dependencies:
|
|
92
64
|
- - "<"
|
93
65
|
- !ruby/object:Gem::Version
|
94
66
|
version: '4.0'
|
95
|
-
- !ruby/object:Gem::Dependency
|
96
|
-
name: rspec
|
97
|
-
requirement: !ruby/object:Gem::Requirement
|
98
|
-
requirements:
|
99
|
-
- - "~>"
|
100
|
-
- !ruby/object:Gem::Version
|
101
|
-
version: '3.2'
|
102
|
-
type: :development
|
103
|
-
prerelease: false
|
104
|
-
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
requirements:
|
106
|
-
- - "~>"
|
107
|
-
- !ruby/object:Gem::Version
|
108
|
-
version: '3.2'
|
109
|
-
- !ruby/object:Gem::Dependency
|
110
|
-
name: countloc
|
111
|
-
requirement: !ruby/object:Gem::Requirement
|
112
|
-
requirements:
|
113
|
-
- - "~>"
|
114
|
-
- !ruby/object:Gem::Version
|
115
|
-
version: '0.4'
|
116
|
-
type: :development
|
117
|
-
prerelease: false
|
118
|
-
version_requirements: !ruby/object:Gem::Requirement
|
119
|
-
requirements:
|
120
|
-
- - "~>"
|
121
|
-
- !ruby/object:Gem::Version
|
122
|
-
version: '0.4'
|
123
|
-
- !ruby/object:Gem::Dependency
|
124
|
-
name: maruku
|
125
|
-
requirement: !ruby/object:Gem::Requirement
|
126
|
-
requirements:
|
127
|
-
- - "~>"
|
128
|
-
- !ruby/object:Gem::Version
|
129
|
-
version: '0.6'
|
130
|
-
type: :development
|
131
|
-
prerelease: false
|
132
|
-
version_requirements: !ruby/object:Gem::Requirement
|
133
|
-
requirements:
|
134
|
-
- - "~>"
|
135
|
-
- !ruby/object:Gem::Version
|
136
|
-
version: '0.6'
|
137
|
-
- !ruby/object:Gem::Dependency
|
138
|
-
name: simplecov
|
139
|
-
requirement: !ruby/object:Gem::Requirement
|
140
|
-
requirements:
|
141
|
-
- - "~>"
|
142
|
-
- !ruby/object:Gem::Version
|
143
|
-
version: '0.7'
|
144
|
-
type: :development
|
145
|
-
prerelease: false
|
146
|
-
version_requirements: !ruby/object:Gem::Requirement
|
147
|
-
requirements:
|
148
|
-
- - "~>"
|
149
|
-
- !ruby/object:Gem::Version
|
150
|
-
version: '0.7'
|
151
|
-
- !ruby/object:Gem::Dependency
|
152
|
-
name: yard
|
153
|
-
requirement: !ruby/object:Gem::Requirement
|
154
|
-
requirements:
|
155
|
-
- - ">="
|
156
|
-
- !ruby/object:Gem::Version
|
157
|
-
version: 0.9.11
|
158
|
-
type: :development
|
159
|
-
prerelease: false
|
160
|
-
version_requirements: !ruby/object:Gem::Requirement
|
161
|
-
requirements:
|
162
|
-
- - ">="
|
163
|
-
- !ruby/object:Gem::Version
|
164
|
-
version: 0.9.11
|
165
|
-
- !ruby/object:Gem::Dependency
|
166
|
-
name: chefstyle
|
167
|
-
requirement: !ruby/object:Gem::Requirement
|
168
|
-
requirements:
|
169
|
-
- - '='
|
170
|
-
- !ruby/object:Gem::Version
|
171
|
-
version: 1.0.5
|
172
|
-
type: :development
|
173
|
-
prerelease: false
|
174
|
-
version_requirements: !ruby/object:Gem::Requirement
|
175
|
-
requirements:
|
176
|
-
- - '='
|
177
|
-
- !ruby/object:Gem::Version
|
178
|
-
version: 1.0.5
|
179
|
-
- !ruby/object:Gem::Dependency
|
180
|
-
name: climate_control
|
181
|
-
requirement: !ruby/object:Gem::Requirement
|
182
|
-
requirements:
|
183
|
-
- - ">="
|
184
|
-
- !ruby/object:Gem::Version
|
185
|
-
version: '0'
|
186
|
-
type: :development
|
187
|
-
prerelease: false
|
188
|
-
version_requirements: !ruby/object:Gem::Requirement
|
189
|
-
requirements:
|
190
|
-
- - ">="
|
191
|
-
- !ruby/object:Gem::Version
|
192
|
-
version: '0'
|
193
67
|
description: A Test Kitchen Driver for Amazon EC2
|
194
68
|
email:
|
195
69
|
- fnichol@nichol.ca
|
@@ -216,7 +90,7 @@ homepage: https://github.com/test-kitchen/kitchen-ec2
|
|
216
90
|
licenses:
|
217
91
|
- Apache-2.0
|
218
92
|
metadata: {}
|
219
|
-
post_install_message:
|
93
|
+
post_install_message:
|
220
94
|
rdoc_options: []
|
221
95
|
require_paths:
|
222
96
|
- lib
|
@@ -224,15 +98,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
224
98
|
requirements:
|
225
99
|
- - ">="
|
226
100
|
- !ruby/object:Gem::Version
|
227
|
-
version: '2.
|
101
|
+
version: '2.5'
|
228
102
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
229
103
|
requirements:
|
230
104
|
- - ">="
|
231
105
|
- !ruby/object:Gem::Version
|
232
106
|
version: '0'
|
233
107
|
requirements: []
|
234
|
-
rubygems_version: 3.
|
235
|
-
signing_key:
|
108
|
+
rubygems_version: 3.2.15
|
109
|
+
signing_key:
|
236
110
|
specification_version: 4
|
237
111
|
summary: A Test Kitchen Driver for Amazon EC2
|
238
112
|
test_files: []
|