test-kitchen 3.1.0 → 3.6.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/Gemfile +15 -10
- data/lib/kitchen/cli.rb +1 -1
- data/lib/kitchen/command/diagnose.rb +1 -1
- data/lib/kitchen/config.rb +8 -8
- data/lib/kitchen/configurable.rb +1 -1
- data/lib/kitchen/driver/ssh_base.rb +2 -2
- data/lib/kitchen/errors.rb +13 -0
- data/lib/kitchen/lifecycle_hook/base.rb +6 -4
- data/lib/kitchen/lifecycle_hook/local.rb +1 -1
- data/lib/kitchen/lifecycle_hooks.rb +3 -1
- data/lib/kitchen/loader/yaml.rb +1 -8
- data/lib/kitchen/platform.rb +1 -1
- data/lib/kitchen/platform_filter.rb +72 -0
- data/lib/kitchen/plugin_base.rb +0 -1
- data/lib/kitchen/provisioner/base.rb +7 -1
- data/lib/kitchen/provisioner/chef/common_sandbox.rb +8 -6
- data/lib/kitchen/provisioner/chef/policyfile.rb +11 -7
- data/lib/kitchen/provisioner/chef_base.rb +36 -19
- data/lib/kitchen/provisioner/shell.rb +0 -1
- data/lib/kitchen/ssh.rb +10 -3
- data/lib/kitchen/suite.rb +4 -2
- data/lib/kitchen/transport/base.rb +10 -6
- data/lib/kitchen/transport/ssh.rb +24 -11
- data/lib/kitchen/transport/winrm.rb +33 -9
- data/lib/kitchen/util.rb +13 -0
- data/lib/kitchen/verifier/base.rb +16 -7
- data/lib/kitchen/version.rb +1 -1
- data/lib/kitchen.rb +1 -1
- data/templates/driver/README.md.erb +2 -2
- data/test-kitchen.gemspec +7 -19
- metadata +63 -220
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
# limitations under the License.
|
|
17
17
|
|
|
18
18
|
require_relative "../../kitchen"
|
|
19
|
+
require_relative "../util"
|
|
19
20
|
|
|
20
21
|
require "fileutils" unless defined?(FileUtils)
|
|
21
22
|
require "net/ssh" unless defined?(Net::SSH)
|
|
@@ -102,7 +103,9 @@ module Kitchen
|
|
|
102
103
|
# (see Base#cleanup!)
|
|
103
104
|
def cleanup!
|
|
104
105
|
if @connection
|
|
105
|
-
|
|
106
|
+
string_to_mask = "[SSH] shutting previous connection #{@connection}"
|
|
107
|
+
masked_string = Util.mask_values(string_to_mask, %w{password ssh_http_proxy_password})
|
|
108
|
+
logger.debug(masked_string)
|
|
106
109
|
@connection.close
|
|
107
110
|
@connection = @connection_options = nil
|
|
108
111
|
end
|
|
@@ -125,7 +128,9 @@ module Kitchen
|
|
|
125
128
|
def close
|
|
126
129
|
return if @session.nil?
|
|
127
130
|
|
|
128
|
-
|
|
131
|
+
string_to_mask = "[SSH] closing connection to #{self}"
|
|
132
|
+
masked_string = Util.mask_values(string_to_mask, %w{password ssh_http_proxy_password})
|
|
133
|
+
logger.debug(masked_string)
|
|
129
134
|
session.close
|
|
130
135
|
ensure
|
|
131
136
|
@session = nil
|
|
@@ -135,7 +140,9 @@ module Kitchen
|
|
|
135
140
|
def execute(command)
|
|
136
141
|
return if command.nil?
|
|
137
142
|
|
|
138
|
-
|
|
143
|
+
string_to_mask = "[SSH] #{self} (#{command})"
|
|
144
|
+
masked_string = Util.mask_values(string_to_mask, %w{password ssh_http_proxy_password})
|
|
145
|
+
logger.debug(masked_string)
|
|
139
146
|
exit_code = execute_with_exit_code(command)
|
|
140
147
|
|
|
141
148
|
if exit_code != 0
|
|
@@ -176,9 +183,11 @@ module Kitchen
|
|
|
176
183
|
Array(locals).map do |local|
|
|
177
184
|
opts = File.directory?(local) ? { recursive: true } : {}
|
|
178
185
|
|
|
179
|
-
waits.push
|
|
180
|
-
|
|
181
|
-
|
|
186
|
+
waits.push(
|
|
187
|
+
session.scp.upload(local, remote, opts) do |_ch, name, sent, total|
|
|
188
|
+
logger.debug("Async Uploaded #{name} (#{total} bytes)") if sent == total
|
|
189
|
+
end
|
|
190
|
+
)
|
|
182
191
|
waits.shift.wait while waits.length >= max_ssh_sessions
|
|
183
192
|
end
|
|
184
193
|
waits.each(&:wait)
|
|
@@ -216,7 +225,7 @@ module Kitchen
|
|
|
216
225
|
delay = 3
|
|
217
226
|
session(
|
|
218
227
|
retries: max_wait_until_ready / delay,
|
|
219
|
-
delay
|
|
228
|
+
delay:,
|
|
220
229
|
message: "Waiting for SSH service on #{hostname}:#{port}, " \
|
|
221
230
|
"retrying in #{delay} seconds"
|
|
222
231
|
)
|
|
@@ -350,7 +359,9 @@ module Kitchen
|
|
|
350
359
|
def retry_connection(opts)
|
|
351
360
|
log_msg = "[SSH] opening connection to #{self}"
|
|
352
361
|
log_msg += " via #{ssh_gateway_username}@#{ssh_gateway}:#{ssh_gateway_port}" if ssh_gateway
|
|
353
|
-
|
|
362
|
+
masked_string = Util.mask_values(log_msg, %w{password ssh_http_proxy_password})
|
|
363
|
+
|
|
364
|
+
logger.debug(masked_string)
|
|
354
365
|
yield
|
|
355
366
|
rescue *RESCUE_EXCEPTIONS_ON_ESTABLISH => e
|
|
356
367
|
if (opts[:retries] -= 1) > 0
|
|
@@ -457,7 +468,7 @@ module Kitchen
|
|
|
457
468
|
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
|
458
469
|
def connection_options(data)
|
|
459
470
|
opts = {
|
|
460
|
-
logger
|
|
471
|
+
logger:,
|
|
461
472
|
user_known_hosts_file: "/dev/null",
|
|
462
473
|
hostname: data[:hostname],
|
|
463
474
|
port: data[:port],
|
|
@@ -539,7 +550,7 @@ module Kitchen
|
|
|
539
550
|
# Creates a new SSH Connection instance and save it for potential future
|
|
540
551
|
# reuse.
|
|
541
552
|
#
|
|
542
|
-
# @param options [Hash]
|
|
553
|
+
# @param options [Hash] connection options
|
|
543
554
|
# @return [Ssh::Connection] an SSH Connection instance
|
|
544
555
|
# @api private
|
|
545
556
|
def create_new_connection(options, &block)
|
|
@@ -553,7 +564,9 @@ module Kitchen
|
|
|
553
564
|
# @return [Ssh::Connection] an SSH Connection instance
|
|
554
565
|
# @api private
|
|
555
566
|
def reuse_connection
|
|
556
|
-
|
|
567
|
+
string_to_mask = "[SSH] reusing existing connection #{@connection}"
|
|
568
|
+
masked_string = Util.mask_values(string_to_mask, %w{password ssh_http_proxy_password})
|
|
569
|
+
logger.debug(masked_string)
|
|
557
570
|
yield @connection if block_given?
|
|
558
571
|
@connection
|
|
559
572
|
end
|
|
@@ -20,7 +20,9 @@
|
|
|
20
20
|
require "rbconfig" unless defined?(RbConfig)
|
|
21
21
|
require "uri" unless defined?(URI)
|
|
22
22
|
require_relative "../../kitchen"
|
|
23
|
+
require_relative "../util"
|
|
23
24
|
require "winrm" unless defined?(WinRM::Connection)
|
|
25
|
+
require "winrm/exceptions" unless defined?(WinRM::WinRMHTTPTransportError)
|
|
24
26
|
|
|
25
27
|
module Kitchen
|
|
26
28
|
module Transport
|
|
@@ -103,7 +105,9 @@ module Kitchen
|
|
|
103
105
|
def execute(command)
|
|
104
106
|
return if command.nil?
|
|
105
107
|
|
|
106
|
-
|
|
108
|
+
string_to_mask = "[WinRM] #{self} (#{command})"
|
|
109
|
+
masked_string = Util.mask_values(string_to_mask, %w{password ssh_http_proxy_password})
|
|
110
|
+
logger.debug(masked_string)
|
|
107
111
|
|
|
108
112
|
exit_code, stderr = execute_with_exit_code(command)
|
|
109
113
|
|
|
@@ -118,6 +122,22 @@ module Kitchen
|
|
|
118
122
|
end
|
|
119
123
|
end
|
|
120
124
|
|
|
125
|
+
def retry?(current_try, max_retries, retryable_exit_codes, exception)
|
|
126
|
+
# Avoid duplicating Kitchen::Transport::Base#retry?
|
|
127
|
+
result = super
|
|
128
|
+
return result if result == true
|
|
129
|
+
|
|
130
|
+
case exception
|
|
131
|
+
when WinRM::WinRMHTTPTransportError
|
|
132
|
+
return current_try <= max_retries &&
|
|
133
|
+
[400, 500].include?(exception.status_code)
|
|
134
|
+
when WinRM::WinRMWSManFault
|
|
135
|
+
return current_try <= max_retries
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
false
|
|
139
|
+
end
|
|
140
|
+
|
|
121
141
|
# (see Base::Connection#login_command)
|
|
122
142
|
def login_command
|
|
123
143
|
case RbConfig::CONFIG["host_os"]
|
|
@@ -238,10 +258,10 @@ module Kitchen
|
|
|
238
258
|
end
|
|
239
259
|
end
|
|
240
260
|
|
|
241
|
-
# Execute a
|
|
261
|
+
# Execute a PowerShell script over WinRM and return the command's
|
|
242
262
|
# exit code and standard error.
|
|
243
263
|
#
|
|
244
|
-
# @param command [String]
|
|
264
|
+
# @param command [String] PowerShell script to execute
|
|
245
265
|
# @return [[Integer,String]] an array containing the exit code of the
|
|
246
266
|
# script and the standard error stream
|
|
247
267
|
# @api private
|
|
@@ -424,8 +444,8 @@ module Kitchen
|
|
|
424
444
|
opts = {
|
|
425
445
|
instance_name: instance.name,
|
|
426
446
|
kitchen_root: data[:kitchen_root],
|
|
427
|
-
logger
|
|
428
|
-
endpoint
|
|
447
|
+
logger:,
|
|
448
|
+
endpoint:,
|
|
429
449
|
user: data[:username],
|
|
430
450
|
password: data[:password],
|
|
431
451
|
rdp_port: data[:rdp_port],
|
|
@@ -437,7 +457,7 @@ module Kitchen
|
|
|
437
457
|
transport: data[:winrm_transport],
|
|
438
458
|
elevated: data[:elevated],
|
|
439
459
|
elevated_username: data[:elevated_username] || data[:username],
|
|
440
|
-
elevated_password
|
|
460
|
+
elevated_password:,
|
|
441
461
|
}
|
|
442
462
|
opts.merge!(additional_transport_args(data, opts[:transport]))
|
|
443
463
|
if opts[:transport].to_sym == :ssl && opts.key?(:client_cert) && opts.key?(:client_key)
|
|
@@ -477,12 +497,14 @@ module Kitchen
|
|
|
477
497
|
# Creates a new WinRM Connection instance and save it for potential
|
|
478
498
|
# future reuse.
|
|
479
499
|
#
|
|
480
|
-
# @param options [Hash]
|
|
500
|
+
# @param options [Hash] connection options
|
|
481
501
|
# @return [Ssh::Connection] a WinRM Connection instance
|
|
482
502
|
# @api private
|
|
483
503
|
def create_new_connection(options, &block)
|
|
484
504
|
if @connection
|
|
485
|
-
|
|
505
|
+
string_to_mask = "[WinRM] shutting previous connection #{@connection}"
|
|
506
|
+
masked_string = Util.mask_values(string_to_mask, %w{password ssh_http_proxy_password})
|
|
507
|
+
logger.debug(masked_string)
|
|
486
508
|
@connection.close
|
|
487
509
|
end
|
|
488
510
|
|
|
@@ -542,7 +564,9 @@ module Kitchen
|
|
|
542
564
|
# @return [Winrm::Connection] a WinRM Connection instance
|
|
543
565
|
# @api private
|
|
544
566
|
def reuse_connection
|
|
545
|
-
|
|
567
|
+
string_to_mask = "[WinRM] reusing existing connection #{@connection}"
|
|
568
|
+
masked_string = Util.mask_values(string_to_mask, %w{password ssh_http_proxy_password})
|
|
569
|
+
logger.debug(masked_string)
|
|
546
570
|
yield @connection if block_given?
|
|
547
571
|
@connection
|
|
548
572
|
end
|
data/lib/kitchen/util.rb
CHANGED
|
@@ -88,6 +88,19 @@ module Kitchen
|
|
|
88
88
|
end
|
|
89
89
|
end
|
|
90
90
|
|
|
91
|
+
# Returns a string with masked values for specified parameters.
|
|
92
|
+
#
|
|
93
|
+
# @param string_to_mask [String] the object whose string representation is parsed
|
|
94
|
+
# @param [Array] the list of keys whose values should be masked
|
|
95
|
+
# @return [String] the string representation of passed object with masked values
|
|
96
|
+
def self.mask_values(string_to_mask, keys)
|
|
97
|
+
masked_string = string_to_mask
|
|
98
|
+
keys.each do |key|
|
|
99
|
+
masked_string.gsub!(/:#{key}=>"([^"]*)"/, %{:#{key}=>"******"})
|
|
100
|
+
end
|
|
101
|
+
masked_string
|
|
102
|
+
end
|
|
103
|
+
|
|
91
104
|
# Returns a formatted string representing a duration in seconds.
|
|
92
105
|
#
|
|
93
106
|
# @param total [Integer] the total number of seconds
|
|
@@ -65,7 +65,6 @@ module Kitchen
|
|
|
65
65
|
# @raise [ActionFailed] if the action could not be completed
|
|
66
66
|
def call(state)
|
|
67
67
|
create_sandbox
|
|
68
|
-
sandbox_dirs = Util.list_directory(sandbox_path)
|
|
69
68
|
|
|
70
69
|
instance.transport.connection(state) do |conn|
|
|
71
70
|
conn.execute(install_command)
|
|
@@ -74,14 +73,17 @@ module Kitchen
|
|
|
74
73
|
conn.upload(sandbox_dirs, config[:root_path])
|
|
75
74
|
debug("Transfer complete")
|
|
76
75
|
conn.execute(prepare_command)
|
|
77
|
-
conn.execute(run_command)
|
|
78
76
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
77
|
+
begin
|
|
78
|
+
conn.execute(run_command)
|
|
79
|
+
ensure
|
|
80
|
+
info("Downloading files from #{instance.to_str}")
|
|
81
|
+
config[:downloads].to_h.each do |remotes, local|
|
|
82
|
+
debug("Downloading #{Array(remotes).join(", ")} to #{local}")
|
|
83
|
+
conn.download(remotes, local)
|
|
84
|
+
end
|
|
85
|
+
debug("Download complete")
|
|
83
86
|
end
|
|
84
|
-
debug("Download complete")
|
|
85
87
|
end
|
|
86
88
|
rescue Kitchen::Transport::TransportFailed => ex
|
|
87
89
|
raise ActionFailed, ex.message
|
|
@@ -174,6 +176,13 @@ module Kitchen
|
|
|
174
176
|
"trying to access the path."
|
|
175
177
|
end
|
|
176
178
|
|
|
179
|
+
# Returns the list of items in the sandbox directory
|
|
180
|
+
#
|
|
181
|
+
# @return [String] the absolute path of sandbox directory files
|
|
182
|
+
def sandbox_dirs
|
|
183
|
+
Util.list_directory(sandbox_path)
|
|
184
|
+
end
|
|
185
|
+
|
|
177
186
|
# Sets the API version for this verifier. If the verifier does not set
|
|
178
187
|
# this value, then `nil` will be used and reported.
|
|
179
188
|
#
|
data/lib/kitchen/version.rb
CHANGED
data/lib/kitchen.rb
CHANGED
|
@@ -58,7 +58,7 @@ Created and maintained by [<%= config[:author] %>][author] (<<%= config[:email]
|
|
|
58
58
|
|
|
59
59
|
[author]: https://github.com/enter-github-user
|
|
60
60
|
[issues]: https://github.com/enter-github-user/<%= config[:gem_name] %>/issues
|
|
61
|
-
[license]: https://github.com/enter-github-user/<%= config[:gem_name] %>/blob/
|
|
61
|
+
[license]: https://github.com/enter-github-user/<%= config[:gem_name] %>/blob/main/LICENSE
|
|
62
62
|
[repo]: https://github.com/enter-github-user/<%= config[:gem_name] %>
|
|
63
|
-
[driver_usage]:
|
|
63
|
+
[driver_usage]: https://kitchen.ci/docs/drivers/
|
|
64
64
|
[chef_omnibus_dl]: http://www.chef.io/chef/install/
|
data/test-kitchen.gemspec
CHANGED
|
@@ -20,33 +20,21 @@ Gem::Specification.new do |gem|
|
|
|
20
20
|
gem.executables = %w{kitchen}
|
|
21
21
|
gem.require_paths = ["lib"]
|
|
22
22
|
|
|
23
|
-
gem.required_ruby_version = ">=
|
|
23
|
+
gem.required_ruby_version = ">= 3.1"
|
|
24
24
|
|
|
25
|
+
gem.add_dependency "bcrypt_pbkdf", "~> 1.0" # ed25519 ssh key support
|
|
26
|
+
gem.add_dependency "chef-utils", ">= 16.4.35"
|
|
27
|
+
gem.add_dependency "ed25519", "~> 1.2" # ed25519 ssh key support
|
|
28
|
+
gem.add_dependency "mixlib-install", "~> 3.6"
|
|
25
29
|
gem.add_dependency "mixlib-shellout", ">= 1.2", "< 4.0"
|
|
26
|
-
gem.add_dependency "net-scp", ">= 1.1", "<
|
|
27
|
-
gem.add_dependency "net-ssh", ">= 2.9", "<
|
|
30
|
+
gem.add_dependency "net-scp", ">= 1.1", "< 5.0" # pinning until we can confirm 4+ works
|
|
31
|
+
gem.add_dependency "net-ssh", ">= 2.9", "< 8.0" # pinning until we can confirm 8+ works
|
|
28
32
|
gem.add_dependency "net-ssh-gateway", ">= 1.2", "< 3.0" # pinning until we can confirm 3+ works
|
|
29
|
-
gem.add_dependency "ed25519", "~> 1.2" # ed25519 ssh key support
|
|
30
|
-
gem.add_dependency "bcrypt_pbkdf", "~> 1.0" # ed25519 ssh key support
|
|
31
33
|
gem.add_dependency "thor", ">= 0.19", "< 2.0"
|
|
32
|
-
gem.add_dependency "mixlib-install", "~> 3.6"
|
|
33
34
|
gem.add_dependency "winrm", "~> 2.0"
|
|
34
35
|
gem.add_dependency "winrm-elevated", "~> 1.0"
|
|
35
36
|
gem.add_dependency "winrm-fs", "~> 1.1"
|
|
36
|
-
gem.add_dependency "chef-utils", ">= 16.4.35"
|
|
37
37
|
# Required to run the Chef provisioner local license check for remote systems
|
|
38
38
|
# TK is not under Chef EULA
|
|
39
39
|
gem.add_dependency "license-acceptance", ">= 1.0.11", "< 3.0" # pinning until we can confirm 3+ works
|
|
40
|
-
|
|
41
|
-
gem.add_development_dependency "rb-readline"
|
|
42
|
-
gem.add_development_dependency "bundler"
|
|
43
|
-
gem.add_development_dependency "rake"
|
|
44
|
-
|
|
45
|
-
gem.add_development_dependency "aruba", "~> 0.11", "< 1.0"
|
|
46
|
-
gem.add_development_dependency "fakefs", "~> 1.0"
|
|
47
|
-
gem.add_development_dependency "minitest", "~> 5.3", "< 5.15"
|
|
48
|
-
gem.add_development_dependency "mocha", "~> 1.1"
|
|
49
|
-
gem.add_development_dependency "cucumber", ">= 2.1", "< 8.0"
|
|
50
|
-
gem.add_development_dependency "countloc", "~> 0.4"
|
|
51
|
-
gem.add_development_dependency "maruku", "~> 0.6"
|
|
52
40
|
end
|