test-kitchen 1.4.2 → 1.5.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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/.travis.yml +29 -33
  4. data/CHANGELOG.md +86 -2
  5. data/CONTRIBUTING.md +17 -0
  6. data/Gemfile.proxy_tests +5 -0
  7. data/MAINTAINERS.md +24 -0
  8. data/features/kitchen_driver_discover_command.feature +6 -0
  9. data/features/kitchen_init_command.feature +55 -7
  10. data/features/step_definitions/gem_steps.rb +12 -4
  11. data/features/step_definitions/git_steps.rb +1 -1
  12. data/features/step_definitions/output_steps.rb +1 -1
  13. data/features/support/env.rb +13 -9
  14. data/lib/kitchen/cli.rb +46 -5
  15. data/lib/kitchen/command/driver_discover.rb +8 -0
  16. data/lib/kitchen/command.rb +1 -0
  17. data/lib/kitchen/config.rb +4 -0
  18. data/lib/kitchen/configurable.rb +32 -0
  19. data/lib/kitchen/driver/ssh_base.rb +18 -4
  20. data/lib/kitchen/generator/driver_create.rb +2 -2
  21. data/lib/kitchen/generator/init.rb +4 -4
  22. data/lib/kitchen/instance.rb +7 -0
  23. data/lib/kitchen/lazy_hash.rb +20 -0
  24. data/lib/kitchen/logger.rb +4 -7
  25. data/lib/kitchen/provisioner/base.rb +16 -1
  26. data/lib/kitchen/provisioner/chef_base.rb +43 -98
  27. data/lib/kitchen/provisioner/chef_solo.rb +7 -4
  28. data/lib/kitchen/provisioner/chef_zero.rb +12 -5
  29. data/lib/kitchen/ssh.rb +1 -1
  30. data/lib/kitchen/transport/base.rb +7 -0
  31. data/lib/kitchen/transport/ssh.rb +13 -6
  32. data/lib/kitchen/transport/winrm.rb +168 -50
  33. data/lib/kitchen/verifier/base.rb +18 -1
  34. data/lib/kitchen/verifier/busser.rb +12 -5
  35. data/lib/kitchen/verifier/shell.rb +101 -0
  36. data/lib/kitchen/version.rb +1 -2
  37. data/spec/kitchen/collection_spec.rb +1 -1
  38. data/spec/kitchen/configurable_spec.rb +211 -2
  39. data/spec/kitchen/driver/ssh_base_spec.rb +131 -8
  40. data/spec/kitchen/lazy_hash_spec.rb +27 -0
  41. data/spec/kitchen/logger_spec.rb +10 -0
  42. data/spec/kitchen/provisioner/base_spec.rb +25 -0
  43. data/spec/kitchen/provisioner/chef_base_spec.rb +133 -252
  44. data/spec/kitchen/provisioner/chef_solo_spec.rb +30 -0
  45. data/spec/kitchen/provisioner/chef_zero_spec.rb +27 -2
  46. data/spec/kitchen/provisioner/shell_spec.rb +60 -12
  47. data/spec/kitchen/ssh_spec.rb +1 -1
  48. data/spec/kitchen/transport/ssh_spec.rb +2 -1
  49. data/spec/kitchen/transport/winrm_spec.rb +228 -48
  50. data/spec/kitchen/verifier/base_spec.rb +26 -0
  51. data/spec/kitchen/verifier/busser_spec.rb +69 -3
  52. data/spec/kitchen/verifier/shell_spec.rb +157 -0
  53. data/support/busser_install_command.sh +1 -2
  54. data/support/chef_base_install_command.ps1 +19 -12
  55. data/templates/driver/README.md.erb +1 -1
  56. data/test-kitchen.gemspec +12 -3
  57. metadata +106 -10
@@ -295,15 +295,36 @@ module Kitchen
295
295
  # @param code [String] the shell code to be wrapped
296
296
  # @return [String] wrapped shell code
297
297
  # @api private
298
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
299
+ # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
298
300
  def wrap_shell_code(code)
299
301
  env = []
300
302
  if config[:http_proxy]
301
303
  env << shell_env_var("http_proxy", config[:http_proxy])
302
304
  env << shell_env_var("HTTP_PROXY", config[:http_proxy])
