kitchen-ec2 3.17.0 → 3.17.1
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/client.rb +4 -12
- data/lib/kitchen/driver/aws/dedicated_hosts.rb +4 -4
- data/lib/kitchen/driver/aws/instance_generator.rb +5 -13
- data/lib/kitchen/driver/aws/standard_platform/alma.rb +4 -4
- data/lib/kitchen/driver/aws/standard_platform/amazon.rb +4 -4
- data/lib/kitchen/driver/aws/standard_platform/amazon2.rb +4 -4
- data/lib/kitchen/driver/aws/standard_platform/amazon2023.rb +4 -4
- data/lib/kitchen/driver/aws/standard_platform/centos.rb +4 -4
- data/lib/kitchen/driver/aws/standard_platform/debian.rb +9 -9
- data/lib/kitchen/driver/aws/standard_platform/fedora.rb +4 -4
- data/lib/kitchen/driver/aws/standard_platform/freebsd.rb +4 -4
- data/lib/kitchen/driver/aws/standard_platform/macos.rb +4 -4
- data/lib/kitchen/driver/aws/standard_platform/rhel.rb +5 -5
- data/lib/kitchen/driver/aws/standard_platform/rocky.rb +4 -4
- data/lib/kitchen/driver/aws/standard_platform/ubuntu.rb +4 -4
- data/lib/kitchen/driver/aws/standard_platform/windows.rb +33 -34
- data/lib/kitchen/driver/aws/standard_platform.rb +25 -20
- data/lib/kitchen/driver/ec2.rb +59 -38
- data/lib/kitchen/driver/ec2_version.rb +1 -3
- metadata +25 -25
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: abdd51753a33ae7cf21aeb7f3073cd949d0c0c998eb065955b2bb8982441760a
|
|
4
|
+
data.tar.gz: f8a5ffd49f6213cc5822857f2af830be06fd42fe1c9a29cb60328b0fd4835e45
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b68043de14aab7e71d0b4c4570492e81b0e5b6af6e04ed0ed55df1db476f2f791de20030e0b630919a811c0605f8388719820ed3b7adf87d982b3a53b2b3d230
|
|
7
|
+
data.tar.gz: 74c9d0cea39fccd36f79ea1490f24946eac7ecd2670c0fe2434e1a43110727015e18472839a56b28f351e342d69eb038166edc45ecc00b4e15bfa9f393696461
|
|
@@ -22,16 +22,12 @@ require "aws-sdk-core/shared_credentials"
|
|
|
22
22
|
require "aws-sdk-core/instance_profile_credentials"
|
|
23
23
|
|
|
24
24
|
module Kitchen
|
|
25
|
-
|
|
26
25
|
module Driver
|
|
27
|
-
|
|
28
26
|
class Aws
|
|
29
|
-
|
|
30
27
|
# A class for creating and managing the EC2 client connection
|
|
31
28
|
#
|
|
32
29
|
# @author Tyler Ball <tball@chef.io>
|
|
33
30
|
class Client
|
|
34
|
-
|
|
35
31
|
def initialize(
|
|
36
32
|
region,
|
|
37
33
|
profile_name = "default",
|
|
@@ -40,12 +36,12 @@ module Kitchen
|
|
|
40
36
|
ssl_verify_peer = true
|
|
41
37
|
)
|
|
42
38
|
::Aws.config.update(
|
|
43
|
-
region
|
|
39
|
+
region:,
|
|
44
40
|
profile: profile_name,
|
|
45
|
-
http_proxy
|
|
46
|
-
ssl_verify_peer:
|
|
41
|
+
http_proxy:,
|
|
42
|
+
ssl_verify_peer:
|
|
47
43
|
)
|
|
48
|
-
::Aws.config.update(retry_limit:
|
|
44
|
+
::Aws.config.update(retry_limit:) unless retry_limit.nil?
|
|
49
45
|
end
|
|
50
46
|
|
|
51
47
|
# create a new AWS EC2 instance
|
|
@@ -89,11 +85,7 @@ module Kitchen
|
|
|
89
85
|
def resource
|
|
90
86
|
@resource ||= ::Aws::EC2::Resource.new
|
|
91
87
|
end
|
|
92
|
-
|
|
93
88
|
end
|
|
94
|
-
|
|
95
89
|
end
|
|
96
|
-
|
|
97
90
|
end
|
|
98
|
-
|
|
99
91
|
end
|
|
@@ -98,10 +98,10 @@ module Kitchen
|
|
|
98
98
|
info("Deallocating dedicated host #{host_id}")
|
|
99
99
|
|
|
100
100
|
response = ec2.client.release_hosts({ host_ids: [host_id] })
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
101
|
+
return if response.unsuccessful.empty?
|
|
102
|
+
|
|
103
|
+
warn "ERROR: Could not release dedicated host #{host_id}. Host may remain allocated and incur cost"
|
|
104
|
+
exit!
|
|
105
105
|
end
|
|
106
106
|
|
|
107
107
|
# return instance family from type
|
|
@@ -20,16 +20,12 @@ require "base64" unless defined?(Base64)
|
|
|
20
20
|
require "aws-sdk-ec2"
|
|
21
21
|
|
|
22
22
|
module Kitchen
|
|
23
|
-
|
|
24
23
|
module Driver
|
|
25
|
-
|
|
26
24
|
class Aws
|
|
27
|
-
|
|
28
25
|
# A class for encapsulating the instance payload logic
|
|
29
26
|
#
|
|
30
27
|
# @author Tyler Ball <tball@chef.io>
|
|
31
28
|
class InstanceGenerator
|
|
32
|
-
|
|
33
29
|
attr_reader :config, :ec2, :logger
|
|
34
30
|
|
|
35
31
|
def initialize(config, ec2, logger)
|
|
@@ -42,7 +38,7 @@ module Kitchen
|
|
|
42
38
|
# can be passed in null, others need to be ommitted if they are null
|
|
43
39
|
# Some fields can be passed in null, others need to be ommitted if they are null
|
|
44
40
|
# @return [Hash]
|
|
45
|
-
def ec2_instance_data
|
|
41
|
+
def ec2_instance_data
|
|
46
42
|
# Support for looking up security group id and subnet id using tags.
|
|
47
43
|
vpc_id = nil
|
|
48
44
|
client = ::Aws::EC2::Client.new(region: config[:region])
|
|
@@ -129,8 +125,8 @@ module Kitchen
|
|
|
129
125
|
# and Integers need to be represented as Strings
|
|
130
126
|
{ key: k, value: v.to_s }
|
|
131
127
|
end
|
|
132
|
-
instance_tag_spec = { resource_type: "instance", tags:
|
|
133
|
-
volume_tag_spec = { resource_type: "volume", tags:
|
|
128
|
+
instance_tag_spec = { resource_type: "instance", tags: }
|
|
129
|
+
volume_tag_spec = { resource_type: "volume", tags: }
|
|
134
130
|
i[:tag_specifications] = [instance_tag_spec, volume_tag_spec]
|
|
135
131
|
end
|
|
136
132
|
|
|
@@ -146,7 +142,7 @@ module Kitchen
|
|
|
146
142
|
if i.key?(:placement)
|
|
147
143
|
i[:placement][:tenancy] = tenancy
|
|
148
144
|
else
|
|
149
|
-
i[:placement] = { tenancy:
|
|
145
|
+
i[:placement] = { tenancy: }
|
|
150
146
|
end
|
|
151
147
|
end
|
|
152
148
|
unless config[:block_device_mappings].nil? || config[:block_device_mappings].empty?
|
|
@@ -190,7 +186,7 @@ module Kitchen
|
|
|
190
186
|
if i.key?(:placement)
|
|
191
187
|
i[:placement][:tenancy] = tenancy
|
|
192
188
|
else
|
|
193
|
-
i[:placement] = { tenancy:
|
|
189
|
+
i[:placement] = { tenancy: }
|
|
194
190
|
end
|
|
195
191
|
end
|
|
196
192
|
unless config[:instance_initiated_shutdown_behavior].nil? ||
|
|
@@ -212,11 +208,7 @@ module Kitchen
|
|
|
212
208
|
|
|
213
209
|
@user_data = Base64.encode64(raw_user_data)
|
|
214
210
|
end
|
|
215
|
-
|
|
216
211
|
end
|
|
217
|
-
|
|
218
212
|
end
|
|
219
|
-
|
|
220
213
|
end
|
|
221
|
-
|
|
222
214
|
end
|
|
@@ -40,10 +40,10 @@ module Kitchen
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def self.from_image(driver, image)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
return unless /AlmaLinux OS/i.match?(image.name)
|
|
44
|
+
|
|
45
|
+
image.name =~ /\b(\d+(\.\d+)?)\b/i
|
|
46
|
+
new(driver, "alma", (Regexp.last_match || [])[1], image.architecture)
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
end
|
|
@@ -39,10 +39,10 @@ module Kitchen
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def self.from_image(driver, image)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
return unless /amzn-ami/i.match?(image.name)
|
|
43
|
+
|
|
44
|
+
image.name =~ /\b(\d+(\.\d+[\.\d])?)/i
|
|
45
|
+
new(driver, "amazon", (Regexp.last_match || [])[1], image.architecture)
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
end
|
|
@@ -39,10 +39,10 @@ module Kitchen
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def self.from_image(driver, image)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
return unless /amzn2-ami/i.match?(image.name)
|
|
43
|
+
|
|
44
|
+
image.name =~ /\b(\d+(\.\d+[\.\d])?)/i
|
|
45
|
+
new(driver, "amazon2", (Regexp.last_match || [])[1], image.architecture)
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
end
|
|
@@ -39,10 +39,10 @@ module Kitchen
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def self.from_image(driver, image)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
return unless /al2023-ami/i.match?(image.name)
|
|
43
|
+
|
|
44
|
+
image.name =~ /\b(\d+(\.\d+[\.\d])?)/i
|
|
45
|
+
new(driver, "amazon2023", (Regexp.last_match || [])[1], image.architecture)
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
end
|
|
@@ -52,10 +52,10 @@ module Kitchen
|
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
def self.from_image(driver, image)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
return unless /centos/i.match?(image.name)
|
|
56
|
+
|
|
57
|
+
image.name =~ /\b(\d+(\.\d+)?)\b/i
|
|
58
|
+
new(driver, "centos", (Regexp.last_match || [])[1], image.architecture)
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
61
|
end
|
|
@@ -73,16 +73,16 @@ module Kitchen
|
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
def self.from_image(driver, image)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
end
|
|
84
|
-
new(driver, "debian", version, image.architecture)
|
|
76
|
+
return unless /debian/i.match?(image.name)
|
|
77
|
+
|
|
78
|
+
image.name =~ /\b(\d+|#{DEBIAN_CODENAMES.values.join("|")})\b/i
|
|
79
|
+
version = (Regexp.last_match || [])[1]
|
|
80
|
+
if version&.to_i&.zero?
|
|
81
|
+
version = DEBIAN_CODENAMES.find do |_v, codename|
|
|
82
|
+
codename == version.downcase
|
|
83
|
+
end.first
|
|
85
84
|
end
|
|
85
|
+
new(driver, "debian", version, image.architecture)
|
|
86
86
|
end
|
|
87
87
|
end
|
|
88
88
|
end
|
|
@@ -39,10 +39,10 @@ module Kitchen
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def self.from_image(driver, image)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
return unless /fedora/i.match?(image.name)
|
|
43
|
+
|
|
44
|
+
image.name =~ /\b(\d+(\.\d+)?)\b/i
|
|
45
|
+
new(driver, "fedora", (Regexp.last_match || [])[1], image.architecture)
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
end
|
|
@@ -41,10 +41,10 @@ module Kitchen
|
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def self.from_image(driver, image)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
return unless /freebsd/i.match?(image.name)
|
|
45
|
+
|
|
46
|
+
image.name =~ /\b(\d+(\.\d+)?)\b/i
|
|
47
|
+
new(driver, "freebsd", (Regexp.last_match || [])[1], image.architecture)
|
|
48
48
|
end
|
|
49
49
|
end
|
|
50
50
|
end
|
|
@@ -39,10 +39,10 @@ module Kitchen
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def self.from_image(driver, image)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
return unless /amzn-ec2-macos/i.match?(image.name)
|
|
43
|
+
|
|
44
|
+
image.name =~ /\b(\d+(\.\d+[\.\d])?)/i
|
|
45
|
+
new(driver, "macos", (Regexp.last_match || [])[1], image.architecture)
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
end
|
|
@@ -32,7 +32,7 @@ module Kitchen
|
|
|
32
32
|
# default username for this platform's ami
|
|
33
33
|
# @return [String]
|
|
34
34
|
def username
|
|
35
|
-
|
|
35
|
+
version && version.to_f < 6.4 ? "root" : "ec2-user"
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def image_search
|
|
@@ -45,10 +45,10 @@ module Kitchen
|
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
def self.from_image(driver, image)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
return unless /rhel/i.match?(image.name)
|
|
49
|
+
|
|
50
|
+
image.name =~ /\b(\d+(\.\d+)?)/i
|
|
51
|
+
new(driver, "rhel", (Regexp.last_match || [])[1], image.architecture)
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
def sort_by_version(images)
|
|
@@ -39,10 +39,10 @@ module Kitchen
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def self.from_image(driver, image)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
return unless /Rocky-/i.match?(image.name)
|
|
43
|
+
|
|
44
|
+
image.name =~ /\b(\d+(\.\d+[\.\d])?)/i
|
|
45
|
+
new(driver, "rocky", (Regexp.last_match || [])[1], image.architecture)
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
end
|
|
@@ -39,10 +39,10 @@ module Kitchen
|
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def self.from_image(driver, image)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
return unless /ubuntu/i.match?(image.name)
|
|
43
|
+
|
|
44
|
+
image.name =~ /\b(\d+(\.\d+)?)\b/i
|
|
45
|
+
new(driver, "ubuntu", (Regexp.last_match || [])[1], image.architecture)
|
|
46
46
|
end
|
|
47
47
|
end
|
|
48
48
|
end
|
|
@@ -70,21 +70,20 @@ module Kitchen
|
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
def self.from_image(driver, image)
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
new(driver, "windows", version, image.architecture)
|
|
73
|
+
return unless /Windows/i.match?(image.name)
|
|
74
|
+
|
|
75
|
+
# 2008 R2 SP2
|
|
76
|
+
if image.name =~ /(\b\d+)\W*(r\d+)?/i
|
|
77
|
+
major = (Regexp.last_match || [])[1]
|
|
78
|
+
revision = (Regexp.last_match || [])[2]
|
|
79
|
+
service_pack = (Regexp.last_match || [])[1] if image.name =~ /(sp\d+|rtm)/i
|
|
80
|
+
revision = revision.downcase if revision
|
|
81
|
+
service_pack ||= "rtm"
|
|
82
|
+
service_pack = service_pack.downcase
|
|
83
|
+
version = "#{major}#{revision}#{service_pack}"
|
|
87
84
|
end
|
|
85
|
+
|
|
86
|
+
new(driver, "windows", version, image.architecture)
|
|
88
87
|
end
|
|
89
88
|
|
|
90
89
|
protected
|
|
@@ -132,30 +131,30 @@ module Kitchen
|
|
|
132
131
|
|
|
133
132
|
private
|
|
134
133
|
|
|
135
|
-
def windows_name_filter
|
|
134
|
+
def windows_name_filter
|
|
136
135
|
major, revision, service_pack = windows_version_parts
|
|
137
|
-
if
|
|
136
|
+
if [2022, 2019, 2016].include?(major)
|
|
138
137
|
"Windows_Server-#{major}-English-Full-Base-*"
|
|
139
|
-
elsif
|
|
138
|
+
elsif [1709, 1803].include?(major)
|
|
140
139
|
"Windows_Server-#{major}-English-Core-ContainersLatest-*"
|
|
141
140
|
else
|
|
142
|
-
case revision
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
case service_pack
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
141
|
+
revision_strings = case revision
|
|
142
|
+
when nil
|
|
143
|
+
["", "R*_"]
|
|
144
|
+
when 0
|
|
145
|
+
[""]
|
|
146
|
+
else
|
|
147
|
+
["R#{revision}_"]
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
revision_strings = case service_pack
|
|
151
|
+
when nil
|
|
152
|
+
revision_strings.flat_map { |r| ["#{r}RTM", "#{r}SP*"] }
|
|
153
|
+
when 0
|
|
154
|
+
revision_strings.map { |r| "#{r}RTM" }
|
|
155
|
+
else
|
|
156
|
+
revision_strings.map { |r| "#{r}SP#{service_pack}" }
|
|
157
|
+
end
|
|
159
158
|
|
|
160
159
|
name_filter = revision_strings.map do |r|
|
|
161
160
|
"Windows_Server-#{major || "*"}-#{r}-English-*-Base-*"
|
|
@@ -91,6 +91,11 @@ module Kitchen
|
|
|
91
91
|
#
|
|
92
92
|
SUPPORTED_ARCHITECTURES = %w{x86_64 i386 arm64}.freeze
|
|
93
93
|
|
|
94
|
+
#
|
|
95
|
+
# The list of supported ebs volume types
|
|
96
|
+
#
|
|
97
|
+
EBS_VOLUME_TYPES = %w{gp3 gp2}.freeze
|
|
98
|
+
|
|
94
99
|
#
|
|
95
100
|
# Find the best matching image for the given image search.
|
|
96
101
|
#
|
|
@@ -103,12 +108,12 @@ module Kitchen
|
|
|
103
108
|
end
|
|
104
109
|
|
|
105
110
|
# We prefer most recent first
|
|
106
|
-
images = driver.ec2.resource.images(filters:
|
|
111
|
+
images = driver.ec2.resource.images(filters:)
|
|
107
112
|
images = sort_images(images)
|
|
108
113
|
show_returned_images(images)
|
|
109
114
|
|
|
110
115
|
# Grab the best match
|
|
111
|
-
images.first
|
|
116
|
+
images.first&.id
|
|
112
117
|
end
|
|
113
118
|
|
|
114
119
|
#
|
|
@@ -136,9 +141,9 @@ module Kitchen
|
|
|
136
141
|
#
|
|
137
142
|
def self.from_platform_string(driver, platform_string)
|
|
138
143
|
platform, version, architecture = parse_platform_string(platform_string)
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
144
|
+
return unless platform && platforms[platform]
|
|
145
|
+
|
|
146
|
+
platforms[platform].new(driver, platform, version, architecture)
|
|
142
147
|
end
|
|
143
148
|
|
|
144
149
|
#
|
|
@@ -157,6 +162,20 @@ module Kitchen
|
|
|
157
162
|
nil
|
|
158
163
|
end
|
|
159
164
|
|
|
165
|
+
def self.parse_platform_string(platform_string)
|
|
166
|
+
platform, version = platform_string.split("-", 2)
|
|
167
|
+
|
|
168
|
+
# If the right side is a valid architecture, use it as such
|
|
169
|
+
# i.e. debian-i386 or windows-server-2012r2-i386
|
|
170
|
+
if version && SUPPORTED_ARCHITECTURES.include?(version.split("-")[-1])
|
|
171
|
+
# server-2012r2-i386 -> server-2012r2, -, i386
|
|
172
|
+
version, _dash, architecture = version.rpartition("-")
|
|
173
|
+
version = nil if version == ""
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
[platform, version, architecture]
|
|
177
|
+
end
|
|
178
|
+
|
|
160
179
|
protected
|
|
161
180
|
|
|
162
181
|
#
|
|
@@ -192,20 +211,6 @@ module Kitchen
|
|
|
192
211
|
|
|
193
212
|
private
|
|
194
213
|
|
|
195
|
-
def self.parse_platform_string(platform_string)
|
|
196
|
-
platform, version = platform_string.split("-", 2)
|
|
197
|
-
|
|
198
|
-
# If the right side is a valid architecture, use it as such
|
|
199
|
-
# i.e. debian-i386 or windows-server-2012r2-i386
|
|
200
|
-
if version && SUPPORTED_ARCHITECTURES.include?(version.split("-")[-1])
|
|
201
|
-
# server-2012r2-i386 -> server-2012r2, -, i386
|
|
202
|
-
version, _dash, architecture = version.rpartition("-")
|
|
203
|
-
version = nil if version == ""
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
[platform, version, architecture]
|
|
207
|
-
end
|
|
208
|
-
|
|
209
214
|
def sort_images(images)
|
|
210
215
|
# P6: We prefer more recent images over older ones
|
|
211
216
|
images = images.sort_by(&:creation_date).reverse
|
|
@@ -214,7 +219,7 @@ module Kitchen
|
|
|
214
219
|
# P4: We prefer (SSD) (if available)
|
|
215
220
|
images = prefer(images) do |image|
|
|
216
221
|
image.block_device_mappings.any? do |b|
|
|
217
|
-
b.device_name == image.root_device_name && b.ebs &&
|
|
222
|
+
b.device_name == image.root_device_name && b.ebs && EBS_VOLUME_TYPES.any?(b.ebs.volume_type)
|
|
218
223
|
end
|
|
219
224
|
end
|
|
220
225
|
# P3: We prefer ebs over instance_store (if available)
|
data/lib/kitchen/driver/ec2.rb
CHANGED
|
@@ -45,20 +45,17 @@ require "etc" unless defined?(Etc)
|
|
|
45
45
|
require "socket" unless defined?(Socket)
|
|
46
46
|
|
|
47
47
|
module Kitchen
|
|
48
|
-
|
|
49
48
|
module Driver
|
|
50
|
-
|
|
51
49
|
# Amazon EC2 driver for Test Kitchen.
|
|
52
50
|
#
|
|
53
51
|
# @author Fletcher Nichol <fnichol@nichol.ca>
|
|
54
52
|
class Ec2 < Kitchen::Driver::Base
|
|
55
|
-
|
|
56
53
|
kitchen_driver_api_version 2
|
|
57
54
|
|
|
58
55
|
plugin_version Kitchen::Driver::EC2_VERSION
|
|
59
56
|
|
|
60
57
|
default_config :region, ENV["AWS_REGION"] || "us-east-1"
|
|
61
|
-
default_config :shared_credentials_profile, ENV
|
|
58
|
+
default_config :shared_credentials_profile, ENV.fetch("AWS_PROFILE", nil)
|
|
62
59
|
default_config :availability_zone, nil
|
|
63
60
|
default_config :instance_type, &:default_instance_type
|
|
64
61
|
default_config :ebs_optimized, false
|
|
@@ -82,14 +79,14 @@ module Kitchen
|
|
|
82
79
|
default_config :aws_access_key_id, nil
|
|
83
80
|
default_config :aws_secret_access_key, nil
|
|
84
81
|
default_config :aws_session_token, nil
|
|
85
|
-
default_config :aws_ssh_key_id, ENV
|
|
82
|
+
default_config :aws_ssh_key_id, ENV.fetch("AWS_SSH_KEY_ID", nil)
|
|
86
83
|
default_config :aws_ssh_key_type, "rsa"
|
|
87
84
|
default_config :image_id, &:default_ami
|
|
88
85
|
default_config :image_search, nil
|
|
89
86
|
default_config :username, nil
|
|
90
87
|
default_config :associate_public_ip, nil
|
|
91
88
|
default_config :interface, nil
|
|
92
|
-
default_config :http_proxy, ENV["HTTPS_PROXY"] || ENV
|
|
89
|
+
default_config :http_proxy, ENV["HTTPS_PROXY"] || ENV.fetch("HTTP_PROXY", nil)
|
|
93
90
|
default_config :retry_limit, 3
|
|
94
91
|
default_config :tenancy, "default"
|
|
95
92
|
default_config :instance_initiated_shutdown_behavior, nil
|
|
@@ -194,10 +191,10 @@ module Kitchen
|
|
|
194
191
|
end
|
|
195
192
|
|
|
196
193
|
# empty keys cause failures when tagging and they make no sense
|
|
197
|
-
validations[:tags] = lambda do |
|
|
194
|
+
validations[:tags] = lambda do |_attr, val, _driver|
|
|
198
195
|
# if someone puts the tags each on their own line it's an array not a hash
|
|
199
196
|
# @todo we should probably just do the right thing and support this format
|
|
200
|
-
if val.
|
|
197
|
+
if val.instance_of?(Array)
|
|
201
198
|
warn "AWS instance tags must be specified as a single hash, not a tag " \
|
|
202
199
|
"on each line. Example: {:foo => 'bar', :bar => 'foo'}"
|
|
203
200
|
exit!
|
|
@@ -247,13 +244,13 @@ module Kitchen
|
|
|
247
244
|
info("Auto placement on one dedicated host out of: #{hosts_with_capacity.map(&:host_id).join(", ")}")
|
|
248
245
|
end
|
|
249
246
|
|
|
250
|
-
if config[:spot_price]
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
247
|
+
server = if config[:spot_price]
|
|
248
|
+
# Spot instance when a price is set
|
|
249
|
+
with_request_limit_backoff(state) { submit_spots }
|
|
250
|
+
else
|
|
251
|
+
# On-demand instance
|
|
252
|
+
with_request_limit_backoff(state) { submit_server }
|
|
253
|
+
end
|
|
257
254
|
info("Instance <#{server.id}> requested.")
|
|
258
255
|
with_request_limit_backoff(state) do
|
|
259
256
|
logging_proc = ->(attempts) { info("Polling AWS for existence, attempt #{attempts}...") }
|
|
@@ -269,7 +266,7 @@ module Kitchen
|
|
|
269
266
|
tries: 10,
|
|
270
267
|
sleep: lambda { |n| [2**n, 30].min },
|
|
271
268
|
on: ::Aws::EC2::Errors::InvalidInstanceIDNotFound
|
|
272
|
-
) do |
|
|
269
|
+
) do |_r, _|
|
|
273
270
|
wait_until_ready(server, state)
|
|
274
271
|
end
|
|
275
272
|
|
|
@@ -320,10 +317,10 @@ module Kitchen
|
|
|
320
317
|
delete_key(state)
|
|
321
318
|
|
|
322
319
|
# Clean up dedicated hosts matching instance_type and unused (if allowed)
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
320
|
+
return unless config[:tenancy] == "host" && allow_deallocate_host?
|
|
321
|
+
|
|
322
|
+
empty_hosts = hosts_with_capacity.select { |host| host_unused?(host) }
|
|
323
|
+
empty_hosts.each { |host| deallocate_host(host.host_id) }
|
|
327
324
|
end
|
|
328
325
|
|
|
329
326
|
def image
|
|
@@ -427,7 +424,7 @@ module Kitchen
|
|
|
427
424
|
def expand_config(conf, key)
|
|
428
425
|
configs = []
|
|
429
426
|
|
|
430
|
-
if conf[key]
|
|
427
|
+
if conf[key].is_a?(Array)
|
|
431
428
|
values = conf[key]
|
|
432
429
|
values.each do |value|
|
|
433
430
|
new_config = conf.clone
|
|
@@ -499,11 +496,11 @@ module Kitchen
|
|
|
499
496
|
instance_data = instance_generator.ec2_instance_data
|
|
500
497
|
|
|
501
498
|
config_spot_price = config[:spot_price].to_s
|
|
502
|
-
if %w{ondemand on-demand}.include?(config_spot_price)
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
499
|
+
spot_price = if %w{ondemand on-demand}.include?(config_spot_price)
|
|
500
|
+
""
|
|
501
|
+
else
|
|
502
|
+
config_spot_price
|
|
503
|
+
end
|
|
507
504
|
spot_options = {
|
|
508
505
|
# Must use one-time in order to use instance_interruption_behavior=terminate
|
|
509
506
|
# spot_instance_type: "one-time", # default
|
|
@@ -519,7 +516,7 @@ module Kitchen
|
|
|
519
516
|
|
|
520
517
|
instance_data[:instance_market_options] = {
|
|
521
518
|
market_type: "spot",
|
|
522
|
-
spot_options
|
|
519
|
+
spot_options:,
|
|
523
520
|
}
|
|
524
521
|
|
|
525
522
|
# The preferred way to create a spot instance is via request_spot_instances()
|
|
@@ -551,7 +548,7 @@ module Kitchen
|
|
|
551
548
|
aws_instance.state.name == "running" &&
|
|
552
549
|
hostname != "0.0.0.0"
|
|
553
550
|
|
|
554
|
-
if ready && (
|
|
551
|
+
if ready && (hostname.nil? || hostname == "")
|
|
555
552
|
debug("Unable to detect hostname using interface_type #{config[:interface]}. Fallback to ordered mapping")
|
|
556
553
|
state[:hostname] = hostname(aws_instance, nil)
|
|
557
554
|
end
|
|
@@ -567,7 +564,7 @@ module Kitchen
|
|
|
567
564
|
output = Base64.decode64(output)
|
|
568
565
|
debug "Console output: --- \n#{output}"
|
|
569
566
|
end
|
|
570
|
-
ready = !!(output
|
|
567
|
+
ready = !!(output.include?("Windows is Ready to use"))
|
|
571
568
|
end
|
|
572
569
|
end
|
|
573
570
|
ready
|
|
@@ -600,7 +597,7 @@ module Kitchen
|
|
|
600
597
|
end
|
|
601
598
|
|
|
602
599
|
def fetch_windows_admin_password(server, state)
|
|
603
|
-
wait_with_destroy(server, state, "to fetch windows admin password") do |
|
|
600
|
+
wait_with_destroy(server, state, "to fetch windows admin password") do |_aws_instance|
|
|
604
601
|
enc = server.client.get_password_data(
|
|
605
602
|
instance_id: state[:server_id]
|
|
606
603
|
).password_data
|
|
@@ -655,7 +652,7 @@ module Kitchen
|
|
|
655
652
|
server.send(interface_type)
|
|
656
653
|
else
|
|
657
654
|
potential_hostname = nil
|
|
658
|
-
INTERFACE_TYPES.
|
|
655
|
+
INTERFACE_TYPES.each_value do |type|
|
|
659
656
|
potential_hostname ||= server.send(type)
|
|
660
657
|
# AWS returns an empty string if the dns name isn't populated yet
|
|
661
658
|
potential_hostname = nil if potential_hostname == ""
|
|
@@ -717,7 +714,7 @@ module Kitchen
|
|
|
717
714
|
|
|
718
715
|
# Preparing custom static admin user if we defined something other than Administrator
|
|
719
716
|
custom_admin_script = ""
|
|
720
|
-
if
|
|
717
|
+
if instance.transport[:username] !~ /administrator/i && instance.transport[:password]
|
|
721
718
|
custom_admin_script = Kitchen::Util.outdent!(<<-EOH)
|
|
722
719
|
"Disabling Complex Passwords" >> $logfile
|
|
723
720
|
$seccfg = [IO.Path]::GetTempFileName()
|
|
@@ -759,7 +756,7 @@ module Kitchen
|
|
|
759
756
|
def image_info(image)
|
|
760
757
|
root_device = image.block_device_mappings
|
|
761
758
|
.find { |b| b.device_name == image.root_device_name }
|
|
762
|
-
volume_type = " #{root_device.ebs.volume_type}" if root_device
|
|
759
|
+
volume_type = " #{root_device.ebs.volume_type}" if root_device&.ebs
|
|
763
760
|
|
|
764
761
|
" Architecture: #{image.architecture}," \
|
|
765
762
|
" Virtualization: #{image.virtualization_type}," \
|
|
@@ -813,6 +810,17 @@ module Kitchen
|
|
|
813
810
|
params = {
|
|
814
811
|
group_name: "kitchen-#{Array.new(8) { rand(36).to_s(36) }.join}",
|
|
815
812
|
description: "Test Kitchen for #{instance.name} by #{Etc.getlogin || "nologin"} on #{Socket.gethostname}",
|
|
813
|
+
tag_specifications: [
|
|
814
|
+
{
|
|
815
|
+
resource_type: "security-group",
|
|
816
|
+
tags: [
|
|
817
|
+
{
|
|
818
|
+
key: "created-by",
|
|
819
|
+
value: "test-kitchen",
|
|
820
|
+
},
|
|
821
|
+
],
|
|
822
|
+
},
|
|
823
|
+
],
|
|
816
824
|
}
|
|
817
825
|
params[:vpc_id] = vpc_id if vpc_id
|
|
818
826
|
resp = ec2.client.create_security_group(params)
|
|
@@ -829,7 +837,7 @@ module Kitchen
|
|
|
829
837
|
from_port: port,
|
|
830
838
|
to_port: port,
|
|
831
839
|
ip_ranges: Array(config[:security_group_cidr_ip]).map do |cidr_ip|
|
|
832
|
-
{ cidr_ip:
|
|
840
|
+
{ cidr_ip: }
|
|
833
841
|
end,
|
|
834
842
|
}
|
|
835
843
|
end
|
|
@@ -851,14 +859,28 @@ module Kitchen
|
|
|
851
859
|
(Etc.getlogin || "nologin").gsub(/\W/, ""),
|
|
852
860
|
Socket.gethostname.gsub(/\W/, "")[0..20],
|
|
853
861
|
Time.now.utc.iso8601,
|
|
854
|
-
Array.new(8) { rand(36).to_s(36) }.join
|
|
862
|
+
Array.new(8) { rand(36).to_s(36) }.join,
|
|
855
863
|
]
|
|
856
864
|
# In a perfect world this would generate the key locally and use ImportKey
|
|
857
865
|
# instead for better security, but given the use case that is very likely
|
|
858
866
|
# to rapidly exhaust local entropy by creating a lot of keys. So this is
|
|
859
867
|
# probably fine. If you want very high security, probably don't use this
|
|
860
868
|
# feature anyway.
|
|
861
|
-
resp = ec2.client.create_key_pair(
|
|
869
|
+
resp = ec2.client.create_key_pair(
|
|
870
|
+
key_name: "kitchen-#{name_parts.join("-")}",
|
|
871
|
+
key_type: config[:aws_ssh_key_type],
|
|
872
|
+
tag_specifications: [
|
|
873
|
+
{
|
|
874
|
+
resource_type: "key-pair",
|
|
875
|
+
tags: [
|
|
876
|
+
{
|
|
877
|
+
key: "created-by",
|
|
878
|
+
value: "test-kitchen",
|
|
879
|
+
},
|
|
880
|
+
],
|
|
881
|
+
},
|
|
882
|
+
]
|
|
883
|
+
)
|
|
862
884
|
state[:auto_key_id] = resp.key_name
|
|
863
885
|
info("Created automatic key pair #{state[:auto_key_id]}")
|
|
864
886
|
# Write the key out with safe permissions
|
|
@@ -892,7 +914,7 @@ module Kitchen
|
|
|
892
914
|
puts "ENI #{config[:elastic_network_interface_id]} already attached."
|
|
893
915
|
end
|
|
894
916
|
rescue ::Aws::EC2::Errors::InvalidNetworkInterfaceIDNotFound => e
|
|
895
|
-
warn(
|
|
917
|
+
warn(e.to_s)
|
|
896
918
|
end
|
|
897
919
|
end
|
|
898
920
|
|
|
@@ -922,7 +944,6 @@ module Kitchen
|
|
|
922
944
|
state.delete(:auto_key_id)
|
|
923
945
|
File.unlink("#{config[:kitchen_root]}/.kitchen/#{instance.name}.pem")
|
|
924
946
|
end
|
|
925
|
-
|
|
926
947
|
end
|
|
927
948
|
end
|
|
928
949
|
end
|
metadata
CHANGED
|
@@ -1,35 +1,15 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kitchen-ec2
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.17.
|
|
4
|
+
version: 3.17.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
-
|
|
7
|
+
- Test Kitchen Team
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-
|
|
11
|
+
date: 2023-11-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
|
-
- !ruby/object:Gem::Dependency
|
|
14
|
-
name: test-kitchen
|
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
|
16
|
-
requirements:
|
|
17
|
-
- - ">="
|
|
18
|
-
- !ruby/object:Gem::Version
|
|
19
|
-
version: 1.4.1
|
|
20
|
-
- - "<"
|
|
21
|
-
- !ruby/object:Gem::Version
|
|
22
|
-
version: '4'
|
|
23
|
-
type: :runtime
|
|
24
|
-
prerelease: false
|
|
25
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
26
|
-
requirements:
|
|
27
|
-
- - ">="
|
|
28
|
-
- !ruby/object:Gem::Version
|
|
29
|
-
version: 1.4.1
|
|
30
|
-
- - "<"
|
|
31
|
-
- !ruby/object:Gem::Version
|
|
32
|
-
version: '4'
|
|
33
13
|
- !ruby/object:Gem::Dependency
|
|
34
14
|
name: aws-sdk-ec2
|
|
35
15
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -64,9 +44,29 @@ dependencies:
|
|
|
64
44
|
- - "<"
|
|
65
45
|
- !ruby/object:Gem::Version
|
|
66
46
|
version: '4.0'
|
|
47
|
+
- !ruby/object:Gem::Dependency
|
|
48
|
+
name: test-kitchen
|
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: 1.4.1
|
|
54
|
+
- - "<"
|
|
55
|
+
- !ruby/object:Gem::Version
|
|
56
|
+
version: '4'
|
|
57
|
+
type: :runtime
|
|
58
|
+
prerelease: false
|
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
60
|
+
requirements:
|
|
61
|
+
- - ">="
|
|
62
|
+
- !ruby/object:Gem::Version
|
|
63
|
+
version: 1.4.1
|
|
64
|
+
- - "<"
|
|
65
|
+
- !ruby/object:Gem::Version
|
|
66
|
+
version: '4'
|
|
67
67
|
description: A Test Kitchen Driver for Amazon EC2
|
|
68
68
|
email:
|
|
69
|
-
-
|
|
69
|
+
- help@sous-chefs.org
|
|
70
70
|
executables: []
|
|
71
71
|
extensions: []
|
|
72
72
|
extra_rdoc_files: []
|
|
@@ -110,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
110
110
|
- !ruby/object:Gem::Version
|
|
111
111
|
version: '0'
|
|
112
112
|
requirements: []
|
|
113
|
-
rubygems_version: 3.4.
|
|
113
|
+
rubygems_version: 3.4.10
|
|
114
114
|
signing_key:
|
|
115
115
|
specification_version: 4
|
|
116
116
|
summary: A Test Kitchen Driver for Amazon EC2
|