kitchen-ec2 3.13.0 → 3.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c5ed0f1bbc994d156a6374c98a1c48f00d2f789f8540b0cb33ae0755996ffca5
4
- data.tar.gz: 0f5f90acb192d7a649ebd9d7861ed2bfbec2ae1665d32c5e66d75685518b1eff
3
+ metadata.gz: 0ab954ba95ae18b5a8af7013f2c2a62ac9437375ea4c4d9fa82c09448335b6ee
4
+ data.tar.gz: d721117b22321834df518eb5c0a8c14495141148546b48717a337f8953457c20
5
5
  SHA512:
6
- metadata.gz: 890a0a34755ab636605a8fcfbc45ce8c0f055adb0fa5404c48d516060da3089628091d37bbc9ad555601d742f40647183f2b34988dc703ca03477722b3dfb1bf
7
- data.tar.gz: 617aaee4fdd8b335e17731621abb9ae140b73286e4da2e77adbb46cdc560789f02eeb85f208217e3ffbd03746c52a46f4ae051d93ab1436fb2fb8f3f2b267351
6
+ metadata.gz: 19cff1d09410833ec15c2407d0e14a454c681f5d3044f50e6bb8713050e3ec7524c56b94d9232b8c09f7e25fe9f05fd7b28bff00bda60ba13de9ac1723520da2
7
+ data.tar.gz: ece685664f0dfb5e7aacb7af3e97d565f005f653a9be2f9ee7c6fbd7566f57a831aba2e3fc3c38a3b098159f3130a95f821c9021400d14f1d471b16fac7113d4
@@ -0,0 +1,135 @@
1
+ module Kitchen
2
+ module Driver
3
+ module Mixins
4
+ module DedicatedHosts
5
+ # check if a suitable dedicated host is available
6
+ # @return Boolean
7
+ def host_available?
8
+ !hosts_with_capacity.empty?
9
+ end
10
+
11
+ # get dedicated host with capacity for instance type
12
+ # @return Aws::EC2::Types::Host
13
+ def hosts_with_capacity
14
+ hosts_managed.select do |host|
15
+ # T-instance hosts do not report available capacity and can be overprovisioned
16
+ if host.available_capacity.nil?
17
+ true
18
+ else
19
+ instance_capacity = host.available_capacity.available_instance_capacity
20
+ capacity_for_type = instance_capacity.detect { |cap| cap.instance_type == config[:instance_type] }
21
+ capacity_for_type.available_capacity > 0
22
+ end
23
+ end
24
+ end
25
+
26
+ # check if host has no instances running
27
+ # @param host_id [Aws::EC2::Types::Host] dedicated host
28
+ # @return Boolean
29
+ def host_unused?(host)
30
+ host.instances.empty?
31
+ end
32
+
33
+ # get host data for host id
34
+ # @param host_id [Aws::EC2::Types::Host] dedicated host
35
+ # @return Array(Aws::EC2::Types::Host)
36
+ def host_for_id(host_id)
37
+ ec2.client.describe_hosts(host_ids: [host_id])&.first
38
+ end
39
+
40
+ # get dedicated hosts managed by Test Kitchen
41
+ # @return Array(Aws::EC2::Types::Host)
42
+ def hosts_managed
43
+ response = ec2.client.describe_hosts(
44
+ filter: [
45
+ { name: "tag:ManagedBy", values: ["Test Kitchen"] },
46
+ ]
47
+ )
48
+
49
+ response.hosts.select { |host| host.state == "available" }
50
+ end
51
+
52
+ # allocate new dedicated host for requested instance type
53
+ # @return String host id
54
+ def allocate_host
55
+ unless allow_allocate_host?
56
+ warn "ERROR: Attempted to allocate dedicated host but need environment variable TK_ALLOCATE_DEDICATED_HOST to be set"
57
+ exit!
58
+ end
59
+
60
+ unless config[:availability_zone]
61
+ warn "Attempted to allocate dedicated host but option 'availability_zone' is not set"
62
+ exit!
63
+ end
64
+
65
+ info("Allocating dedicated host for #{config[:instance_type]} instances. This will incur additional cost")
66
+
67
+ request = {
68
+ availability_zone: config[:availability_zone],
69
+ quantity: 1,
70
+
71
+ auto_placement: "on",
72
+
73
+ tag_specifications: [
74
+ {
75
+ resource_type: "dedicated-host",
76
+ tags: [
77
+ { key: "ManagedBy", value: "Test Kitchen" },
78
+ ],
79
+ },
80
+ ],
81
+ }
82
+
83
+ # ".metal" is a 1:1 association, everything else has multi-instance capability
84
+ if instance_size_from_type(config[:instance_type]) == "metal"
85
+ request[:instance_type] = config[:instance_type]
86
+ else
87
+ request[:instance_family] = instance_family_from_type(config[:instance_type])
88
+ end
89
+
90
+ response = ec2.client.allocate_hosts(request)
91
+ response.host_ids.first
92
+ end
93
+
94
+ # deallocate a dedicated host
95
+ # @param host_id [String] dedicated host id
96
+ # @return Aws::EC2::Types::ReleaseHostsResult
97
+ def deallocate_host(host_id)
98
+ info("Deallocating dedicated host #{host_id}")
99
+
100
+ response = ec2.client.release_hosts({ host_ids: [host_id] })
101
+ unless response.unsuccessful.empty?
102
+ warn "ERROR: Could not release dedicated host #{host_id}. Host may remain allocated and incur cost"
103
+ exit!
104
+ end
105
+ end
106
+
107
+ # return instance family from type
108
+ # @param instance_type [String] type in format family.size
109
+ # @return String instance family
110
+ def instance_family_from_type(instance_type)
111
+ instance_type.split(".").first
112
+ end
113
+
114
+ # return instance size from type
115
+ # @param instance_type [String] type in format family.size
116
+ # @return String instance size
117
+ def instance_size_from_type(instance_type)
118
+ instance_type.split(".").last
119
+ end
120
+
121
+ # check config, if host allocation is enabled
122
+ # @return Boolean
123
+ def allow_allocate_host?
124
+ config[:allocate_dedicated_host]
125
+ end
126
+
127
+ # check config, if host deallocation is enabled
128
+ # @return Boolean
129
+ def allow_deallocate_host?
130
+ config[:deallocate_dedicated_host]
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -21,6 +21,7 @@ require "json" unless defined?(JSON)
21
21
  require "kitchen"
