kitchen-ec2 3.2.0 → 3.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 828a479cf1ebe8de5423fad1926bc74f1cb66ddc1a1b4f853977424e65dd4709
4
- data.tar.gz: 67851982c4d376be9ca701040e38d8e7b5cb308a7cf52cd0056da8f898558dcd
3
+ metadata.gz: 0d6429e51c08d43c0e1084b9acc55b76feacae05bbe42b7cf3a1e35e0de70f87
4
+ data.tar.gz: 9f2a0adbe2866ad6a267ab8adc14d24a890b22b71b0abe272808a2a52def3933
5
5
  SHA512:
6
- metadata.gz: 1165fa8225401552970c19983091d8cb38f234a08f9f84a68ebb45cdf05b5670271e92b780b9e8fa0fdecc1c18083e3702f3ddace3561a76628226d09f67ce26
7
- data.tar.gz: abe70ab29dacefda005ec11ffa0710841532e7f8407c203daf6bd782acb1c1da59d95c1c188bfca81cc20bd010d2ce7df5c6e78371eff0960f46dcbf3c885245
6
+ metadata.gz: aa308480b37d109ec173851aefe0098523d2a59c06481e88004bf76ccb8d87dfbd865300d2383157af13b38af47588ec2d1adf0541734f7279669a8dbcb0b673
7
+ data.tar.gz: 48f6f1a3dc22caf5d04079ef1579c19850e7e72558708e633537adb752969c3aac1b79702804864fac3fad9140e8d9053347c3ecde47e578e0545366d0b0b619
@@ -49,14 +49,24 @@ module Kitchen
49
49
  ::Aws.config.update(retry_limit: retry_limit) unless retry_limit.nil?
50
50
  end
51
51
 
52
+ # create a new AWS EC2 instance
53
+ # @param options [Hash] has of instance options
54
+ # @see https://docs.aws.amazon.com/sdkforruby/api/Aws/EC2/Resource.html#create_instances-instance_method
55
+ # @return [Aws::EC2::Instance]
52
56
  def create_instance(options)
53
57
  resource.create_instances(options).first
54
58
  end
55
59
 
60
+ # get an instance object given an id
61
+ # @param id [String] aws instance id
62
+ # @return [Aws::EC2::Instance]
56
63
  def get_instance(id)
57
64
  resource.instance(id)
58
65
  end
59
66
 
67
+ # get an instance object given a spot request ID
68
+ # @param request_id [String] aws spot instance id
69
+ # @return [Aws::EC2::Instance]
60
70
  def get_instance_from_spot_request(request_id)
61
71
  resource.instances(
62
72
  filters: [{
@@ -39,29 +39,34 @@ module Kitchen
39
39
  @logger = logger
40
40
  end
41
41
 
42
- # Transform the provided config into the hash to send to AWS. Some fields
42
+ # Transform the provided kitchen config into the hash we'll use to create the aws instance
43
43
  # can be passed in null, others need to be ommitted if they are null
44
+ # Some fields can be passed in null, others need to be ommitted if they are null
45
+ # @return [Hash]
44
46
  def ec2_instance_data # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
45
47
  # Support for looking up security group id and subnet id using tags.
46
-
48
+ vpc_id = nil
49
+ client = ::Aws::EC2::Client.new(region: config[:region])
47
50
  if config[:subnet_id].nil? && config[:subnet_filter]
48
- config[:subnet_id] = ::Aws::EC2::Client
49
- .new(region: config[:region]).describe_subnets(
50
- filters: [
51
- {
52
- name: "tag:#{config[:subnet_filter][:tag]}",
53
- values: [config[:subnet_filter][:value]],
54
- },
55
- ]
56
- )[0][0].subnet_id
57
-
58
- if config[:subnet_id].nil?
59
- raise "The subnet tagged '#{config[:subnet_filter][:tag]}\
60
- #{config[:subnet_filter][:value]}' does not exist!"
61
- end
51
+ subnets = client.describe_subnets(
52
+ filters: [
53
+ {
54
+ name: "tag:#{config[:subnet_filter][:tag]}",
55
+ values: [config[:subnet_filter][:value]],
56
+ },
57
+ ]
58
+ ).subnets
59
+ raise "The subnet tagged '#{config[:subnet_filter][:tag]}:#{config[:subnet_filter][:value]}' does not exist!" unless subnets.any?
60
+
61
+ # => Select the least-populated subnet if we have multiple matches
62
+ subnet = subnets.sort_by { |s| s[:available_ip_address_count] }.last
63
+ vpc_id = subnet.vpc_id
64
+ config[:subnet_id] = subnet.subnet_id
62
65
  end
63
66
 
64
67
  if config[:security_group_ids].nil? && config[:security_group_filter]
68
+ # => Grab the VPC in the case a Subnet ID rather than Filter was set
69
+ vpc_id ||= client.describe_subnets(subnet_ids: [config[:subnet_id]]).subnets[0].vpc_id
65
70
  security_groups = []
66
71
  filters = [config[:security_group_filter]].flatten
67
72
  filters.each do |sg_filter|
@@ -72,6 +77,10 @@ module Kitchen
72
77
  name: "group-name",
73
78
  values: [sg_filter[:name]],
74
79
  },
80
+ {
81
+ name: "vpc-id",
82
+ values: [vpc_id],
83
+ },
75
84
  ]
76
85
  end
77
86
 
@@ -81,13 +90,17 @@ module Kitchen
81
90
  name: "tag:#{sg_filter[:tag]}",
82
91
  values: [sg_filter[:value]],
83
92
  },