305
+ else
306
+ export_proxy(env, "http")
303
307
  end
304
308
  if config[:https_proxy]
305
309
  env << shell_env_var("https_proxy", config[:https_proxy])
306
310
  env << shell_env_var("HTTPS_PROXY", config[:https_proxy])
311
+ else
312
+ export_proxy(env, "https")
313
+ end
314
+ if config[:ftp_proxy]
315
+ env << shell_env_var("ftp_proxy", config[:ftp_proxy])
316
+ env << shell_env_var("FTP_PROXY", config[:ftp_proxy])
317
+ else
318
+ export_proxy(env, "ftp")
319
+ end
320
+ # if http_proxy was set from environment variable or https_proxy was set
321
+ # from environment variable, or ftp_proxy was set from environment
322
+ # variable, include no_proxy environment variable, if set.
323
+ if (!config[:http_proxy] && (ENV["http_proxy"] || ENV["HTTP_PROXY"])) ||
324
+ (!config[:https_proxy] && (ENV["https_proxy"] || ENV["HTTPS_PROXY"])) ||
325
+ (!config[:ftp_proxy] && (ENV["ftp_proxy"] || ENV["FTP_PROXY"]))
326
+ env << shell_env_var("no_proxy", ENV["no_proxy"]) if ENV["no_proxy"]
327
+ env << shell_env_var("NO_PROXY", ENV["NO_PROXY"]) if ENV["NO_PROXY"]
307
328
  end
308
329
  if powershell_shell?
309
330
  env.join("\n").concat("\n").concat(code)
@@ -312,6 +333,17 @@ module Kitchen
312
333
  end
313
334
  end
314
335
 
336
+ # Helper method to export
337
+ #
338
+ # @param env [Array] the environment to modify
339
+ # @param code [String] the type of proxy to export, one of 'http', 'https' or 'ftp'
340
+ # @api private
341
+ def export_proxy(env, type)
342
+ env << shell_env_var("#{type}_proxy", ENV["#{type}_proxy"]) if ENV["#{type}_proxy"]
343
+ env << shell_env_var("#{type.upcase}_PROXY", ENV["#{type.upcase}_PROXY"]) if
344
+ ENV["#{type.upcase}_PROXY"]
345
+ end
346
+
315
347
  # Class methods which will be mixed in on inclusion of Configurable module.
316
348
  module ClassMethods
317
349
 
@@ -233,17 +233,31 @@ module Kitchen
233
233
  [combined[:hostname], combined[:username], opts]
234
234
  end
235
235
 
236
- # Adds http and https proxy environment variables to a command, if set
237
- # in configuration data.
236
+ # Adds http, https and ftp proxy environment variables to a command, if
237
+ # set in configuration data or on local workstation.
238
238
  #
239
239
  # @param cmd [String] command string
240
240
  # @return [String] command string
241
241
  # @api private
242
+ # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity, Metrics/AbcSize
242
243
  def env_cmd(cmd)
243
244
  return if cmd.nil?
244
245
  env = "env"
245
- env << " http_proxy=#{config[:http_proxy]}" if config[:http_proxy]
246
- env << " https_proxy=#{config[:https_proxy]}" if config[:https_proxy]
246
+ http_proxy = config[:http_proxy] || ENV["http_proxy"] ||
247
+ ENV["HTTP_PROXY"]
248
+ https_proxy = config[:https_proxy] || ENV["https_proxy"] ||
249
+ ENV["HTTPS_PROXY"]
250
+ ftp_proxy = config[:ftp_proxy] || ENV["ftp_proxy"] ||
251
+ ENV["FTP_PROXY"]
252
+ no_proxy = if (!config[:http_proxy] && http_proxy) ||
253
+ (!config[:https_proxy] && https_proxy) ||
254
+ (!config[:ftp_proxy] && ftp_proxy)
255
+ ENV["no_proxy"] || ENV["NO_PROXY"]
256
+ end
257
+ env << " http_proxy=#{http_proxy}" if http_proxy
258
+ env << " https_proxy=#{https_proxy}" if https_proxy
259
+ env << " ftp_proxy=#{ftp_proxy}" if ftp_proxy
260
+ env << " no_proxy=#{no_proxy}" if no_proxy
247
261
 