22
22
  require_relative "ec2_version"
23
23
  require_relative "aws/client"
24
+ require_relative "aws/dedicated_hosts"
24
25
  require_relative "aws/instance_generator"
25
26
  require_relative "aws/standard_platform"
26
27
  require_relative "aws/standard_platform/amazon"
@@ -89,6 +90,10 @@ module Kitchen
89
90
  default_config :instance_initiated_shutdown_behavior, nil
90
91
  default_config :ssl_verify_peer, true
91
92
  default_config :skip_cost_warning, false
93
+ default_config :allocate_dedicated_host, false
94
+ default_config :deallocate_dedicated_host, false
95
+
96
+ include Kitchen::Driver::Mixins::DedicatedHosts
92
97
 
93
98
  def initialize(*args, &block)
94
99
  super
@@ -225,6 +230,18 @@ module Kitchen
225
230
  config[:aws_ssh_key_id] = nil
226
231
  end
227
232
 
233
+ # Allocate new dedicated hosts if needed and allowed
234
+ if config[:tenancy] == "host"
235
+ unless host_available? || allow_allocate_host?
236
+ warn "ERROR: tenancy `host` requested but no suitable host and allocation not allowed (set `allocate_dedicated_host` setting)"
237
+ exit!
238
+ end
239
+
240
+ allocate_host unless host_available?
241
+
242
+ info("Auto placement on one dedicated host out of: #{hosts_with_capacity.map(&:host_id).join(", ")}")
243
+ end
244
+
228
245
  if config[:spot_price]
229
246
  # Spot instance when a price is set
230
247
  server = with_request_limit_backoff(state) { submit_spots }
@@ -296,6 +313,12 @@ module Kitchen
296
313
  # Clean up any auto-created security groups or keys.
297
314
  delete_security_group(state)
298
315
  delete_key(state)
316
+
317
+ # Clean up dedicated hosts matching instance_type and unused (if allowed)
318
+ if config[:tenancy] == "host" && allow_deallocate_host?
319
+ empty_hosts = hosts_with_capacity.select { |host| host_unused?(host) }
320
+ empty_hosts.each { |host| deallocate_host(host.host_id) }
321
+ end
299
322
  end
300
323
 
301
324
  def image
@@ -21,6 +21,6 @@ module Kitchen
21
21
  module Driver
22
22
 
23
23
  # Version string for EC2 Test Kitchen driver
24
- EC2_VERSION = "3.13.0".freeze
24
+ EC2_VERSION = "3.14.0".freeze
25
25
  end
26
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.13.0
4
+ version: 3.14.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: 2022-05-30 00:00:00.000000000 Z
11
+ date: 2022-12-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: test-kitchen
@@ -73,6 +73,7 @@ extra_rdoc_files: []
73
73
  files:
74
74
  - LICENSE
75
75
  - lib/kitchen/driver/aws/client.rb
76
+ - lib/kitchen/driver/aws/dedicated_hosts.rb
76
77
  - lib/kitchen/driver/aws/instance_generator.rb
77
78
  - lib/kitchen/driver/aws/standard_platform.rb
78
79
  - lib/kitchen/driver/aws/standard_platform/amazon.rb
@@ -90,7 +91,7 @@ homepage: https://github.com/test-kitchen/kitchen-ec2
90
91
  licenses:
91
92
  - Apache-2.0
92
93
  metadata: {}
93
- post_install_message:
94
+ post_install_message:
94
95
  rdoc_options: []
95
96
  require_paths:
96
97
  - lib
@@ -105,8 +106,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
105
106
  - !ruby/object:Gem::Version
106
107
  version: '0'
107
108
  requirements: []
108
- rubygems_version: 3.2.3
109
- signing_key:
109
+ rubygems_version: 3.2.32
110
+ signing_key:
110
111
  specification_version: 4
111
112
  summary: A Test Kitchen Driver for Amazon EC2
112
113
  test_files: []