93
+ {
94
+ name: "vpc-id",
95
+ values: [vpc_id],
96
+ },
84
97
  ]
85
98
  end
86
99
 
87
- security_group = ::Aws::EC2::Client.new(region: config[:region]).describe_security_groups(r)[0][0]
100
+ security_group = client.describe_security_groups(r).security_groups
88
101
 
89
- if security_group
90
- security_groups.push(security_group.group_id)
102
+ if security_group.any?
103
+ security_group.each { |sg| security_groups.push(sg.group_id) }
91
104
  else
92
105
  raise "A Security Group matching the following filter could not be found:\n#{sg_filter}"
93
106
  end
@@ -102,8 +115,22 @@ module Kitchen
102
115
  key_name: config[:aws_ssh_key_id],
103
116
  subnet_id: config[:subnet_id],
104
117
  private_ip_address: config[:private_ip_address],
118
+ min_count: 1,
119
+ max_count: 1,
105
120
  }
106
121
 
122
+ if config[:tags] && !config[:tags].empty?
123
+ tags = config[:tags].map do |k, v|
124
+ # we convert the value to a string because
125
+ # nils should be passed as an empty String
126
+ # and Integers need to be represented as Strings
127
+ { key: k, value: v.to_s }
128
+ end
129
+ instance_tag_spec = { resource_type: "instance", tags: tags }
130
+ volume_tag_spec = { resource_type: "volume", tags: tags }
131
+ i[:tag_specifications] = [instance_tag_spec, volume_tag_spec]
132
+ end
133
+
107
134
  availability_zone = config[:availability_zone]
108
135
  if availability_zone
109
136
  if availability_zone =~ /^[a-z]$/i
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "kitchen/driver/aws/standard_platform"
16
+ require_relative "../standard_platform"
17
17
 
18
18
  module Kitchen
19
19
  module Driver
@@ -23,6 +23,8 @@ module Kitchen
23
23
  class Amazon < StandardPlatform
24
24
  StandardPlatform.platforms["amazon"] = self
25
25
 
26
+ # default username for this platform's ami
27
+ # @return [String]
26
28
  def username
27
29
  "ec2-user"
28
30
  end
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "kitchen/driver/aws/standard_platform"
16
+ require_relative "../standard_platform"
17
17
 
18
18
  module Kitchen
19
19
  module Driver
@@ -23,6 +23,8 @@ module Kitchen
23
23
  class Amazon2 < StandardPlatform
24
24
  StandardPlatform.platforms["amazon2"] = self
25
25
 
26
+ # default username for this platform's ami
27
+ # @return [String]
26
28
  def username
27
29
  "ec2-user"
28
30
  end
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "kitchen/driver/aws/standard_platform"
16
+ require_relative "../standard_platform"
17
17
 
18
18
  module Kitchen
19
19
  module Driver
@@ -23,6 +23,8 @@ module Kitchen
23
23
  class Centos < StandardPlatform
24
24
  StandardPlatform.platforms["centos"] = self
25
25
 
26
+ # default username for this platform's ami
27
+ # @return [String]
26
28
  def username
27
29
  # Centos 6.x images use root as the username (but the "centos 6"
28
30
  # updateable image uses "centos")
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "kitchen/driver/aws/standard_platform"
16
+ require_relative "../standard_platform"
17
17
 
18
18
  module Kitchen
19
19
  module Driver
