kitchen-ec2 3.13.0 → 3.14.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: 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: []