kitchen-ec2 3.13.0 → 3.15.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: f3b81a785bd64e6ae13091e71fe8faf3b295755fc9b30d4cee0c84246a107ea1
4
+ data.tar.gz: c0bfc45018438894ebb3775204d3e712ed5aef754a81b7588cb0cca79369e2ab
5
5
  SHA512:
6
- metadata.gz: 890a0a34755ab636605a8fcfbc45ce8c0f055adb0fa5404c48d516060da3089628091d37bbc9ad555601d742f40647183f2b34988dc703ca03477722b3dfb1bf
7
- data.tar.gz: 617aaee4fdd8b335e17731621abb9ae140b73286e4da2e77adbb46cdc560789f02eeb85f208217e3ffbd03746c52a46f4ae051d93ab1436fb2fb8f3f2b267351
6
+ metadata.gz: 0d13f84f11907b1fb657dca1a400173be055420c30a7a5282af7273c7f1ecfd48485abdf24dc1d1fbe1fa67f4642564b080243f1fdae9d1e400052e3119e7f68
7
+ data.tar.gz: bb606e4db8b58e7ed57951cca247e4c8271fdbe5430ba59102f2524c0de9201ab46ea38fb431101f92ea02ac720ea508f5b59abb383ed4ffab5821f251366a71
@@ -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
@@ -0,0 +1,51 @@
1
+ #
2
+ # Copyright:: 2016-2018, Chef Software, Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require_relative "../standard_platform"
17
+
18
+ module Kitchen
19
+ module Driver
20
+ class Aws
21
+ class StandardPlatform
22
+ class MacOS < StandardPlatform
23
+ StandardPlatform.platforms["macos"] = self
24
+
25
+ # default username for this platform's ami
26
+ # @return [String]
27
+ def username
28
+ "ec2-user"
29
+ end
30
+
31
+ def image_search
32
+ search = {
33
+ "owner-id" => "100343932686",
34
+ "name" => version ? "amzn-ec2-macos-#{version}*" : "amzn2-ec2-macos-*",
35
+ }
36
+ search["architecture"] = architecture if architecture
37
+ search["architecture"] = "arm64_mac" if architecture == "arm64"
38
+ search
39
+ end
40
+
41
+ def self.from_image(driver, image)
42
+ if /amzn-ec2-macos/i.match?(image.name)
43
+ image.name =~ /\b(\d+(\.\d+[\.\d])?)/i
44
+ new(driver, "macos", (Regexp.last_match || [])[1], image.architecture)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -27,6 +27,7 @@ module Kitchen
27
27
  # rhel
28
28
  # fedora
29
29
  # freebsd
30
+ # macos
30
31
  # ubuntu
31
32
  # windows
32
33
  #
@@ -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"
@@ -30,6 +31,7 @@ require_relative "aws/standard_platform/debian"
30
31
  require_relative "aws/standard_platform/rhel"
31
32
  require_relative "aws/standard_platform/fedora"
32
33
  require_relative "aws/standard_platform/freebsd"
34
+ require_relative "aws/standard_platform/macos"
33
35
  require_relative "aws/standard_platform/ubuntu"
34
36
  require_relative "aws/standard_platform/windows"
35
37
  require "aws-sdk-ec2"
@@ -78,6 +80,7 @@ module Kitchen
78
80
  default_config :aws_secret_access_key, nil
79
81
  default_config :aws_session_token, nil
80
82
  default_config :aws_ssh_key_id, ENV["AWS_SSH_KEY_ID"]
83
+ default_config :aws_ssh_key_type, "rsa"
81
84
  default_config :image_id, &:default_ami
82
85
  default_config :image_search, nil
83
86
  default_config :username, nil
@@ -89,6 +92,10 @@ module Kitchen
89
92
  default_config :instance_initiated_shutdown_behavior, nil
90
93
  default_config :ssl_verify_peer, true
91
94
  default_config :skip_cost_warning, false
95
+ default_config :allocate_dedicated_host, false
96
+ default_config :deallocate_dedicated_host, false
97
+
98
+ include Kitchen::Driver::Mixins::DedicatedHosts
92
99
 
93
100
  def initialize(*args, &block)
94
101
  super
@@ -225,6 +232,18 @@ module Kitchen
225
232
  config[:aws_ssh_key_id] = nil
226
233
  end
227
234
 
235
+ # Allocate new dedicated hosts if needed and allowed
236
+ if config[:tenancy] == "host"
237
+ unless host_available? || allow_allocate_host?
238
+ warn "ERROR: tenancy `host` requested but no suitable host and allocation not allowed (set `allocate_dedicated_host` setting)"
239
+ exit!
240
+ end
241
+
242
+ allocate_host unless host_available?
243
+
244
+ info("Auto placement on one dedicated host out of: #{hosts_with_capacity.map(&:host_id).join(", ")}")
245
+ end
246
+
228
247
  if config[:spot_price]
229
248
  # Spot instance when a price is set
230
249
  server = with_request_limit_backoff(state) { submit_spots }
@@ -296,6 +315,12 @@ module Kitchen
296
315
  # Clean up any auto-created security groups or keys.
297
316
  delete_security_group(state)
298
317
  delete_key(state)
318
+
319
+ # Clean up dedicated hosts matching instance_type and unused (if allowed)
320
+ if config[:tenancy] == "host" && allow_deallocate_host?
321
+ empty_hosts = hosts_with_capacity.select { |host| host_unused?(host) }
322
+ empty_hosts.each { |host| deallocate_host(host.host_id) }
323
+ end
299
324
  end
300
325
 
301
326
  def image
@@ -830,7 +855,7 @@ module Kitchen
830
855
  # to rapidly exhaust local entropy by creating a lot of keys. So this is
831
856
  # probably fine. If you want very high security, probably don't use this
832
857
  # feature anyway.
833
- resp = ec2.client.create_key_pair(key_name: "kitchen-#{name_parts.join("-")}")
858
+ resp = ec2.client.create_key_pair(key_name: "kitchen-#{name_parts.join("-")}", key_type: config[:aws_ssh_key_type])
834
859
  state[:auto_key_id] = resp.key_name
835
860
  info("Created automatic key pair #{state[:auto_key_id]}")
836
861
  # Write the key out with safe permissions
@@ -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.15.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.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fletcher Nichol
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-30 00:00:00.000000000 Z
11
+ date: 2022-12-13 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
@@ -81,6 +82,7 @@ files:
81
82
  - lib/kitchen/driver/aws/standard_platform/debian.rb
82
83
  - lib/kitchen/driver/aws/standard_platform/fedora.rb
83
84
  - lib/kitchen/driver/aws/standard_platform/freebsd.rb
85
+ - lib/kitchen/driver/aws/standard_platform/macos.rb
84
86
  - lib/kitchen/driver/aws/standard_platform/rhel.rb
85
87
  - lib/kitchen/driver/aws/standard_platform/ubuntu.rb
86
88
  - lib/kitchen/driver/aws/standard_platform/windows.rb
@@ -105,7 +107,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
105
107
  - !ruby/object:Gem::Version
106
108
  version: '0'
107
109
  requirements: []
108
- rubygems_version: 3.2.3
110
+ rubygems_version: 3.3.16
109
111
  signing_key:
110
112
  specification_version: 4
111
113
  summary: A Test Kitchen Driver for Amazon EC2