@@ -26,14 +26,17 @@ module Kitchen
26
26
  # 10/11 are listed last since we default to the first item in the hash
27
27
  # and 10/11 are not released yet. When they're released move them up
28
28
  DEBIAN_CODENAMES = {
29
+ 10 => "buster",
29
30
  9 => "stretch",
30
31
  8 => "jessie",
31
32
  7 => "wheezy",
32
33
  6 => "squeeze",
33
34
  11 => "bullseye",
34
- 10 => "buster",
35
+ 12 => "bookworm",
35
36
  }.freeze
36
37
 
38
+ # default username for this platform's ami
39
+ # @return [String]
37
40
  def username
38
41
  "admin"
39
42
  end
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "kitchen/driver/aws/standard_platform"
16
+ require_relative "../standard_platform"
17
17
 
18
18
  module Kitchen
19
19
  module Driver
@@ -23,6 +23,8 @@ module Kitchen
23
23
  class Fedora < StandardPlatform
24
24
  StandardPlatform.platforms["fedora"] = self
25
25
 
26
+ # default username for this platform's ami
27
+ # @return [String]
26
28
  def username
27
29
  "fedora"
28
30
  end
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "kitchen/driver/aws/standard_platform"
16
+ require_relative "../standard_platform"
17
17
 
18
18
  module Kitchen
19
19
  module Driver
@@ -23,6 +23,8 @@ module Kitchen
23
23
  class Freebsd < StandardPlatform
24
24
  StandardPlatform.platforms["freebsd"] = self
25
25
 
26
+ # default username for this platform's ami
27
+ # @return [String]
26
28
  def username
27
29
  "ec2-user"
28
30
  end
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "kitchen/driver/aws/standard_platform"
16
+ require_relative "../standard_platform"
17
17
 
18
18
  module Kitchen
19
19
  module Driver
@@ -29,6 +29,8 @@ module Kitchen
29
29
  super(driver, "rhel", version, architecture)
30
30
  end
31
31
 
32
+ # default username for this platform's ami
33
+ # @return [String]
32
34
  def username
33
35
  (version && version.to_f < 6.4) ? "root" : "ec2-user"
34
36
  end
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "kitchen/driver/aws/standard_platform"
16
+ require_relative "../standard_platform"
17
17
 
18
18
  module Kitchen
19
19
  module Driver
@@ -23,6 +23,8 @@ module Kitchen
23
23
  class Ubuntu < StandardPlatform
24
24
  StandardPlatform.platforms["ubuntu"] = self
25
25
 
26
+ # default username for this platform's ami
27
+ # @return [String]
26
28
  def username
27
29
  "ubuntu"
28
30
  end
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- require "kitchen/driver/aws/standard_platform"
16
+ require_relative "../standard_platform"
17
17
 
18
18
  module Kitchen
19
19
  module Driver
@@ -23,6 +23,8 @@ module Kitchen
23
23
  class Windows < StandardPlatform
24
24
  StandardPlatform.platforms["windows"] = self
25
25
 
26
+ # default username for this platform's ami
27
+ # @return [String]
26
28
  def username
27
29
  "administrator"
28
30
  end
@@ -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(state) }
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
- # Tagging can fail with a NotFound error even though we waited until the server exists
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 =~ /chef/
264
+ create_ec2_json(state) if instance.provisioner.name =~ /chef/i
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.
@@ -291,14 +275,11 @@ module Kitchen
291
275
  server = ec2.get_instance(state[:server_id])
292
276
  unless server.nil?
293
277
  instance.transport.connection(state).close
294
- server.terminate
295
- end
296
- if state[:spot_request_id]
297
- debug("Deleting spot request <#{state[:server_id]}>")
298
- ec2.client.cancel_spot_instance_requests(
299
- spot_instance_request_ids: [state[:spot_request_id]]
300
- )
301
- state.delete(:spot_request_id)
278
+ begin
279
+ server.terminate
280
+ rescue ::Aws::EC2::Errors::InvalidInstanceIDNotFound => e
281
+ warn("Received #{e}, instance was probably already destroyed. Ignoring")
282
+ end
302
283
  end
303
284
  # If we are going to clean up an automatic security group, we need
304
285
  # to wait for the instance to shut down. This slightly breaks the
@@ -405,15 +386,14 @@ module Kitchen
405
386
  @instance_generator = Aws::InstanceGenerator.new(config, ec2, instance.logger)
406
387
  end
407
388
 
408
- # Fog AWS helper for creating the instance
389
+ # AWS helper for creating the instance
409
390
  def submit_server