248
262
  env == "env" ? cmd : "#{env} #{cmd}"
249
263
  end
@@ -87,8 +87,8 @@ module Kitchen
87
87
  # @api private
88
88
  def initialize_git
89
89
  inside(target_dir) do
90
- run("git init")
91
- run("git add .")
90
+ run("git init", :capture => true)
91
+ run("git add .", :capture => true)
92
92
  end
93
93
  end
94
94
 
@@ -143,10 +143,10 @@ module Kitchen
143
143
  rakedoc = <<-RAKE.gsub(/^ {10}/, "")
144
144
 
145
145
  begin
146
- require "kitchen/rake_tasks"
146
+ require 'kitchen/rake_tasks'
147
147
  Kitchen::RakeTasks.new
148
148
  rescue LoadError
149
- puts ">>>>> Kitchen gem not loaded, omitting tasks" unless ENV["CI"]
149
+ puts '>>>>> Kitchen gem not loaded, omitting tasks' unless ENV['CI']
150
150
  end
151
151
  RAKE
152
152
  append_to_file(File.join(destination_root, "Rakefile"), rakedoc)
@@ -161,10 +161,10 @@ module Kitchen
161
161
  thordoc = <<-THOR.gsub(/^ {10}/, "")
162
162
 
163
163
  begin
164
- require "kitchen/thor_tasks"
164
+ require 'kitchen/thor_tasks'
165
165
  Kitchen::ThorTasks.new
166
166
  rescue LoadError
167
- puts ">>>>> Kitchen gem not loaded, omitting tasks" unless ENV["CI"]
167
+ puts '>>>>> Kitchen gem not loaded, omitting tasks' unless ENV['CI']
168
168
  end
169
169
  THOR
170
170
  append_to_file(File.join(destination_root, "Thorfile"), thordoc)
@@ -267,6 +267,13 @@ module Kitchen
267
267
  state_file.read[:last_action]
268
268
  end
269
269
 
270
+ # Clean up any per-instance resources before exiting.
271
+ #
272
+ # @return [void]
273
+ def cleanup!
274
+ @transport.cleanup! if @transport
275
+ end
276
+
270
277
  private
271
278
 
272
279
  # @return [StateFile] a state file object that can be read from or written
@@ -53,6 +53,7 @@ module Kitchen
53
53
  #
54
54
  # @author Fletcher Nichol <fnichol@nichol.ca>
55
55
  class LazyHash < SimpleDelegator
56
+ include Enumerable
56
57
 
57
58
  # Creates a new LazyHash using a Hash-like object to populate itself and
58
59
  # an object that can be used as context in value-callable blocks. The
@@ -105,6 +106,25 @@ module Kitchen
105
106
  hash
106
107
  end
107
108
 
109
+ # Yields each key/value pair to the provided block. Returns a new
110
+ # Hash with only the keys and rendered values for which the block
111
+ # returns true.
112
+ #
113
+ # @return [Hash] a new hash
114
+ def select(&block)
115
+ to_hash.select(&block)
116
+ end
117
+
118
+ # If no block provided, returns an enumerator over the keys and
119
+ # rendered values in the underlying object. If a block is
120
+ # provided, calls the block once for each [key, rendered_value]
121
+ # pair in the underlying object.
122
+ #
123
+ # @return [Enumerator, Array]
124
+ def each(&block)
125
+ to_hash.each(&block)
126
+ end
127
+
108
128
  private
109
129
 
110
130
  # Returns an object or invokes call with context if object is callable.
@@ -343,13 +343,10 @@ module Kitchen
343
343
  # @param msg [String] a message
344
344
  def <<(msg)
345
345
  @buffer ||= ""
346
- lines, _, remainder = msg.rpartition("\n")
347
- if lines.empty?
348
- @buffer << remainder
349
- else
350
- lines.insert(0, @buffer)
351
- lines.split("\n").each { |l| format_line(l.chomp) }
352
- @buffer = ""
346
+ @buffer += msg
347
+ while i = @buffer.index("\n")
348
+ format_line(@buffer[0, i].chomp)
349
+ @buffer[0, i + 1] = ""
353
350
  end
354
351
  end
355
352
 
