kitchen-ec2 2.5.0 → 3.0.0.preview
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 +9 -9
- data/lib/kitchen/driver/aws/instance_generator.rb +25 -25
- data/lib/kitchen/driver/aws/standard_platform.rb +3 -3
- data/lib/kitchen/driver/aws/standard_platform/centos.rb +3 -3
- data/lib/kitchen/driver/aws/standard_platform/windows.rb +3 -3
- data/lib/kitchen/driver/ec2.rb +25 -29
- data/lib/kitchen/driver/ec2_version.rb +1 -1
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2778637095bcb2e87ba702a0c04c496debc70e9b0eb781e6581e079667875edd
|
4
|
+
data.tar.gz: 3215d5359bd928d6446bdce249e34940e1f3b1a86dfeadf06f8bf36c5b21a4de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 308bf0b88efe068274892048e443f5704c646080eaed86c0ae0ad1d75c511e87226f027b4fce86f4b7193459e3baafb26ccc9c884b5ec3961c55d0a1f3b7cf3c
|
7
|
+
data.tar.gz: b2e1c18a028972c97ca062eafe64c57b0f9334d07bb0f098d4c250117e4ea2a8b492ee18fdc5b4b23b64c8803015b85b9b7ba27e2cd13d4ae9cf93375611911f
|
@@ -17,7 +17,7 @@
|
|
17
17
|
# See the License for the specific language governing permissions and
|
18
18
|
# limitations under the License.
|
19
19
|
|
20
|
-
require "aws-sdk"
|
20
|
+
require "aws-sdk-ec2"
|
21
21
|
require "aws-sdk-core/credentials"
|
22
22
|
require "aws-sdk-core/shared_credentials"
|
23
23
|
require "aws-sdk-core/instance_profile_credentials"
|
@@ -41,12 +41,12 @@ module Kitchen
|
|
41
41
|
ssl_verify_peer = true
|
42
42
|
)
|
43
43
|
::Aws.config.update(
|
44
|
-
:
|
45
|
-
:
|
46
|
-
:
|
47
|
-
:
|
44
|
+
region: region,
|
45
|
+
profile: profile_name,
|
46
|
+
http_proxy: http_proxy,
|
47
|
+
ssl_verify_peer: ssl_verify_peer
|
48
48
|
)
|
49
|
-
::Aws.config.update(:
|
49
|
+
::Aws.config.update(retry_limit: retry_limit) unless retry_limit.nil?
|
50
50
|
end
|
51
51
|
|
52
52
|
def create_instance(options)
|
@@ -59,9 +59,9 @@ module Kitchen
|
|
59
59
|
|
60
60
|
def get_instance_from_spot_request(request_id)
|
61
61
|
resource.instances(
|
62
|
-
:
|
63
|
-
:
|
64
|
-
:
|
62
|
+
filters: [{
|
63
|
+
name: "spot-instance-request-id",
|
64
|
+
values: [request_id],
|
65
65
|
}]
|
66
66
|
).to_a[0]
|
67
67
|
end
|
@@ -18,7 +18,7 @@
|
|
18
18
|
# limitations under the License.
|
19
19
|
|
20
20
|
require "base64"
|
21
|
-
require "aws-sdk"
|
21
|
+
require "aws-sdk-ec2"
|
22
22
|
|
23
23
|
module Kitchen
|
24
24
|
|
@@ -45,12 +45,12 @@ module Kitchen
|
|
45
45
|
# Support for looking up security group id and subnet id using tags.
|
46
46
|
|
47
47
|
if config[:subnet_id].nil? && config[:subnet_filter]
|
48
|
-
config[:subnet_id] = ::Aws::EC2::Client
|
49
|
-
new(:
|
50
|
-
:
|
48
|
+
config[:subnet_id] = ::Aws::EC2::Client
|
49
|
+
.new(region: config[:region]).describe_subnets(
|
50
|
+
filters: [
|
51
51
|
{
|
52
|
-
:
|
53
|
-
:
|
52
|
+
name: "tag:#{config[:subnet_filter][:tag]}",
|
53
|
+
values: [config[:subnet_filter][:value]],
|
54
54
|
},
|
55
55
|
]
|
56
56
|
)[0][0].subnet_id
|
@@ -62,12 +62,12 @@ module Kitchen
|
|
62
62
|
end
|
63
63
|
|
64
64
|
if config[:security_group_ids].nil? && config[:security_group_filter]
|
65
|
-
security_group = ::Aws::EC2::Client
|
66
|
-
new(:
|
67
|
-
:
|
65
|
+
security_group = ::Aws::EC2::Client
|
66
|
+
.new(region: config[:region]).describe_security_groups(
|
67
|
+
filters: [
|
68
68
|
{
|
69
|
-
:
|
70
|
-
:
|
69
|
+
name: "tag:#{config[:security_group_filter][:tag]}",
|
70
|
+
values: [config[:security_group_filter][:value]],
|
71
71
|
},
|
72
72
|
]
|
73
73
|
)[0][0]
|
@@ -81,12 +81,12 @@ module Kitchen
|
|
81
81
|
end
|
82
82
|
|
83
83
|
i = {
|
84
|
-
:
|
85
|
-
:
|
86
|
-
:
|
87
|
-
:
|
88
|
-
:
|
89
|
-
:
|
84
|
+
instance_type: config[:instance_type],
|
85
|
+
ebs_optimized: config[:ebs_optimized],
|
86
|
+
image_id: config[:image_id],
|
87
|
+
key_name: config[:aws_ssh_key_id],
|
88
|
+
subnet_id: config[:subnet_id],
|
89
|
+
private_ip_address: config[:private_ip_address],
|
90
90
|
}
|
91
91
|
|
92
92
|
availability_zone = config[:availability_zone]
|
@@ -94,14 +94,14 @@ module Kitchen
|
|
94
94
|
if availability_zone =~ /^[a-z]$/i
|
95
95
|
availability_zone = "#{config[:region]}#{availability_zone}"
|
96
96
|
end
|
97
|
-
i[:placement] = { :
|
97
|
+
i[:placement] = { availability_zone: availability_zone.downcase }
|
98
98
|
end
|
99
99
|
tenancy = config[:tenancy]
|
100
100
|
if tenancy
|
101
101
|
if i.key?(:placement)
|
102
102
|
i[:placement][:tenancy] = tenancy
|
103
103
|
else
|
104
|
-
i[:placement] = { :
|
104
|
+
i[:placement] = { tenancy: tenancy }
|
105
105
|
end
|
106
106
|
end
|
107
107
|
unless config[:block_device_mappings].nil? || config[:block_device_mappings].empty?
|
@@ -110,14 +110,14 @@ module Kitchen
|
|
110
110
|
i[:security_group_ids] = Array(config[:security_group_ids]) if config[:security_group_ids]
|
111
111
|
i[:user_data] = prepared_user_data if prepared_user_data
|
112
112
|
if config[:iam_profile_name]
|
113
|
-
i[:iam_instance_profile] = { :
|
113
|
+
i[:iam_instance_profile] = { name: config[:iam_profile_name] }
|
114
114
|
end
|
115
115
|
if !config.fetch(:associate_public_ip, nil).nil?
|
116
116
|
i[:network_interfaces] =
|
117
117
|
[{
|
118
|
-
:
|
119
|
-
:
|
120
|
-
:
|
118
|
+
device_index: 0,
|
119
|
+
associate_public_ip_address: config[:associate_public_ip],
|
120
|
+
delete_on_termination: true,
|
121
121
|
}]
|
122
122
|
# If specifying `:network_interfaces` in the request, you must specify
|
123
123
|
# network specific configs in the network_interfaces block and not at
|
@@ -137,14 +137,14 @@ module Kitchen
|
|
137
137
|
if availability_zone =~ /^[a-z]$/i
|
138
138
|
availability_zone = "#{config[:region]}#{availability_zone}"
|
139
139
|
end
|
140
|
-
i[:placement] = { :
|
140
|
+
i[:placement] = { availability_zone: availability_zone.downcase }
|
141
141
|
end
|
142
142
|
tenancy = config[:tenancy]
|
143
143
|
if tenancy
|
144
144
|
if i.key?(:placement)
|
145
145
|
i[:placement][:tenancy] = tenancy
|
146
146
|
else
|
147
|
-
i[:placement] = { :
|
147
|
+
i[:placement] = { tenancy: tenancy }
|
148
148
|
end
|
149
149
|
end
|
150
150
|
unless config[:instance_initiated_shutdown_behavior].nil? ||
|
@@ -88,7 +88,7 @@ module Kitchen
|
|
88
88
|
#
|
89
89
|
# The list of supported architectures
|
90
90
|
#
|
91
|
-
SUPPORTED_ARCHITECTURES = %w{x86_64 i386 arm64}
|
91
|
+
SUPPORTED_ARCHITECTURES = %w{x86_64 i386 arm64}.freeze
|
92
92
|
|
93
93
|
#
|
94
94
|
# Find the best matching image for the given image search.
|
@@ -98,11 +98,11 @@ module Kitchen
|
|
98
98
|
driver.debug("Searching for images matching #{image_search} ...")
|
99
99
|
# Convert to ec2 search format (pairs of name+values)
|
100
100
|
filters = image_search.map do |key, value|
|
101
|
-
{ :
|
101
|
+
{ name: key.to_s, values: Array(value).map(&:to_s) }
|
102
102
|
end
|
103
103
|
|
104
104
|
# We prefer most recent first
|
105
|
-
images = driver.ec2.resource.images(:
|
105
|
+
images = driver.ec2.resource.images(filters: filters)
|
106
106
|
images = sort_images(images)
|
107
107
|
show_returned_images(images)
|
108
108
|
|
@@ -43,9 +43,9 @@ module Kitchen
|
|
43
43
|
# 7.1 -> [ img1, img2, img3 ]
|
44
44
|
# 6 -> [ img4, img5 ]
|
45
45
|
# ...
|
46
|
-
images.group_by { |image| self.class.from_image(driver, image).version }
|
47
|
-
sort_by { |k, _v| (k && k.include?(".") ? k.to_f : "#{k}.999".to_f) }
|
48
|
-
reverse.flat_map { |_k, v| v }
|
46
|
+
images.group_by { |image| self.class.from_image(driver, image).version }
|
47
|
+
.sort_by { |k, _v| (k && k.include?(".") ? k.to_f : "#{k}.999".to_f) }
|
48
|
+
.reverse.flat_map { |_k, v| v }
|
49
49
|
end
|
50
50
|
|
51
51
|
def self.from_image(driver, image)
|
@@ -60,9 +60,9 @@ module Kitchen
|
|
60
60
|
# 2008r2rtm -> [ img1, img2, img3 ]
|
61
61
|
# 2012r2sp1 -> [ img4, img5 ]
|
62
62
|
# ...
|
63
|
-
images.group_by { |image| self.class.from_image(driver, image).windows_version_parts }
|
64
|
-
sort_by { |version, _platform_images| version }
|
65
|
-
reverse.flat_map { |_version, platform_images| platform_images }
|
63
|
+
images.group_by { |image| self.class.from_image(driver, image).windows_version_parts }
|
64
|
+
.sort_by { |version, _platform_images| version }
|
65
|
+
.reverse.flat_map { |_version, platform_images| platform_images }
|
66
66
|
end
|
67
67
|
|
68
68
|
def self.from_image(driver, image)
|
data/lib/kitchen/driver/ec2.rb
CHANGED
@@ -33,14 +33,13 @@ require_relative "aws/standard_platform/fedora"
|
|
33
33
|
require_relative "aws/standard_platform/freebsd"
|
34
34
|
require_relative "aws/standard_platform/ubuntu"
|
35
35
|
require_relative "aws/standard_platform/windows"
|
36
|
+
require "aws-sdk-ec2"
|
36
37
|
require "aws-sdk-core/waiters/errors"
|
37
38
|
require "retryable"
|
38
39
|
require "time"
|
39
40
|
require "etc"
|
40
41
|
require "socket"
|
41
42
|
|
42
|
-
Aws.eager_autoload!
|
43
|
-
|
44
43
|
module Kitchen
|
45
44
|
|
46
45
|
module Driver
|
@@ -55,7 +54,7 @@ module Kitchen
|
|
55
54
|
plugin_version Kitchen::Driver::EC2_VERSION
|
56
55
|
|
57
56
|
default_config :region, ENV["AWS_REGION"] || "us-east-1"
|
58
|
-
default_config :shared_credentials_profile,
|
57
|
+
default_config :shared_credentials_profile, ENV["AWS_PROFILE"]
|
59
58
|
default_config :availability_zone, nil
|
60
59
|
default_config :instance_type do |driver|
|
61
60
|
driver.default_instance_type
|
@@ -96,9 +95,6 @@ module Kitchen
|
|
96
95
|
|
97
96
|
def initialize(*args, &block)
|
98
97
|
super
|
99
|
-
# AWS Ruby SDK loading isn't thread safe, so as soon as we know we're
|
100
|
-
# going to use EC2, autoload it. Seems to have been fixed in Ruby 2.3+
|
101
|
-
::Aws.eager_autoload! unless RUBY_VERSION.to_f >= 2.3
|
102
98
|
end
|
103
99
|
|
104
100
|
def self.validation_warn(driver, old_key, new_key)
|
@@ -252,15 +248,15 @@ module Kitchen
|
|
252
248
|
# Tagging an instance is possible before volumes are attached. Tagging the volumes after
|
253
249
|
# instance creation is consistent.
|
254
250
|
Retryable.retryable(
|
255
|
-
:
|
256
|
-
:
|
257
|
-
:
|
251
|
+
tries: 10,
|
252
|
+
sleep: lambda { |n| [2**n, 30].min },
|
253
|
+
on: ::Aws::EC2::Errors::InvalidInstanceIDNotFound
|
258
254
|
) do |r, _|
|
259
255
|
info("Attempting to tag the instance, #{r} retries")
|
260
256
|
tag_server(server)
|
261
257
|
|
262
258
|
# Get information about the AMI (image) used to create the image.
|
263
|
-
image_data = ec2.client.describe_images({ :
|
259
|
+
image_data = ec2.client.describe_images({ image_ids: [server.image_id] })[0][0]
|
264
260
|
|
265
261
|
state[:server_id] = server.id
|
266
262
|
info("EC2 instance <#{state[:server_id]}> created.")
|
@@ -303,7 +299,7 @@ module Kitchen
|
|
303
299
|
if state[:spot_request_id]
|
304
300
|
debug("Deleting spot request <#{state[:server_id]}>")
|
305
301
|
ec2.client.cancel_spot_instance_requests(
|
306
|
-
:
|
302
|
+
spot_instance_request_ids: [state[:spot_request_id]]
|
307
303
|
)
|
308
304
|
state.delete(:spot_request_id)
|
309
305
|
end
|
@@ -433,7 +429,7 @@ module Kitchen
|
|
433
429
|
state[:spot_request_id] = spot_request_id
|
434
430
|
ec2.client.wait_until(
|
435
431
|
:spot_instance_request_fulfilled,
|
436
|
-
:
|
432
|
+
spot_instance_request_ids: [spot_request_id]
|
437
433
|
) do |w|
|
438
434
|
w.max_attempts = config[:retryable_tries]
|
439
435
|
w.delay = config[:retryable_sleep]
|
@@ -449,9 +445,9 @@ module Kitchen
|
|
449
445
|
def create_spot_request
|
450
446
|
request_duration = config[:retryable_tries] * config[:retryable_sleep]
|
451
447
|
request_data = {
|
452
|
-
:
|
453
|
-
:
|
454
|
-
:
|
448
|
+
spot_price: config[:spot_price].to_s,
|
449
|
+
launch_specification: instance_generator.ec2_instance_data,
|
450
|
+
valid_until: Time.now + request_duration,
|
455
451
|
}
|
456
452
|
if config[:block_duration_minutes]
|
457
453
|
request_data[:block_duration_minutes] = config[:block_duration_minutes]
|
@@ -467,19 +463,19 @@ module Kitchen
|
|
467
463
|
# we convert the value to a string because
|
468
464
|
# nils should be passed as an empty String
|
469
465
|
# and Integers need to be represented as Strings
|
470
|
-
{ :
|
466
|
+
{ key: k, value: v.to_s }
|
471
467
|
end
|
472
|
-
server.create_tags(:
|
468
|
+
server.create_tags(tags: tags)
|
473
469
|
end
|
474
470
|
end
|
475
471
|
|
476
472
|
def tag_volumes(server)
|
477
473
|
if config[:tags] && !config[:tags].empty?
|
478
474
|
tags = config[:tags].map do |k, v|
|
479
|
-
{ :
|
475
|
+
{ key: k, value: v.to_s }
|
480
476
|
end
|
481
477
|
server.volumes.each do |volume|
|
482
|
-
volume.create_tags(:
|
478
|
+
volume.create_tags(tags: tags)
|
483
479
|
end
|
484
480
|
end
|
485
481
|
end
|
@@ -493,8 +489,8 @@ module Kitchen
|
|
493
489
|
described_volume_count = 0
|
494
490
|
ready_volume_count = 0
|
495
491
|
if aws_instance.exists?
|
496
|
-
described_volume_count = ec2.client.describe_volumes(:
|
497
|
-
{ :
|
492
|
+
described_volume_count = ec2.client.describe_volumes(filters: [
|
493
|
+
{ name: "attachment.instance-id", values: ["#{state[:server_id]}"] }]
|
498
494
|
).volumes.length
|
499
495
|
aws_instance.volumes.each { ready_volume_count += 1 }
|
500
496
|
end
|
@@ -542,9 +538,9 @@ module Kitchen
|
|
542
538
|
begin
|
543
539
|
with_request_limit_backoff(state) do
|
544
540
|
server.wait_until(
|
545
|
-
:
|
546
|
-
:
|
547
|
-
:
|
541
|
+
max_attempts: config[:retryable_tries],
|
542
|
+
delay: config[:retryable_sleep],
|
543
|
+
before_attempt: wait_log,
|
548
544
|
&block
|
549
545
|
)
|
550
546
|
end
|
@@ -559,7 +555,7 @@ module Kitchen
|
|
559
555
|
def fetch_windows_admin_password(server, state)
|
560
556
|
wait_with_destroy(server, state, "to fetch windows admin password") do |aws_instance|
|
561
557
|
enc = server.client.get_password_data(
|
562
|
-
:
|
558
|
+
instance_id: state[:server_id]
|
563
559
|
).password_data
|
564
560
|
# Password data is blank until password is available
|
565
561
|
!enc.nil? && !enc.empty?
|
@@ -595,7 +591,7 @@ module Kitchen
|
|
595
591
|
"public" => "public_ip_address",
|
596
592
|
"private" => "private_ip_address",
|
597
593
|
"private_dns" => "private_dns_name",
|
598
|
-
}
|
594
|
+
}.freeze
|
599
595
|
|
600
596
|
#
|
601
597
|
# Lookup hostname of provided server. If interface_type is provided use
|
@@ -668,7 +664,7 @@ module Kitchen
|
|
668
664
|
#Firewall Config
|
669
665
|
& netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" profile=public protocol=tcp localport=5985 remoteip=localsubnet new remoteip=any >> $logfile
|
670
666
|
Set-ItemProperty -Name LocalAccountTokenFilterPolicy -Path HKLM:\\software\\Microsoft\\Windows\\CurrentVersion\\Policies\\system -Value 1
|
671
|
-
|
667
|
+
EOH
|
672
668
|
|
673
669
|
# Preparing custom static admin user if we defined something other than Administrator
|
674
670
|
custom_admin_script = ""
|
@@ -712,8 +708,8 @@ module Kitchen
|
|
712
708
|
end
|
713
709
|
|
714
710
|
def image_info(image)
|
715
|
-
root_device = image.block_device_mappings
|
716
|
-
find { |b| b.device_name == image.root_device_name }
|
711
|
+
root_device = image.block_device_mappings
|
712
|
+
.find { |b| b.device_name == image.root_device_name }
|
717
713
|
volume_type = " #{root_device.ebs.volume_type}" if root_device && root_device.ebs
|
718
714
|
|
719
715
|
" Architecture: #{image.architecture}," \
|
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:
|
4
|
+
version: 3.0.0.preview
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fletcher Nichol
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-04-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: test-kitchen
|
@@ -59,19 +59,19 @@ dependencies:
|
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: '0'
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
|
-
name: aws-sdk
|
62
|
+
name: aws-sdk-ec2
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
64
64
|
requirements:
|
65
65
|
- - "~>"
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version: '
|
67
|
+
version: '1.0'
|
68
68
|
type: :runtime
|
69
69
|
prerelease: false
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
72
|
- - "~>"
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: '
|
74
|
+
version: '1.0'
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
76
|
name: retryable
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -218,12 +218,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
218
218
|
requirements:
|
219
219
|
- - ">="
|
220
220
|
- !ruby/object:Gem::Version
|
221
|
-
version: 2.
|
221
|
+
version: '2.3'
|
222
222
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
223
223
|
requirements:
|
224
|
-
- - "
|
224
|
+
- - ">"
|
225
225
|
- !ruby/object:Gem::Version
|
226
|
-
version:
|
226
|
+
version: 1.3.1
|
227
227
|
requirements: []
|
228
228
|
rubygems_version: 3.0.3
|
229
229
|
signing_key:
|