410
391
  instance_data = instance_generator.ec2_instance_data
411
392
  debug("Creating EC2 instance in region #{config[:region]} with properties:")
412
393
  instance_data.each do |key, value|
413
394
  debug("- #{key} = #{value.inspect}")
414
395
  end
415
- instance_data[:min_count] = 1
416
- instance_data[:max_count] = 1
396
+
417
397
  ec2.create_instance(instance_data)
418
398
  end
419
399
 
@@ -441,7 +421,7 @@ module Kitchen
441
421
  configs
442
422
  end
443
423
 
444
- def submit_spots(state)
424
+ def submit_spots
445
425
  configs = [config]
446
426
  expanded = []
447
427
  keys = %i{instance_type subnet_id}
@@ -454,40 +434,22 @@ module Kitchen
454
434
  expanded = []
455
435
  end
456
436
 
437
+ errs = []
457
438
  configs.each do |conf|
458
439
  begin
459
440
  @config = conf
460
- return submit_spot(state)
461
- rescue
441
+ return submit_spot
442
+ rescue => e
443
+ errs.append(e)
462
444
  end
463
445
  end
464
-
465
- raise "Could not create a spot"
446
+ raise ["Could not create a spot instance:", errs].flatten.join("\n")
466
447
  end
467
448
 
468
- def submit_spot(state)
449
+ def submit_spot
469
450
  debug("Creating EC2 Spot Instance..")
451
+ instance_data = instance_generator.ec2_instance_data
470
452
 
471
- spot_request_id = create_spot_request
472
- # deleting the instance cancels the request, but deleting the request
473
- # does not affect the instance
474
- state[:spot_request_id] = spot_request_id
475
- ec2.client.wait_until(
476
- :spot_instance_request_fulfilled,
477
- spot_instance_request_ids: [spot_request_id]
478
- ) do |w|
479
- w.max_attempts = config[:spot_wait] / config[:retryable_sleep]
480
- w.delay = config[:retryable_sleep]
481
- w.before_attempt do |attempts|
482
- c = attempts * config[:retryable_sleep]
483
- t = config[:spot_wait]
484
- info "Waited #{c}/#{t}s for spot request <#{spot_request_id}> to become fulfilled."
485
- end
486
- end
487
- ec2.get_instance_from_spot_request(spot_request_id)
488
- end
489
-
490
- def create_spot_request
491
453
  request_duration = config[:spot_wait]
492
454
  config_spot_price = config[:spot_price].to_s
493
455
  if %w{ondemand on-demand}.include?(config_spot_price)
@@ -495,56 +457,36 @@ module Kitchen
495
457
  else
496
458
  spot_price = config_spot_price
497
459
  end