@@ -29,8 +29,8 @@ module Kitchen
29
29
  include Logging
30
30
 
31
31
  default_config :http_proxy, nil
32
-
33
32
  default_config :https_proxy, nil
33
+ default_config :ftp_proxy, nil
34
34
 
35
35
  default_config :root_path do |provisioner|
36
36
  provisioner.windows_os? ? "$env:TEMP\\kitchen" : "/tmp/kitchen"
@@ -44,6 +44,8 @@ module Kitchen
44
44
  provisioner.windows_os? ? nil : "sudo -E"
45
45
  end
46
46
 
47
+ default_config :command_prefix, nil
48
+
47
49
  expand_path_for :test_base_path
48
50
 
49
51
  # Constructs a new provisioner by providing a configuration hash.
@@ -208,6 +210,19 @@ module Kitchen
208
210
  def sudo(script)
209
211
  config[:sudo] ? "#{config[:sudo_command]} #{script}" : script
210
212
  end
213
+
214
+ # Conditionally prefixes a command with a command prefix.
215
+ # This should generally be done after a command has been
216
+ # conditionally prefixed by #sudo as certain platforms, such as
217
+ # Cisco Nexus, require all commands to be run with a prefix to
218
+ # obtain outbound network access.
219
+ #
220
+ # @param command [String] command to be prefixed
221
+ # @return [String] the command, conditionally prefixed with the configured prefix
222
+ # @api private
223
+ def prefix_command(script)
224
+ config[:command_prefix] ? "#{config[:command_prefix]} #{script}" : script
225
+ end
211
226
  end
212
227
  end
213
228
  end
@@ -25,6 +25,9 @@ require "kitchen/provisioner/chef/berkshelf"
25
25
  require "kitchen/provisioner/chef/common_sandbox"
26
26
  require "kitchen/provisioner/chef/librarian"
27
27
  require "kitchen/util"
28
+ require "mixlib/install"
29
+ require "chef-config/config"
30
+ require "chef-config/workstation_config_loader"
28
31
 
29
32
  module Kitchen
30
33
 
@@ -40,25 +43,15 @@ module Kitchen
40
43
  default_config :chef_omnibus_install_options, nil
41
44
  default_config :run_list, []
42
45
  default_config :attributes, {}
46
+ default_config :config_path, nil
43
47
  default_config :log_file, nil
48
+ default_config :profile_ruby, false
44
49
  default_config :cookbook_files_glob, %w[
45
50
  README.* metadata.{json,rb}
46
51
  attributes/**/* definitions/**/* files/**/* libraries/**/*
47
52
  providers/**/* recipes/**/* resources/**/* templates/**/*
48
53
  ].join(",")
49
54
 
50
- default_config :chef_metadata_url do |provisioner|
51
- provisioner.default_windows_chef_metadata_url if provisioner.windows_os?
52
- end
53
-
54
- default_config :chef_omnibus_root do |provisioner|
55
- if provisioner.windows_os?
56
- "$env:systemdrive\\opscode\\chef"
57
- else
58
- "/opt/chef"
59
- end
60
- end
61
-
62
55
  default_config :data_path do |provisioner|
63
56
  provisioner.calculate_path("data")
64
57
  end
@@ -94,29 +87,27 @@ module Kitchen
94
87
  end
95
88
  expand_path_for :encrypted_data_bag_secret_key_path
96
89
 
90
+ # Reads the local Chef::Config object (if present). We do this because
91
+ # we want to start bring Chef config and ChefDK tool config closer
92
+ # together. For example, we want to configure proxy settings in 1
93
+ # location instead of 3 configuration files.
94
+ #
95
+ # @param config [Hash] initial provided configuration
96
+ def initialize(config = {})
97
+ super(config)
98
+
99
+ ChefConfig::WorkstationConfigLoader.new(config[:config_path]).load
100
+ # This exports any proxy config present in the Chef config to
101
+ # appropriate environment variables, which Test Kitchen respects
102
+ ChefConfig::Config.export_proxies
103
+ end
104
+
97
105
  # (see Base#create_sandbox)
98
106
  def create_sandbox
99
107
  super
100
108
  Chef::CommonSandbox.new(config, sandbox_path, instance).populate
101
109
  end
102
110
 
