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.
@@ -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
- logger.debug("[SSH] shutting previous connection #{@connection}")
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
- logger.debug("[SSH] closing connection to #{self}")
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
- logger.debug("[SSH] #{self} (#{command})")
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 session.scp.upload(local, remote, opts) do |_ch, name, sent, total|
180
- logger.debug("Async Uploaded #{name} (#{total} bytes)") if sent == total
181
- end
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: 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
- logger.debug(log_msg)
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: 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] conneciton options
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
- logger.debug("[SSH] reusing existing connection #{@connection}")
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
- logger.debug("[WinRM] #{self} (#{command})")
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 Powershell script over WinRM and return the command's
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] Powershell script to execute
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: logger,
428
- endpoint: 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: 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] conneciton options
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
- logger.debug("[WinRM] shutting previous connection #{@connection}")
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
- logger.debug("[WinRM] reusing existing connection #{@connection}")
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
- info("Downloading files from #{instance.to_str}")
80
- config[:downloads].to_h.each do |remotes, local|
81
- debug("Downloading #{Array(remotes).join(", ")} to #{local}")
82
- conn.download(remotes, local)
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
  #
@@ -16,5 +16,5 @@
16
16
  # limitations under the License.
17
17
 
18
18
  module Kitchen
19
- VERSION = "3.1.0".freeze
19
+ VERSION = "3.6.0".freeze
20
20
  end
data/lib/kitchen.rb CHANGED
@@ -91,7 +91,7 @@ module Kitchen
91
91
  stdout: $stdout,
92
92
  logdev: log_location,
93
93
  level: Util.to_logger_level(level),
94
- log_overwrite: log_overwrite
94
+ log_overwrite:
95
95
  )
96
96
  end
97
97
 
@@ -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/master/LICENSE
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]: http://docs.kitchen-ci.org/drivers/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 = ">= 2.6"
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", "< 4.0" # pinning until we can confirm 4+ works
27
- gem.add_dependency "net-ssh", ">= 2.9", "< 7.0" # pinning until we can confirm 7+ works
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