kitchen-ec2 3.22.7 → 3.22.9
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 +3 -1
- data/lib/kitchen/driver/aws/instance_generator.rb +5 -3
- data/lib/kitchen/driver/aws/standard_platform/alma.rb +17 -0
- data/lib/kitchen/driver/aws/standard_platform/fedora.rb +31 -1
- data/lib/kitchen/driver/aws/standard_platform/freebsd.rb +22 -0
- data/lib/kitchen/driver/aws/standard_platform/rhel.rb +5 -4
- data/lib/kitchen/driver/aws/standard_platform.rb +14 -0
- data/lib/kitchen/driver/ec2.rb +73 -6
- data/lib/kitchen/driver/ec2_version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 54de858935bf91fcad58900283fd45042007c18d546797d098f29b955d177c87
|
|
4
|
+
data.tar.gz: 95fc2485b796d0e87974e17de7b34dd858c08fdb2d2433cbae6975983cea1501
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dad42aca368360dd2d11c58583d13360f34fa77925a0fd40ede0c97da97092361c74ba7b61401918d7c1ae33732806fe8cdd7ddb84b2d23024dc21a20a94a835
|
|
7
|
+
data.tar.gz: 5e3a1ce54adf7425bce0c70816b212b0a2e8be36f35e9a1f8a58ebe971cfda2ace1c004e9dea91dc5d334021ba8df5f7541d1f891b1121021a9321f82d0f311c
|
|
@@ -91,7 +91,9 @@ module Kitchen
|
|
|
91
91
|
# host costs money whether or not it is used.
|
|
92
92
|
def allocate_host
|
|
93
93
|
unless allow_allocate_host?
|
|
94
|
-
warn "ERROR: Attempted to allocate dedicated host but
|
|
94
|
+
warn "ERROR: Attempted to allocate a dedicated host, but the driver setting `allocate_dedicated_host` is not enabled. " \
|
|
95
|
+
"Set `allocate_dedicated_host: true` to allow it, remembering that a dedicated host is billed from allocation " \
|
|
96
|
+
"until it is released."
|
|
95
97
|
exit!
|
|
96
98
|
end
|
|
97
99
|
|
|
@@ -232,11 +232,13 @@ module Kitchen
|
|
|
232
232
|
i[:placement][:tenancy] = placement[:tenancy]
|
|
233
233
|
end
|
|
234
234
|
end
|
|
235
|
+
# RunInstances calls this `license_specifications`. The driver option
|
|
236
|
+
# is `licenses`, and the payload key used to match the option rather
|
|
237
|
+
# than the API, which no EC2 API accepts.
|
|
235
238
|
license_specifications = config[:licenses]
|
|
236
239
|
if license_specifications
|
|
237
|
-
i[:
|
|
238
|
-
|
|
239
|
-
i[:licenses].append({ license_configuration_arn: license_configuration_arn[:license_configuration_arn] })
|
|
240
|
+
i[:license_specifications] = license_specifications.map do |license|
|
|
241
|
+
{ license_configuration_arn: license[:license_configuration_arn] }
|
|
240
242
|
end
|
|
241
243
|
end
|
|
242
244
|
unless config[:instance_initiated_shutdown_behavior].nil? ||
|
|
@@ -50,6 +50,23 @@ module Kitchen
|
|
|
50
50
|
search
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
+
# Sort images newest release first, keeping Kitten builds last.
|
|
54
|
+
#
|
|
55
|
+
# AlmaLinux Kitten is AlmaLinux's development distribution, published
|
|
56
|
+
# from the same account and under the same "AlmaLinux OS" prefix as
|
|
57
|
+
# the releases. Its name carries no release number, so {.from_image}
|
|
58
|
+
# reads the major straight into the build date: "AlmaLinux OS Kitten
|
|
59
|
+
# 10.20260727.0" yields "10.20260727", a far larger number than the
|
|
60
|
+
# "10.2" of an actual release, which sorts Kitten ahead of
|
|
61
|
+
# everything. A versioned search is unaffected, since "AlmaLinux OS
|
|
62
|
+
# 10*" does not match "AlmaLinux OS Kitten 10*".
|
|
63
|
+
#
|
|
64
|
+
# @param images [Array<Aws::EC2::Image>] the images to sort
|
|
65
|
+
# @return [Array<Aws::EC2::Image>] the images, newest release first
|
|
66
|
+
def sort_by_version(images)
|
|
67
|
+
prefer(super) { |image| !image.name.include?("Kitten") }
|
|
68
|
+
end
|
|
69
|
+
|
|
53
70
|
# Detect this platform from an EC2 image.
|
|
54
71
|
#
|
|
55
72
|
# Matching is done on the image name, which is the only reliable signal
|
|
@@ -23,6 +23,12 @@ module Kitchen
|
|
|
23
23
|
class Fedora < StandardPlatform
|
|
24
24
|
StandardPlatform.platforms["fedora"] = self
|
|
25
25
|
|
|
26
|
+
# Name fragments marking an image as a development stream rather
|
|
27
|
+
# than a Fedora release: Rawhide (the rolling development branch),
|
|
28
|
+
# ELN (Enterprise Linux Next) and the Prerelease builds published
|
|
29
|
+
# while a release is still stabilising.
|
|
30
|
+
DEVELOPMENT_STREAMS = /-(?:Rawhide|ELN|Prerelease)-/i
|
|
31
|
+
|
|
26
32
|
# The account EC2 creates on this platform's official AMIs.
|
|
27
33
|
#
|
|
28
34
|
# Used as the SSH username when the transport does not specify one.
|
|
@@ -43,12 +49,36 @@ module Kitchen
|
|
|
43
49
|
def image_search
|
|
44
50
|
search = {
|
|
45
51
|
"owner-id" => "125523088429",
|
|
46
|
-
"name" =>
|
|
52
|
+
"name" => if version
|
|
53
|
+
# Both naming schemes are searched because the older
|
|
54
|
+
# one is still present in some regions.
|
|
55
|
+
["Fedora-Cloud-Base-AmazonEC2.*-#{version}-*",
|
|
56
|
+
"Fedora-Cloud-Base-#{version}-*"]
|
|
57
|
+
else
|
|
58
|
+
"Fedora-Cloud-Base-*"
|
|
59
|
+
end,
|
|
47
60
|
}
|
|
48
61
|
search["architecture"] = architecture if architecture
|
|
49
62
|
search
|
|
50
63
|
end
|
|
51
64
|
|
|
65
|
+
# Sort images newest release first, keeping development streams last.
|
|
66
|
+
#
|
|
67
|
+
# Fedora publishes Rawhide, ELN and Prerelease images from the same
|
|
68
|
+
# account and under the same "Fedora-Cloud-Base-" prefix as its
|
|
69
|
+
# releases. Those names carry a build date where a release carries a
|
|
70
|
+
# release number, so {.from_image} reads a version like "20250820.0"
|
|
71
|
+
# off them -- larger than any real release, which sorts them to the
|
|
72
|
+
# front. They are pushed to the back afterwards, the same way RHEL
|
|
73
|
+
# handles its Beta images.
|
|
74
|
+
#
|
|
75
|
+
# @param images [Array<Aws::EC2::Image>] the images to sort
|
|
76
|
+
# @return [Array<Aws::EC2::Image>] the images, newest release first
|
|
77
|
+
def sort_by_version(images)
|
|
78
|
+
images = super
|
|
79
|
+
prefer(images) { |image| !DEVELOPMENT_STREAMS.match?(image.name) }
|
|
80
|
+
end
|
|
81
|
+
|
|
52
82
|
# Detect this platform from an EC2 image.
|
|
53
83
|
#
|
|
54
84
|
# Matching is done on the image name, which is the only reliable signal
|
|
@@ -57,6 +57,28 @@ module Kitchen
|
|
|
57
57
|
search
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
+
# Sort images newest release first, preferring the cloud-init flavor.
|
|
61
|
+
#
|
|
62
|
+
# FreeBSD publishes several flavors of each release, distinguished
|
|
63
|
+
# only by a word at the end of the image name, and only the
|
|
64
|
+
# cloud-init flavor is a general-purpose cloud image. "base" and
|
|
65
|
+
# "small" ship without sudo, so a converge fails on them; "builder"
|
|
66
|
+
# is a developer image that does not boot to a usable state on a
|
|
67
|
+
# small instance -- launched on a t3.micro it reaches "impaired" and
|
|
68
|
+
# never opens port 22. Nothing in the name distinguishes them by
|
|
69
|
+
# date or version, so without a preference the flavor selected is
|
|
70
|
+
# effectively arbitrary.
|
|
71
|
+
#
|
|
72
|
+
# Releases old enough to predate the flavored names publish a single
|
|
73
|
+
# image each. Because this is a stable partition rather than a
|
|
74
|
+
# filter, those are left where the version sort put them.
|
|
75
|
+
#
|
|
76
|
+
# @param images [Array<Aws::EC2::Image>] the images to sort
|
|
77
|
+
# @return [Array<Aws::EC2::Image>] the images, best match first
|
|
78
|
+
def sort_by_version(images)
|
|
79
|
+
prefer(super) { |image| image.name.include?("cloud-init") }
|
|
80
|
+
end
|
|
81
|
+
|
|
60
82
|
# Detect this platform from an EC2 image.
|
|
61
83
|
#
|
|
62
84
|
# Matching is done on the image name, which is the only reliable signal
|
|
@@ -90,10 +90,11 @@ module Kitchen
|
|
|
90
90
|
# @param images [Array<Aws::EC2::Image>] the images to sort
|
|
91
91
|
# @return [Array<Aws::EC2::Image>] the images, best match first
|
|
92
92
|
def sort_by_version(images)
|
|
93
|
-
#
|
|
94
|
-
|
|
95
|
-
#
|
|
96
|
-
|
|
93
|
+
# `prefer(super)`, not `super(images)` followed by
|
|
94
|
+
# `prefer(images)`: `prefer` returns a new array rather than
|
|
95
|
+
# reordering in place, so applying it to the original argument
|
|
96
|
+
# discarded the version sort entirely.
|
|
97
|
+
prefer(super) { |image| !image.name.match?(/_Beta-/i) }
|
|
97
98
|
end
|
|
98
99
|
end
|
|
99
100
|
end
|
|
@@ -153,6 +153,20 @@ module Kitchen
|
|
|
153
153
|
#
|
|
154
154
|
def self.from_platform_string(driver, platform_string)
|
|
155
155
|
platform, version, architecture = parse_platform_string(platform_string)
|
|
156
|
+
|
|
157
|
+
# A few platform names end in what looks like a version but is
|
|
158
|
+
# really part of the distribution's name: "amazon2023" and "amazon2"
|
|
159
|
+
# are Amazon Linux 2023 and Amazon Linux 2, not releases 2023 and 2
|
|
160
|
+
# of "amazon" (which is the long-EOL Amazon Linux 1). Written with a
|
|
161
|
+
# dash -- the spelling the documentation uses -- the split above
|
|
162
|
+
# lands on the "amazon" platform searching for a release that never
|
|
163
|
+
# existed, and no image matches. Fold the release back into the name
|
|
164
|
+
# whenever the two together name a platform that is registered.
|
|
165
|
+
if version && platforms["#{platform}#{version}"]
|
|
166
|
+
platform = "#{platform}#{version}"
|
|
167
|
+
version = nil
|
|
168
|
+
end
|
|
169
|
+
|
|
156
170
|
return unless platform && platforms[platform]
|
|
157
171
|
|
|
158
172
|
platforms[platform].new(driver, platform, version, architecture)
|
data/lib/kitchen/driver/ec2.rb
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
# See the License for the specific language governing permissions and
|
|
17
17
|
# limitations under the License.
|
|
18
18
|
|
|
19
|
+
require "fileutils" unless defined?(FileUtils)
|
|
19
20
|
require "sshkey" unless defined?(SSHKey)
|
|
20
21
|
require "benchmark" unless defined?(Benchmark)
|
|
21
22
|
require "json" unless defined?(JSON)
|
|
@@ -248,11 +249,13 @@ module Kitchen
|
|
|
248
249
|
#
|
|
249
250
|
# Any failure destroys the instance and everything auto-created alongside
|
|
250
251
|
# it, so that a failed create does not leave billable resources behind.
|
|
252
|
+
# Interrupts are re-raised untouched once that cleanup has run.
|
|
251
253
|
#
|
|
252
254
|
# @param state [Hash] the instance state, updated in place with
|
|
253
255
|
# `:server_id`, `:hostname` and any auto-created credentials
|
|
254
256
|
# @return [void]
|
|
255
|
-
# @raise [
|
|
257
|
+
# @raise [Kitchen::ActionFailed] wrapping whatever went wrong, after
|
|
258
|
+
# cleaning up
|
|
256
259
|
def create(state)
|
|
257
260
|
return if state[:server_id]
|
|
258
261
|
|
|
@@ -335,10 +338,60 @@ module Kitchen
|
|
|
335
338
|
attach_network_interface(state) unless config[:elastic_network_interface_id].nil?
|
|
336
339
|
create_ec2_json(state) if /chef/i.match?(instance.provisioner.name)
|
|
337
340
|
debug("ec2:create '#{state[:hostname]}'")
|
|
338
|
-
rescue Exception => e
|
|
339
|
-
#
|
|
341
|
+
rescue ::Exception => e
|
|
342
|
+
# Deliberately ::Exception, and deliberately broad: a create that is
|
|
343
|
+
# interrupted partway through must still clean up, or the user is left
|
|
344
|
+
# paying for an instance Test Kitchen has forgotten about.
|
|
345
|
+
#
|
|
346
|
+
# Root-qualified because this file is nested inside `module Kitchen`.
|
|
347
|
+
# There is no Kitchen::Exception today, but Kitchen::StandardError does
|
|
348
|
+
# exist, and an unqualified constant would silently pick it up if one
|
|
349
|
+
# were ever added.
|
|
340
350
|
destroy(state)
|
|
341
|
-
|
|
351
|
+
|
|
352
|
+
# Signals and exits are re-raised untouched. Wrapping a Ctrl-C in an
|
|
353
|
+
# ActionFailed would report the user's own interrupt as a driver bug.
|
|
354
|
+
raise if e.is_a?(::SignalException) || e.is_a?(::SystemExit)
|
|
355
|
+
|
|
356
|
+
raise Kitchen::ActionFailed, create_failure_message(e), e.backtrace
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
# Describe a failed create without discarding what actually went wrong.
|
|
360
|
+
#
|
|
361
|
+
# This message used to append "in the specified region <region>. Please
|
|
362
|
+
# check this AMI is available in this region" to *every* failure, and to
|
|
363
|
+
# raise a bare RuntimeError, so the original exception class and
|
|
364
|
+
# backtrace were lost. A local OpenSSL fault, an expired credential or a
|
|
365
|
+
# missing subnet all arrived looking like an AMI problem, sending users
|
|
366
|
+
# to check something that was never wrong.
|
|
367
|
+
#
|
|
368
|
+
# The hint is worth keeping -- an AMI that does not exist in the region
|
|
369
|
+
# really is a common mistake -- but only when the failure is about the
|
|
370
|
+
# image.
|
|
371
|
+
#
|
|
372
|
+
# @param error [Exception] the underlying failure
|
|
373
|
+
# @return [String]
|
|
374
|
+
# @see https://github.com/test-kitchen/kitchen-ec2/issues/606
|
|
375
|
+
def create_failure_message(error)
|
|
376
|
+
message = "Failed to create the EC2 instance: #{error.class}: #{error.message}"
|
|
377
|
+
return message unless image_related_error?(error)
|
|
378
|
+
|
|
379
|
+
"#{message} Check that image #{config[:image_id]} exists and is available " \
|
|
380
|
+
"in region #{config[:region]}."
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
# Whether a failure is about the AMI rather than something else entirely.
|
|
384
|
+
#
|
|
385
|
+
# EC2 reports every image problem with a code beginning "InvalidAMI"; the
|
|
386
|
+
# message check catches errors raised by the driver itself, which are
|
|
387
|
+
# plain strings with no code attached.
|
|
388
|
+
#
|
|
389
|
+
# @param error [Exception] the underlying failure
|
|
390
|
+
# @return [Boolean]
|
|
391
|
+
def image_related_error?(error)
|
|
392
|
+
return true if error.respond_to?(:code) && error.code.to_s.start_with?("InvalidAMI")
|
|
393
|
+
|
|
394
|
+
error.message.to_s.match?(/\bAMI\b/i)
|
|
342
395
|
end
|
|
343
396
|
|
|
344
397
|
# Terminate the instance and clean up everything created alongside it.
|
|
@@ -1179,7 +1232,12 @@ module Kitchen
|
|
|
1179
1232
|
info("Removing automatic key pair #{state[:auto_key_id]}")
|
|
1180
1233
|
ec2.client.delete_key_pair(key_name: state[:auto_key_id])
|
|
1181
1234
|
state.delete(:auto_key_id)
|
|
1182
|
-
|
|
1235
|
+
# The file is not always still there: it may have been cleaned up by
|
|
1236
|
+
# hand, wiped along with .kitchen, or never written at all, since
|
|
1237
|
+
# create records the key pair in the state before writing it. This is
|
|
1238
|
+
# the last thing destroy does, so raising here fails the whole action
|
|
1239
|
+
# after every AWS resource has already been cleaned up successfully.
|
|
1240
|
+
FileUtils.rm_f("#{config[:kitchen_root]}/.kitchen/#{instance.name}.pem")
|
|
1183
1241
|
end
|
|
1184
1242
|
|
|
1185
1243
|
# Finalize the driver config and install transport overrides.
|
|
@@ -1648,9 +1706,18 @@ module Kitchen
|
|
|
1648
1706
|
"--region", driver_instance.config[:region]
|
|
1649
1707
|
]
|
|
1650
1708
|
|
|
1651
|
-
#
|
|
1709
|
+
# Tunnelling SSH over SSM needs a session document that forwards a
|
|
1710
|
+
# port. Without one, `start-session` opens an interactive shell
|
|
1711
|
+
# session instead, which speaks nothing SSH understands: pointed at
|
|
1712
|
+
# that as a ProxyCommand, SSH waits for a banner that never comes
|
|
1713
|
+
# and the create hangs until it is interrupted. AWS-StartSSHSession
|
|
1714
|
+
# is the document AWS publishes for this, and `%p` is substituted by
|
|
1715
|
+
# Net::SSH::Proxy::Command with the port being connected on, so a
|
|
1716
|
+
# transport using a port other than 22 tunnels to that port.
|
|
1652
1717
|
if driver_instance.config[:ssm_session_manager_document_name]
|
|
1653
1718
|
cmd += ["--document-name", driver_instance.config[:ssm_session_manager_document_name]]
|
|
1719
|
+
else
|
|
1720
|
+
cmd += ["--document-name", "AWS-StartSSHSession", "--parameters", "portNumber=%p"]
|
|
1654
1721
|
end
|
|
1655
1722
|
|
|
1656
1723
|
# Add AWS profile if specified
|