103
- # @return [String] a metadata URL for the Chef Omnitruck API suitable
104
- # for installing a Windows MSI package
105
- def default_windows_chef_metadata_url
106
- version = config[:require_chef_omnibus]
107
- version = "latest" if version == true
108
- base = if config[:chef_omnibus_url] =~ %r{/install.sh$}
109
- "#{File.dirname(config[:chef_omnibus_url])}/"
110
- else
111
- "https://www.chef.io/chef/"
112
- end
113
-
114
- url = "#{base}#{metadata_project_from_options}"
115
- url << "?p=windows&m=x86_64&pv=2008r2" # same pacakge for all versions
116
- url << "&v=#{CGI.escape(version.to_s.downcase)}"
117
- url
118
- end
119
-
120
111
  # (see Base#init_command)
121
112
  def init_command
122
113
  dirs = %w[
@@ -130,7 +121,7 @@ module Kitchen
130
121
  init_command_vars_for_bourne(dirs)
131
122
  end
132
123
 
133
- shell_code_from_file(vars, "chef_base_init_command")
124
+ prefix_command(shell_code_from_file(vars, "chef_base_init_command"))
134
125
  end
135
126
 
136
127
  # (see Base#install_command)
@@ -139,17 +130,33 @@ module Kitchen
139
130
 
140
131
  version = config[:require_chef_omnibus].to_s.downcase
141
132
 
142
- vars = if powershell_shell?
143
- install_command_vars_for_powershell(version)
144
- else
145
- install_command_vars_for_bourne(version)
146
- end
133
+ # Passing "true" to mixlib-install currently breaks the windows metadata_url
134
+ # TODO: remove this line once https://github.com/chef/mixlib-install/pull/22
135
+ # is accepted and released
136
+ version = "" if version == "true" && powershell_shell?
147
137
 
148
- shell_code_from_file(vars, "chef_base_install_command")
138
+ installer = Mixlib::Install.new(version, powershell_shell?, install_options)
139
+ config[:chef_omnibus_root] = installer.root
140
+ prefix_command(sudo(installer.install_command))
149
141
  end
150
142
 
151
143
  private
152
144
 
145
+ # @return [Hash] an option hash for the install commands
146
+ # @api private
147
+ def install_options
148
+ project = /\s*-P (\w+)\s*/.match(config[:chef_omnibus_install_options])
149
+ {
150
+ :omnibus_url => config[:chef_omnibus_url],
151
+ :project => project.nil? ? nil : project[1],
152
+ :install_flags => config[:chef_omnibus_install_options]
153
+ }.tap do |opts|
154
+ opts[:root] = config[:chef_omnibus_root] if config.key? :chef_omnibus_root
155
+ opts[:http_proxy] = config[:http_proxy] if config.key? :http_proxy
156
+ opts[:https_proxy] = config[:https_proxy] if config.key? :https_proxy
157
+ end
158
+ end
159
+
153
160
  # @return [String] an absolute path to a Berksfile, relative to the
154
161
  # kitchen root
155
162
  # @api private
@@ -251,43 +258,6 @@ module Kitchen
251
258
  ].join("\n")
252
259
  end
253
260
 
254
- # Generates the install command variables for Bourne shell-based
255
- # platforms.
256
- #
257
- # @param version [String] version string
258
- # @return [String] shell variable lines
259
- # @api private
260
- def install_command_vars_for_bourne(version)
261
- install_flags = %w[latest true].include?(version) ? "" : "-v #{CGI.escape(version)}"
262
- if config[:chef_omnibus_install_options]
263
- install_flags << " " << config[:chef_omnibus_install_options]
264
- end
265
-
266
- [
267
- shell_var("chef_omnibus_root", config[:chef_omnibus_root]),
268
- shell_var("chef_omnibus_url", config[:chef_omnibus_url]),
269
- shell_var("install_flags", install_flags.strip),
270
- shell_var("pretty_version", pretty_version(version)),
271
- shell_var("sudo_sh", sudo("sh")),
272
- shell_var("version", version)
273
- ].join("\n")
274
- end
275
-
276
- # Generates the install command variables for PowerShell-based platforms.
277
- #
278
- # @param version [String] version string
279
- # @return [String] shell variable lines
280
- # @api private
281
- def install_command_vars_for_powershell(version)
282
- [
283
- shell_var("chef_metadata_url", config[:chef_metadata_url]),
284
- shell_var("chef_omnibus_root", config[:chef_omnibus_root]),
285
- shell_var("msi", "$env:TEMP\\chef-#{version}.msi"),
286
- shell_var("pretty_version", pretty_version(version)),
287
- shell_var("version", version)
288
- ].join("\n")
289
- end
290
-
291
261
  # Load cookbook dependency resolver code, if required.
