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.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.travis.yml +29 -33
- data/CHANGELOG.md +86 -2
- data/CONTRIBUTING.md +17 -0
- data/Gemfile.proxy_tests +5 -0
- data/MAINTAINERS.md +24 -0
- data/features/kitchen_driver_discover_command.feature +6 -0
- data/features/kitchen_init_command.feature +55 -7
- data/features/step_definitions/gem_steps.rb +12 -4
- data/features/step_definitions/git_steps.rb +1 -1
- data/features/step_definitions/output_steps.rb +1 -1
- data/features/support/env.rb +13 -9
- data/lib/kitchen/cli.rb +46 -5
- data/lib/kitchen/command/driver_discover.rb +8 -0
- data/lib/kitchen/command.rb +1 -0
- data/lib/kitchen/config.rb +4 -0
- data/lib/kitchen/configurable.rb +32 -0
- data/lib/kitchen/driver/ssh_base.rb +18 -4
- data/lib/kitchen/generator/driver_create.rb +2 -2
- data/lib/kitchen/generator/init.rb +4 -4
- data/lib/kitchen/instance.rb +7 -0
- data/lib/kitchen/lazy_hash.rb +20 -0
- data/lib/kitchen/logger.rb +4 -7
- data/lib/kitchen/provisioner/base.rb +16 -1
- data/lib/kitchen/provisioner/chef_base.rb +43 -98
- data/lib/kitchen/provisioner/chef_solo.rb +7 -4
- data/lib/kitchen/provisioner/chef_zero.rb +12 -5
- data/lib/kitchen/ssh.rb +1 -1
- data/lib/kitchen/transport/base.rb +7 -0
- data/lib/kitchen/transport/ssh.rb +13 -6
- data/lib/kitchen/transport/winrm.rb +168 -50
- data/lib/kitchen/verifier/base.rb +18 -1
- data/lib/kitchen/verifier/busser.rb +12 -5
- data/lib/kitchen/verifier/shell.rb +101 -0
- data/lib/kitchen/version.rb +1 -2
- data/spec/kitchen/collection_spec.rb +1 -1
- data/spec/kitchen/configurable_spec.rb +211 -2
- data/spec/kitchen/driver/ssh_base_spec.rb +131 -8
- data/spec/kitchen/lazy_hash_spec.rb +27 -0
- data/spec/kitchen/logger_spec.rb +10 -0
- data/spec/kitchen/provisioner/base_spec.rb +25 -0
- data/spec/kitchen/provisioner/chef_base_spec.rb +133 -252
- data/spec/kitchen/provisioner/chef_solo_spec.rb +30 -0
- data/spec/kitchen/provisioner/chef_zero_spec.rb +27 -2
- data/spec/kitchen/provisioner/shell_spec.rb +60 -12
- data/spec/kitchen/ssh_spec.rb +1 -1
- data/spec/kitchen/transport/ssh_spec.rb +2 -1
- data/spec/kitchen/transport/winrm_spec.rb +228 -48
- data/spec/kitchen/verifier/base_spec.rb +26 -0
- data/spec/kitchen/verifier/busser_spec.rb +69 -3
- data/spec/kitchen/verifier/shell_spec.rb +157 -0
- data/support/busser_install_command.sh +1 -2
- data/support/chef_base_install_command.ps1 +19 -12
- data/templates/driver/README.md.erb +1 -1
- data/test-kitchen.gemspec +12 -3
- metadata +106 -10
data/lib/kitchen/configurable.rb
CHANGED
|
@@ -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
|
|
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
|
-
|
|
246
|
-
|
|
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
|
|
@@ -143,10 +143,10 @@ module Kitchen
|
|
|
143
143
|
rakedoc = <<-RAKE.gsub(/^ {10}/, "")
|
|
144
144
|
|
|
145
145
|
begin
|
|
146
|
-
require
|
|
146
|
+
require 'kitchen/rake_tasks'
|
|
147
147
|
Kitchen::RakeTasks.new
|
|
148
148
|
rescue LoadError
|
|
149
|
-
puts
|
|
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
|
|
164
|
+
require 'kitchen/thor_tasks'
|
|
165
165
|
Kitchen::ThorTasks.new
|
|
166
166
|
rescue LoadError
|
|
167
|
-
puts
|
|
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)
|
data/lib/kitchen/instance.rb
CHANGED
|
@@ -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
|
data/lib/kitchen/lazy_hash.rb
CHANGED
|
@@ -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.
|
data/lib/kitchen/logger.rb
CHANGED
|
@@ -343,13 +343,10 @@ module Kitchen
|
|
|
343
343
|
# @param msg [String] a message
|
|
344
344
|
def <<(msg)
|
|
345
345
|
@buffer ||= ""
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
@buffer
|
|
349
|
-
|
|
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
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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
|
-
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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 ? :
|
|
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,
|
|
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
|
-
|
|
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
|