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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f3b81a785bd64e6ae13091e71fe8faf3b295755fc9b30d4cee0c84246a107ea1
|
|
4
|
+
data.tar.gz: c0bfc45018438894ebb3775204d3e712ed5aef754a81b7588cb0cca79369e2ab
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
data/lib/kitchen/driver/ec2.rb
CHANGED
|
@@ -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
|
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.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-
|
|
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.
|
|
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
|