292
262
  #
293
263
  # (see Base#load_needed_dependencies!)
@@ -302,31 +272,6 @@ module Kitchen
302
272
  end
303
273
  end
304
274
 
305
- # @return the correct Chef Omnitruck API metadata endpoint, based on
306
- # project type which could live in
307
- # `config[:chef_omnibus_install_options]`
308
- # @api private
309
- def metadata_project_from_options
310
- match = /\s*-P (\w+)\s*/.match(config[:chef_omnibus_install_options])
311
-
312
- if match.nil? || match[1].downcase == "chef"
313
- "metadata"
314
- else
315
- "metadata-#{match[1].downcase}"
316
- end
317
- end
318
-
319
- # @return [String] a pretty/helpful representation of a Chef Omnibus
320
- # package version
321
- # @api private
322
- def pretty_version(version)
323
- case version
324
- when "true" then "install only if missing"
325
- when "latest" then "always install latest version"
326
- else version
327
- end
328
- end
329
-
330
275
  # @return [String] a powershell command to reload the `PATH` environment
331
276
  # variable, only to be used to support old Omnibus Chef packages that
332
277
  # require `PATH` to find the `ruby.exe` binary
@@ -46,7 +46,7 @@ module Kitchen
46
46
  end
47
47
 
48
48
  # (see Base#run_command)
49
- def run_command
49
+ def run_command # rubocop:disable Metrics/AbcSize
50
50
  level = config[:log_level] == :info ? :auto : config[:log_level]
51
51
 
52
52
  cmd = sudo(config[:chef_solo_path]).dup.
@@ -59,11 +59,14 @@ module Kitchen
59
59
  "--json-attributes #{remote_path_join(config[:root_path], "dna.json")}"
60
60
  ]
61
61
  args << "--logfile #{config[:log_file]}" if config[:log_file]
62
+ args << "--profile-ruby" if config[:profile_ruby]
62
63
 
63
- wrap_shell_code(
64
- [cmd, *args].join(" ").
65
- tap { |str| str.insert(0, reload_ps1_path) if windows_os? }
64
+ prefix_command(
65
+ wrap_shell_code(
66
+ [cmd, *args].join(" ").
67
+ tap { |str| str.insert(0, reload_ps1_path) if windows_os? }
66
68
  )
69
+ )
67
70
  end
68
71
 
69
72
  private
@@ -66,16 +66,18 @@ module Kitchen
66
66
  shell_var("gem", sudo(gem_bin))
67
67
  ].join("\n").concat("\n")
68
68
 
69
- shell_code_from_file(vars, "chef_zero_prepare_command_legacy")
69
+ prefix_command(shell_code_from_file(vars, "chef_zero_prepare_command_legacy"))
70
70
  end
71
71
 
72
72
  # (see Base#run_command)
73
73
  def run_command
74
74
  cmd = modern? ? local_mode_command : shim_command
75
75
 
