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 +4 -4
- data/lib/kitchen/driver/aws/dedicated_hosts.rb +135 -0
- data/lib/kitchen/driver/ec2.rb +23 -0
- data/lib/kitchen/driver/ec2_version.rb +1 -1
- metadata +7 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0ab954ba95ae18b5a8af7013f2c2a62ac9437375ea4c4d9fa82c09448335b6ee
|
|
4
|
+
data.tar.gz: d721117b22321834df518eb5c0a8c14495141148546b48717a337f8953457c20
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
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"
|
|
@@ -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
|
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.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-
|
|
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.
|
|
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: []
|