498
- request_data = {
499
- spot_price: spot_price,
500
- launch_specification: instance_generator.ec2_instance_data,
460
+ spot_options = {
461
+ spot_instance_type: "persistent", # Cannot use one-time with valid_until
501
462
  valid_until: Time.now + request_duration,
463
+ instance_interruption_behavior: "stop",
502
464
  }
503
465
  if config[:block_duration_minutes]
504
- request_data[:block_duration_minutes] = config[:block_duration_minutes]
466
+ spot_options[:block_duration_minutes] = config[:block_duration_minutes]
505
467
  end
506
-
507
- response = ec2.client.request_spot_instances(request_data)
508
- response[:spot_instance_requests][0][:spot_instance_request_id]
509
- end
510
-
511
- def tag_server(server)
512
- if config[:tags] && !config[:tags].empty?
513
- tags = config[:tags].map do |k, v|
514
- # we convert the value to a string because
515
- # nils should be passed as an empty String
516
- # and Integers need to be represented as Strings
517
- { key: k.to_s, value: v.to_s }
518
- end
519
- server.create_tags(tags: tags)
468
+ unless spot_price == "" # i.e. on-demand
469
+ spot_options[:max_price] = spot_price
520
470
  end
521
- end
522
471
 
523
- def tag_volumes(server)
524
- if config[:tags] && !config[:tags].empty?
525
- tags = config[:tags].map do |k, v|
526
- { key: k.to_s, value: v.to_s }
527
- end
528
- server.volumes.each do |volume|
529
- volume.create_tags(tags: tags)
530
- end
531
- end
532
- end
472
+ instance_data[:instance_market_options] = {
473
+ market_type: "spot",
474
+ spot_options: spot_options,
475
+ }
533
476
 
534
- # Compares the requested volume count vs what has actually been set to be
535
- # attached to the instance. The information requested through
536
- # ec2.client.described_volumes is updated before the instance volume
537
- # information.
538
- def wait_until_volumes_ready(server, state)
539
- wait_with_destroy(server, state, "volumes to be ready") do |aws_instance|
540
- described_volume_count = 0
541
- ready_volume_count = 0
542
- if aws_instance.exists?
543
- described_volume_count = ec2.client.describe_volumes(filters: [
544
- { name: "attachment.instance-id", values: ["#{state[:server_id]}"] }]).volumes.length
545
- aws_instance.volumes.each { ready_volume_count += 1 }
546
- end
547
- (described_volume_count > 0) && (described_volume_count == ready_volume_count)
477
+ # The preferred way to create a spot instance is via request_spot_instances()
478
+ # However, it does not allow for tagging to occur at creation time.
479
+ # create_instances() allows creation of tagged spot instances, but does
480
+ # not retry if the price could not be satisfied immediately.
481
+ Retryable.retryable(
482
+ tries: config[:spot_wait] / config[:retryable_sleep],
483
+ sleep: lambda { |_n| config[:retryable_sleep] },
484
+ on: ::Aws::EC2::Errors::SpotMaxPriceTooLow
485
+ ) do |retries|
486
+ c = retries * config[:retryable_sleep]
487
+ t = config[:spot_wait]
488
+ info "Waited #{c}/#{t}s for spot request to become fulfilled."
489
+ ec2.create_instance(instance_data)
548
490
  end
549
491
  end
550
492
 
@@ -788,6 +730,7 @@ module Kitchen
788
730
  elsif config[:subnet_filter]
789
731
  subnets = ec2.client.describe_subnets(filters: [{ name: "tag:#{config[:subnet_filter][:tag]}", values: [config[:subnet_filter][:value]] }]).subnets
790
732
  raise "Subnets with tag '#{config[:subnet_filter][:tag]}=#{config[:subnet_filter][:value]}' not found during security group creation" if subnets.empty?
733
+
791
734
  subnets.first.vpc_id
792
735
  else
793
736
  # Try to check for a default VPC.
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
4
  #
5
- # Copyright:: 2016-2018, Chef Software, Inc.
5
+ # Copyright:: Chef Software, Inc.
6
6
  # Copyright:: 2012-2018, Fletcher Nichol
7
7
  #
8
8
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,6 +22,6 @@ module Kitchen
22
22
  module Driver
23
23
 
24
24
  # Version string for EC2 Test Kitchen driver
25
- EC2_VERSION = "3.2.0".freeze
25
+ EC2_VERSION = "3.7.0".freeze
26
26
  end
27
27
  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.2.0
4
+ version: 3.7.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: 2019-09-17 00:00:00.000000000 Z
11
+ date: 2020-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: test-kitchen
@@ -168,14 +168,14 @@ dependencies:
168
168
  requirements:
169
169
  - - '='
170
170
  - !ruby/object:Gem::Version
171
- version: 0.13.3
171
+ version: 1.1.2
172
172
  type: :development
173
173
  prerelease: false
174
174
  version_requirements: !ruby/object:Gem::Requirement
175
175
  requirements:
176
176
  - - '='
177
177
  - !ruby/object:Gem::Version
178
- version: 0.13.3
178
+ version: 1.1.2
179
179
  - !ruby/object:Gem::Dependency
180
180
  name: climate_control
181
181
  requirement: !ruby/object:Gem::Requirement
@@ -216,7 +216,7 @@ homepage: https://github.com/test-kitchen/kitchen-ec2
216
216
  licenses:
217
217
  - Apache-2.0
218
218
  metadata: {}
219
- post_install_message:
219
+ post_install_message:
220
220
  rdoc_options: []
221
221
  require_paths:
222
222
  - lib
@@ -224,15 +224,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
224
224
  requirements:
225
225
  - - ">="
226
226
  - !ruby/object:Gem::Version
227
- version: '2.3'
227
+ version: '2.4'
228
228
  required_rubygems_version: !ruby/object:Gem::Requirement
229
229
  requirements:
230
230
  - - ">="
231
231
  - !ruby/object:Gem::Version
232
232
  version: '0'
233
233
  requirements: []
234
- rubygems_version: 3.0.3
235
- signing_key:
234
+ rubygems_version: 3.1.2
235
+ signing_key:
236
236
  specification_version: 4
237
237
  summary: A Test Kitchen Driver for Amazon EC2
238
238
  test_files: []