76
- wrap_shell_code(
77
- [cmd, *chef_client_args].join(" ").
78
- tap { |str| str.insert(0, reload_ps1_path) if windows_os? }
76
+ prefix_command(
77
+ wrap_shell_code(
78
+ [cmd, *chef_client_args].join(" ").
79
+ tap { |str| str.insert(0, reload_ps1_path) if windows_os? }
80
+ )
79
81
  )
80
82
  end
81
83
 
@@ -86,6 +88,7 @@ module Kitchen
86
88
  #
87
89
  # @param args [Array<String>] array of flags
88
90
  # @api private
91
+ # rubocop:disable Metrics/CyclomaticComplexity
89
92
  def add_optional_chef_client_args!(args)
90
93
  if config[:json_attributes]
91
94
  json = remote_path_join(config[:root_path], "dna.json")
@@ -104,14 +107,18 @@ module Kitchen
104
107
  if config[:chef_zero_port]
105
108
  args << "--chef-zero-port #{config[:chef_zero_port]}"
106
109
  end
110
+ if config[:profile_ruby]
111
+ args << "--profile-ruby"
112
+ end
107
113
  end
114
+ # rubocop:enable Metrics/CyclomaticComplexity
108
115
 
109
116
  # Returns an Array of command line arguments for the chef client.
110
117
  #
111
118
  # @return [Array<String>] an array of command line arguments
112
119
  # @api private
113
120
  def chef_client_args
114
- level = config[:log_level] == :info ? :auto : config[:log_level]
121
+ level = config[:log_level] == :info ? :warn : config[:log_level]
115
122
  args = [
116
123
  "--config #{remote_path_join(config[:root_path], "client.rb")}",
117
124
  "--log_level #{level}",
data/lib/kitchen/ssh.rb CHANGED
@@ -192,7 +192,7 @@ module Kitchen
192
192
  rescue_exceptions = [
193
193
  Errno::EACCES, Errno::EADDRINUSE, Errno::ECONNREFUSED,
194
194
  Errno::ECONNRESET, Errno::ENETUNREACH, Errno::EHOSTUNREACH,
195
- Net::SSH::Disconnect, Net::SSH::AuthenticationFailed
195
+ Net::SSH::Disconnect, Net::SSH::AuthenticationFailed, Net::SSH::ConnectionTimeout
196
196
  ]
197
197
  retries = options[:ssh_retries] || 3
198
198
 
@@ -58,6 +58,13 @@ module Kitchen
58
58
  raise ClientError, "#{self.class}#connection must be implemented"
59
59
  end
60
60
 
61
+ # Closes the connection, if it is still active.
62
+ #
63
+ # @return [void]
64
+ def cleanup!
65
+ # This method may be left unimplemented if that is applicable
66
+ end
67
+
61
68
  # A Connection instance can be generated and re-generated, given new
62
69
  # connection details such as connection port, hostname, credentials, etc.
63
70
  # This object is responsible for carrying out the actions on the remote
@@ -20,6 +20,7 @@ require "kitchen"
20
20
 
21
21
  require "net/ssh"
22
22
  require "net/scp"
23
+ require "timeout"
23
24
 
24
25
  module Kitchen
25
26
 
@@ -85,6 +86,15 @@ module Kitchen
85
86
  end
86
87
  end
87
88
 
89
+ # (see Base#cleanup!)
90
+ def cleanup!
91
+ if @connection
92
+ logger.debug("[SSH] shutting previous connection #{@connection}")
93
+ @connection.close
94
+ @connection = @connection_options = nil
95
+ end
96
+ end
97
+
88
98
  # A Connection instance can be generated and re-generated, given new
89
99
  # connection details such as connection port, hostname, credentials, etc.
90
100
  # This object is responsible for carrying out the actions on the remote
@@ -165,7 +175,8 @@ module Kitchen
165
175
  RESCUE_EXCEPTIONS_ON_ESTABLISH = [
166
176
  Errno::EACCES, Errno::EADDRINUSE, Errno::ECONNREFUSED, Errno::ETIMEDOUT,
167
177
  Errno::ECONNRESET, Errno::ENETUNREACH, Errno::EHOSTUNREACH,
168
- Net::SSH::Disconnect, Net::SSH::AuthenticationFailed, Timeout::Error
178
+ Net::SSH::Disconnect, Net::SSH::AuthenticationFailed, Net::SSH::ConnectionTimeout,
179
+ Timeout::Error
169
180
  ].freeze
170
181
 
171
182
  # @return [Integer] how many times to retry when failing to execute
@@ -334,11 +345,7 @@ module Kitchen
334
345
  # @return [Ssh::Connection] an SSH Connection instance
335
346
  # @api private
336
347
  def create_new_connection(options, &block)
337
- if @connection
338
- logger.debug("[SSH] shutting previous connection #{@connection}")
339
- @connection.close
340
- end
341
-
348
+ cleanup!
342
349
  @connection_options = options
343
350
  @connection = Kitchen::Transport::Ssh::Connection.new(options, &block)
344
351
  end