test-kitchen 1.15.0 → 1.16.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/.travis.yml +3 -2
- data/CHANGELOG.md +45 -1
- data/Gemfile +1 -1
- data/Rakefile +1 -1
- data/lib/kitchen/command/console.rb +1 -1
- data/lib/kitchen/configurable.rb +2 -15
- data/lib/kitchen/provisioner/chef_base.rb +92 -0
- data/lib/kitchen/provisioner/chef_solo.rb +19 -25
- data/lib/kitchen/provisioner/chef_zero.rb +4 -28
- data/lib/kitchen/transport/ssh.rb +4 -0
- data/lib/kitchen/version.rb +1 -1
- data/spec/kitchen/configurable_spec.rb +3 -0
- data/spec/kitchen/provisioner/chef_solo_spec.rb +24 -0
- data/spec/kitchen/provisioner/chef_zero_spec.rb +24 -0
- data/spec/kitchen/ssh_spec.rb +14 -75
- data/spec/kitchen/transport/ssh_spec.rb +19 -70
- data/support/chef-client-fail-if-update-handler.rb +15 -0
- data/test-kitchen.gemspec +1 -1
- metadata +12 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 35d190e1e4d808396433a878cc3f83cea4e471ba
|
4
|
+
data.tar.gz: 7473ada16496b8f037c6f747620b183901f17f39
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1749a54b16c555e6fbe7ff610daf75b028a9978a47057a55edb46c97a2629a808fac08f476741d092135ff92439ac2949ea763813b81b19f80c1885b9c704c2
|
7
|
+
data.tar.gz: 0737791415771c2ccfc7295686e83cd1c195fd515e628fc6d61752a0ba0821655498dafda61ca8c1fd907d79032595470be1b2de48b7b0fc39151b19c81cab75
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,53 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## [v1.16.0](https://github.com/test-kitchen/test-kitchen/tree/v1.16.0) (2017-03-03)
|
4
|
+
[Full Changelog](https://github.com/test-kitchen/test-kitchen/compare/v1.15.0...v1.16.0)
|
5
|
+
|
6
|
+
**Implemented enhancements:**
|
7
|
+
|
8
|
+
- Enforce suite idempotency [\#874](https://github.com/test-kitchen/test-kitchen/issues/874)
|
9
|
+
- Export no\_proxy from kitchen config [\#1178](https://github.com/test-kitchen/test-kitchen/pull/1178) ([itmustbejj](https://github.com/itmustbejj))
|
10
|
+
- Adding transport option "ssh\_key\_only". [\#1141](https://github.com/test-kitchen/test-kitchen/pull/1141) ([cliles](https://github.com/cliles))
|
11
|
+
- Run chef-client twice in chef-zero provisioner [\#875](https://github.com/test-kitchen/test-kitchen/pull/875) ([kamaradclimber](https://github.com/kamaradclimber))
|
12
|
+
|
13
|
+
**Fixed bugs:**
|
14
|
+
|
15
|
+
- Pinning thor to match berks [\#1189](https://github.com/test-kitchen/test-kitchen/pull/1189) ([cheeseplus](https://github.com/cheeseplus))
|
16
|
+
|
17
|
+
**Closed issues:**
|
18
|
+
|
19
|
+
- Message: Could not load the 'ansible\_playbook' provisioner from the load path [\#1197](https://github.com/test-kitchen/test-kitchen/issues/1197)
|
20
|
+
- pull or push in a docker registry with kitchen [\#1186](https://github.com/test-kitchen/test-kitchen/issues/1186)
|
21
|
+
- Compat issues with net-ssh 4.x [\#1184](https://github.com/test-kitchen/test-kitchen/issues/1184)
|
22
|
+
- Changelog was not updated for the 1.15.0 release [\#1183](https://github.com/test-kitchen/test-kitchen/issues/1183)
|
23
|
+
- Could not load or activate Berkshelf [\#1172](https://github.com/test-kitchen/test-kitchen/issues/1172)
|
24
|
+
- WinRm - I/O Operation Aborted [\#1142](https://github.com/test-kitchen/test-kitchen/issues/1142)
|
25
|
+
- Guest hostname does not get set if converge times out during vagrant VM boot [\#1128](https://github.com/test-kitchen/test-kitchen/issues/1128)
|
26
|
+
- I'm trying to run kitchen converge but getting the converge IO error [\#1075](https://github.com/test-kitchen/test-kitchen/issues/1075)
|
27
|
+
- Documentation for support for Encrypted Data Bags [\#384](https://github.com/test-kitchen/test-kitchen/issues/384)
|
28
|
+
|
29
|
+
## [v1.15.0](https://github.com/test-kitchen/test-kitchen/tree/v1.15.0) (2017-01-12)
|
30
|
+
[Full Changelog](https://github.com/test-kitchen/test-kitchen/compare/v1.14.2...v1.15.0)
|
31
|
+
|
32
|
+
**Implemented enhancements:**
|
33
|
+
|
34
|
+
- Display the last action's success [\#1124](https://github.com/test-kitchen/test-kitchen/issues/1124)
|
35
|
+
- Relax dependencies to bring in newer gem versions [\#1176](https://github.com/test-kitchen/test-kitchen/pull/1176) ([lamont-granquist](https://github.com/lamont-granquist))
|
36
|
+
- Make RakeTask\#config public. [\#1069](https://github.com/test-kitchen/test-kitchen/pull/1069) ([gregsymons](https://github.com/gregsymons))
|
37
|
+
|
38
|
+
**Fixed bugs:**
|
39
|
+
|
40
|
+
- Fix busser trying to run bats when bats tests don't exist [\#1133](https://github.com/test-kitchen/test-kitchen/pull/1133) ([amontalban](https://github.com/amontalban))
|
41
|
+
|
42
|
+
**Closed issues:**
|
43
|
+
|
44
|
+
- "incompatible character encodings: UTF-8 and ASCII-8BIT" when using cyrillic letters in cookbook [\#1170](https://github.com/test-kitchen/test-kitchen/issues/1170)
|
45
|
+
- ssh\_key is not read and sent to the args for ssh transport [\#1169](https://github.com/test-kitchen/test-kitchen/issues/1169)
|
46
|
+
|
3
47
|
## [v1.14.2](https://github.com/test-kitchen/test-kitchen/tree/v1.14.2) (2016-12-09)
|
4
48
|
[Full Changelog](https://github.com/test-kitchen/test-kitchen/compare/v1.14.1...v1.14.2)
|
5
49
|
|
6
|
-
**
|
50
|
+
**Implemented enhancements:**
|
7
51
|
|
8
52
|
- Replace finstyle in favor of chefstyle [\#1166](https://github.com/test-kitchen/test-kitchen/pull/1166) ([afiune](https://github.com/afiune))
|
9
53
|
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -37,7 +37,7 @@ begin
|
|
37
37
|
task.options += ["--display-cop-names", "--no-color"]
|
38
38
|
end
|
39
39
|
rescue LoadError
|
40
|
-
puts "
|
40
|
+
puts "chefstyle is not available. gem install chefstyle to do style checking."
|
41
41
|
end
|
42
42
|
|
43
43
|
desc "Run all quality tasks"
|
data/lib/kitchen/configurable.rb
CHANGED
@@ -309,7 +309,7 @@ module Kitchen
|
|
309
309
|
end
|
310
310
|
|
311
311
|
def env_wrapped(code)
|
312
|
-
code_parts =
|
312
|
+
code_parts = resolve_proxy_settings_from_config
|
313
313
|
code_parts << shell_env_var("TEST_KITCHEN", 1)
|
314
314
|
code_parts << shell_env_var("CI", ENV["CI"]) if ENV["CI"]
|
315
315
|
code_parts << code
|
@@ -317,7 +317,7 @@ module Kitchen
|
|
317
317
|
end
|
318
318
|
|
319
319
|
def proxy_setting_keys
|
320
|
-
[:http_proxy, :https_proxy, :ftp_proxy]
|
320
|
+
[:http_proxy, :https_proxy, :ftp_proxy, :no_proxy]
|
321
321
|
end
|
322
322
|
|
323
323
|
def resolve_proxy_settings_from_config
|
@@ -331,19 +331,6 @@ module Kitchen
|
|
331
331
|
end
|
332
332
|
end
|
333
333
|
|
334
|
-
def proxy_settings
|
335
|
-
env = resolve_proxy_settings_from_config
|
336
|
-
|
337
|
-
# if http_proxy was set from environment variable or https_proxy was set
|
338
|
-
# from environment variable, or ftp_proxy was set from environment
|
339
|
-
# variable, include no_proxy environment variable, if set.
|
340
|
-
if !proxy_from_config? && proxy_from_environment?
|
341
|
-
env << shell_env_var("no_proxy", ENV["no_proxy"]) if ENV["no_proxy"]
|
342
|
-
env << shell_env_var("NO_PROXY", ENV["NO_PROXY"]) if ENV["NO_PROXY"]
|
343
|
-
end
|
344
|
-
env
|
345
|
-
end
|
346
|
-
|
347
334
|
def proxy_from_config?
|
348
335
|
proxy_setting_keys.any? do |protocol|
|
349
336
|
!config[protocol].nil?
|
@@ -67,6 +67,10 @@ module Kitchen
|
|
67
67
|
# to ease upgrades, allow the user to turn deprecation warnings into errors
|
68
68
|
default_config :deprecations_as_errors, false
|
69
69
|
|
70
|
+
default_config :multiple_converge, 1
|
71
|
+
|
72
|
+
default_config :enforce_idempotency, false
|
73
|
+
|
70
74
|
default_config :data_path do |provisioner|
|
71
75
|
provisioner.calculate_path("data")
|
72
76
|
end
|
@@ -150,6 +154,10 @@ module Kitchen
|
|
150
154
|
|
151
155
|
private
|
152
156
|
|
157
|
+
def last_exit_code
|
158
|
+
"; exit $LastExitCode" if powershell_shell?
|
159
|
+
end
|
160
|
+
|
153
161
|
# @return [Hash] an option hash for the install commands
|
154
162
|
# @api private
|
155
163
|
def install_options
|
@@ -393,6 +401,90 @@ module Kitchen
|
|
393
401
|
"#{policyfile}"
|
394
402
|
end
|
395
403
|
end
|
404
|
+
|
405
|
+
# Writes a configuration file to the sandbox directory.
|
406
|
+
# @api private
|
407
|
+
def prepare_config_rb
|
408
|
+
data = default_config_rb.merge(config[config_filename.tr(".", "_").to_sym])
|
409
|
+
data = data.merge(:named_run_list => config[:named_run_list]) if config[:named_run_list]
|
410
|
+
|
411
|
+
info("Preparing #{config_filename}")
|
412
|
+
debug("Creating #{config_filename} from #{data.inspect}")
|
413
|
+
|
414
|
+
File.open(File.join(sandbox_path, config_filename), "wb") do |file|
|
415
|
+
file.write(format_config_file(data))
|
416
|
+
end
|
417
|
+
|
418
|
+
prepare_config_idempotency_check if config[:enforce_idempotency]
|
419
|
+
end
|
420
|
+
|
421
|
+
# Writes a configuration file to the sandbox directory
|
422
|
+
# to check for idempotency of the run.
|
423
|
+
# @api private
|
424
|
+
def prepare_config_idempotency_check
|
425
|
+
handler_filename = "chef-client-fail-if-update-handler.rb"
|
426
|
+
source = File.join(
|
427
|
+
File.dirname(__FILE__), %w{.. .. .. support }, handler_filename
|
428
|
+
)
|
429
|
+
FileUtils.cp(source, File.join(sandbox_path, handler_filename))
|
430
|
+
File.open(File.join(sandbox_path, "client_no_updated_resources.rb"), "wb") do |file|
|
431
|
+
file.write(format_config_file(data))
|
432
|
+
file.write("\n\n")
|
433
|
+
file.write("handler_file = File.join(File.dirname(__FILE__), '#{handler_filename}')\n")
|
434
|
+
file.write "Chef::Config.from_file(handler_file)\n"
|
435
|
+
end
|
436
|
+
end
|
437
|
+
|
438
|
+
# Returns an Array of command line arguments for the chef client.
|
439
|
+
#
|
440
|
+
# @return [Array<String>] an array of command line arguments
|
441
|
+
# @api private
|
442
|
+
def chef_args(_config_filename)
|
443
|
+
raise "You must override in sub classes!"
|
444
|
+
end
|
445
|
+
|
446
|
+
# Returns a filename for the configuration file
|
447
|
+
# defaults to client.rb
|
448
|
+
#
|
449
|
+
# @return [String] a filename
|
450
|
+
# @api private
|
451
|
+
def config_filename
|
452
|
+
"client.rb"
|
453
|
+
end
|
454
|
+
|
455
|
+
# Gives the command used to run chef
|
456
|
+
# @api private
|
457
|
+
def chef_cmd(base_cmd)
|
458
|
+
if windows_os?
|
459
|
+
separator = [
|
460
|
+
"; if ($LastExitCode -ne 0) { ",
|
461
|
+
"throw \"Command failed with exit code $LastExitCode.\" } ;",
|
462
|
+
].join
|
463
|
+
else
|
464
|
+
separator = " && "
|
465
|
+
end
|
466
|
+
chef_cmds(base_cmd).join(separator)
|
467
|
+
end
|
468
|
+
|
469
|
+
# Gives an array of command
|
470
|
+
# @api private
|
471
|
+
def chef_cmds(base_cmd)
|
472
|
+
cmd = prefix_command(wrap_shell_code(
|
473
|
+
[base_cmd, *chef_args(config_filename), last_exit_code].join(" ").
|
474
|
+
tap { |str| str.insert(0, reload_ps1_path) if windows_os? }
|
475
|
+
))
|
476
|
+
|
477
|
+
cmds = [cmd].cycle(config[:multiple_converge].to_i).to_a
|
478
|
+
|
479
|
+
if config[:enforce_idempotency]
|
480
|
+
idempotent_cmd = prefix_command(wrap_shell_code(
|
481
|
+
[base_cmd, *chef_args("client_no_updated_resources.rb"), last_exit_code].join(" ").
|
482
|
+
tap { |str| str.insert(0, reload_ps1_path) if windows_os? }
|
483
|
+
))
|
484
|
+
cmds[-1] = idempotent_cmd
|
485
|
+
end
|
486
|
+
cmds
|
487
|
+
end
|
396
488
|
end
|
397
489
|
end
|
398
490
|
end
|
@@ -36,10 +36,15 @@ module Kitchen
|
|
36
36
|
.tap { |path| path.concat(".bat") if provisioner.windows_os? }
|
37
37
|
end
|
38
38
|
|
39
|
+
# (see Base#config_filename)
|
40
|
+
def config_filename
|
41
|
+
"solo.rb"
|
42
|
+
end
|
43
|
+
|
39
44
|
# (see Base#create_sandbox)
|
40
45
|
def create_sandbox
|
41
46
|
super
|
42
|
-
|
47
|
+
prepare_config_rb
|
43
48
|
end
|
44
49
|
|
45
50
|
def modern?
|
@@ -58,13 +63,23 @@ module Kitchen
|
|
58
63
|
end
|
59
64
|
|
60
65
|
# (see Base#run_command)
|
61
|
-
# rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity, Metrics/AbcSize
|
62
66
|
def run_command
|
63
67
|
config[:log_level] = "info" if !modern? && config[:log_level] = "auto"
|
64
68
|
cmd = sudo(config[:chef_solo_path]).dup
|
65
69
|
.tap { |str| str.insert(0, "& ") if powershell_shell? }
|
70
|
+
|
71
|
+
chef_cmd(cmd)
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
# Returns an Array of command line arguments for the chef client.
|
77
|
+
#
|
78
|
+
# @return [Array<String>] an array of command line arguments
|
79
|
+
# @api private
|
80
|
+
def chef_args(solo_rb_filename)
|
66
81
|
args = [
|
67
|
-
"--config #{remote_path_join(config[:root_path],
|
82
|
+
"--config #{remote_path_join(config[:root_path], solo_rb_filename)}",
|
68
83
|
"--log_level #{config[:log_level]}",
|
69
84
|
"--no-color",
|
70
85
|
"--json-attributes #{remote_path_join(config[:root_path], 'dna.json')}",
|
@@ -74,28 +89,7 @@ module Kitchen
|
|
74
89
|
args << "--profile-ruby" if config[:profile_ruby]
|
75
90
|
args << "--legacy-mode" if config[:legacy_mode]
|
76
91
|
|
77
|
-
|
78
|
-
wrap_shell_code(
|
79
|
-
[cmd, *args].join(" ")
|
80
|
-
.tap { |str| str.insert(0, reload_ps1_path) if windows_os? }
|
81
|
-
)
|
82
|
-
)
|
83
|
-
end
|
84
|
-
|
85
|
-
private
|
86
|
-
|
87
|
-
# Writes a solo.rb configuration file to the sandbox directory.
|
88
|
-
#
|
89
|
-
# @api private
|
90
|
-
def prepare_solo_rb
|
91
|
-
data = default_config_rb.merge(config[:solo_rb])
|
92
|
-
|
93
|
-
info("Preparing solo.rb")
|
94
|
-
debug("Creating solo.rb from #{data.inspect}")
|
95
|
-
|
96
|
-
File.open(File.join(sandbox_path, "solo.rb"), "wb") do |file|
|
97
|
-
file.write(format_config_file(data))
|
98
|
-
end
|
92
|
+
args
|
99
93
|
end
|
100
94
|
end
|
101
95
|
end
|
@@ -50,7 +50,7 @@ module Kitchen
|
|
50
50
|
super
|
51
51
|
prepare_chef_client_zero_rb
|
52
52
|
prepare_validation_pem
|
53
|
-
|
53
|
+
prepare_config_rb
|
54
54
|
end
|
55
55
|
|
56
56
|
# (see Base#prepare_command)
|
@@ -71,20 +71,11 @@ module Kitchen
|
|
71
71
|
def run_command
|
72
72
|
cmd = modern? ? local_mode_command : shim_command
|
73
73
|
|
74
|
-
|
75
|
-
wrap_shell_code(
|
76
|
-
[cmd, *chef_client_args, last_exit_code].join(" ")
|
77
|
-
.tap { |str| str.insert(0, reload_ps1_path) if windows_os? }
|
78
|
-
)
|
79
|
-
)
|
74
|
+
chef_cmd(cmd)
|
80
75
|
end
|
81
76
|
|
82
77
|
private
|
83
78
|
|
84
|
-
def last_exit_code
|
85
|
-
"; exit $LastExitCode" if powershell_shell?
|
86
|
-
end
|
87
|
-
|
88
79
|
# Adds optional flags to a chef-client command, depending on
|
89
80
|
# configuration data. Note that this method mutates the incoming Array.
|
90
81
|
#
|
@@ -115,10 +106,10 @@ module Kitchen
|
|
115
106
|
#
|
116
107
|
# @return [Array<String>] an array of command line arguments
|
117
108
|
# @api private
|
118
|
-
def
|
109
|
+
def chef_args(client_rb_filename)
|
119
110
|
level = config[:log_level]
|
120
111
|
args = [
|
121
|
-
"--config #{remote_path_join(config[:root_path],
|
112
|
+
"--config #{remote_path_join(config[:root_path], client_rb_filename)}",
|
122
113
|
"--log_level #{level}",
|
123
114
|
"--force-formatter",
|
124
115
|
"--no-color",
|
@@ -200,21 +191,6 @@ module Kitchen
|
|
200
191
|
FileUtils.cp(source, File.join(sandbox_path, "chef-client-zero.rb"))
|
201
192
|
end
|
202
193
|
|
203
|
-
# Writes a client.rb configuration file to the sandbox directory.
|
204
|
-
#
|
205
|
-
# @api private
|
206
|
-
def prepare_client_rb
|
207
|
-
data = default_config_rb.merge(config[:client_rb])
|
208
|
-
data = data.merge(named_run_list: config[:named_run_list]) if config[:named_run_list]
|
209
|
-
|
210
|
-
info("Preparing client.rb")
|
211
|
-
debug("Creating client.rb from #{data.inspect}")
|
212
|
-
|
213
|
-
File.open(File.join(sandbox_path, "client.rb"), "wb") do |file|
|
214
|
-
file.write(format_config_file(data))
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
194
|
# Writes a fake (but valid) validation.pem into the sandbox directory.
|
219
195
|
#
|
220
196
|
# @api private
|
@@ -416,6 +416,10 @@ module Kitchen
|
|
416
416
|
opts[:auth_methods] = ["publickey"]
|
417
417
|
end
|
418
418
|
|
419
|
+
if data[:ssh_key_only]
|
420
|
+
opts[:auth_methods] = ["publickey"]
|
421
|
+
end
|
422
|
+
|
419
423
|
opts[:password] = data[:password] if data.key?(:password)
|
420
424
|
opts[:forward_agent] = data[:forward_agent] if data.key?(:forward_agent)
|
421
425
|
opts[:verbose] = data[:verbose].to_sym if data.key?(:verbose)
|
data/lib/kitchen/version.rb
CHANGED
@@ -767,6 +767,7 @@ describe Kitchen::Configurable do
|
|
767
767
|
config[:http_proxy] = "http://proxy"
|
768
768
|
config[:https_proxy] = "https://proxy"
|
769
769
|
config[:ftp_proxy] = "ftp://proxy"
|
770
|
+
config[:no_proxy] = "http://no"
|
770
771
|
|
771
772
|
cmd.must_equal(outdent!(<<-CODE.chomp))
|
772
773
|
sh -c '
|
@@ -776,6 +777,8 @@ describe Kitchen::Configurable do
|
|
776
777
|
HTTPS_PROXY="https://proxy"; export HTTPS_PROXY
|
777
778
|
ftp_proxy="ftp://proxy"; export ftp_proxy
|
778
779
|
FTP_PROXY="ftp://proxy"; export FTP_PROXY
|
780
|
+
no_proxy="http://no"; export no_proxy
|
781
|
+
NO_PROXY="http://no"; export NO_PROXY
|
779
782
|
TEST_KITCHEN="1"; export TEST_KITCHEN
|
780
783
|
mkdir foo
|
781
784
|
'
|
@@ -313,6 +313,18 @@ describe Kitchen::Provisioner::ChefSolo do
|
|
313
313
|
cmd.must_match(/'\Z/)
|
314
314
|
end
|
315
315
|
|
316
|
+
it "contains a standard second run if multiple_converge is set to 2" do
|
317
|
+
config[:multiple_converge] = 2
|
318
|
+
cmd.must_match(/chef-solo.*&&.*chef-solo.*/m)
|
319
|
+
cmd.wont_match(/chef-solo.*&&.*chef-solo.*client_no_updated_resources.rb/m)
|
320
|
+
end
|
321
|
+
|
322
|
+
it "contains a specific second run if enforce_idempotency is set" do
|
323
|
+
config[:multiple_converge] = 2
|
324
|
+
config[:enforce_idempotency] = true
|
325
|
+
cmd.must_match(/chef-solo.*&&.*chef-solo.*client_no_updated_resources.rb/m)
|
326
|
+
end
|
327
|
+
|
316
328
|
it "exports http_proxy & HTTP_PROXY when :http_proxy is set" do
|
317
329
|
config[:http_proxy] = "http://proxy"
|
318
330
|
|
@@ -454,6 +466,18 @@ describe Kitchen::Provisioner::ChefSolo do
|
|
454
466
|
platform.stubs(:os_type).returns("windows")
|
455
467
|
end
|
456
468
|
|
469
|
+
it "contains a standard second run if multiple_converge is set to 2" do
|
470
|
+
config[:multiple_converge] = 2
|
471
|
+
cmd.must_match(/chef-solo.*;.*chef-solo.*/m)
|
472
|
+
cmd.wont_match(/chef-solo.*;.*chef-solo.*client_no_updated_resources.rb/m)
|
473
|
+
end
|
474
|
+
|
475
|
+
it "contains a specific second run if enforce_idempotency is set" do
|
476
|
+
config[:multiple_converge] = 2
|
477
|
+
config[:enforce_idempotency] = true
|
478
|
+
cmd.must_match(/chef-solo.*;.*chef-solo.*client_no_updated_resources.rb/m)
|
479
|
+
end
|
480
|
+
|
457
481
|
it "exports http_proxy & HTTP_PROXY when :http_proxy is set" do
|
458
482
|
config[:http_proxy] = "http://proxy"
|
459
483
|
|
@@ -700,6 +700,18 @@ describe Kitchen::Provisioner::ChefZero do
|
|
700
700
|
cmd.must_match(/'\Z/)
|
701
701
|
end
|
702
702
|
|
703
|
+
it "contains a standard second run if multiple_converge is set to 2" do
|
704
|
+
config[:multiple_converge] = 2
|
705
|
+
cmd.must_match(/chef-client.*&&.*chef-client.*/m)
|
706
|
+
cmd.wont_match(/chef-client.*&&.*chef-client.*client_no_updated_resources.rb/m)
|
707
|
+
end
|
708
|
+
|
709
|
+
it "contains a specific second run if enforce_idempotency is set" do
|
710
|
+
config[:multiple_converge] = 2
|
711
|
+
config[:enforce_idempotency] = true
|
712
|
+
cmd.must_match(/chef-client.*&&.*chef-client.*client_no_updated_resources.rb/m)
|
713
|
+
end
|
714
|
+
|
703
715
|
it "exports http_proxy & HTTP_PROXY when :http_proxy is set" do
|
704
716
|
config[:http_proxy] = "http://proxy"
|
705
717
|
|
@@ -763,6 +775,18 @@ describe Kitchen::Provisioner::ChefZero do
|
|
763
775
|
common_shell_specs
|
764
776
|
common_modern_shell_specs
|
765
777
|
|
778
|
+
it "contains a standard second run if multiple_converge is set to 2" do
|
779
|
+
config[:multiple_converge] = 2
|
780
|
+
cmd.must_match(/chef-client.*;.*chef-client.*/m)
|
781
|
+
cmd.wont_match(/chef-client.*;.*chef-client.*client_no_updated_resources.rb/m)
|
782
|
+
end
|
783
|
+
|
784
|
+
it "contains a specific second run if enforce_idempotency is set" do
|
785
|
+
config[:multiple_converge] = 2
|
786
|
+
config[:enforce_idempotency] = true
|
787
|
+
cmd.must_match(/chef-client.*;.*chef-client.*client_no_updated_resources.rb/m)
|
788
|
+
end
|
789
|
+
|
766
790
|
it "exports http_proxy & HTTP_PROXY when :http_proxy is set" do
|
767
791
|
config[:http_proxy] = "http://proxy"
|
768
792
|
|
data/spec/kitchen/ssh_spec.rb
CHANGED
@@ -20,6 +20,7 @@ require_relative "../spec_helper"
|
|
20
20
|
|
21
21
|
require "kitchen/ssh"
|
22
22
|
require "tmpdir"
|
23
|
+
require "net/ssh/test"
|
23
24
|
|
24
25
|
# Hack to sort results in `Dir.entries` only within the yielded block, to limit
|
25
26
|
# the "behavior pollution" to other code. This was needed for Net::SCP, as
|
@@ -50,67 +51,6 @@ def with_sorted_dir_entries
|
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
53
|
-
# Terrible hack to deal with Net::SSH:Test::Extensions which monkey patches
|
54
|
-
# `IO.select` with a version for testing Net::SSH code. Unfortunetly this
|
55
|
-
# impacts other code, so we'll "un-patch" this after each spec and "re-patch"
|
56
|
-
# it before the next one.
|
57
|
-
require "net/ssh/test"
|
58
|
-
def depatch_io
|
59
|
-
IO.class_exec do
|
60
|
-
class << self
|
61
|
-
alias_method :select, :select_for_real
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
# We need to immediately call depatch so that `IO.select` is in a good state
|
66
|
-
# _right now_. The require immediately monkeypatches it and we only want
|
67
|
-
# it monkey patched inside each ssh test
|
68
|
-
depatch_io
|
69
|
-
|
70
|
-
def repatch_io
|
71
|
-
IO.class_exec do
|
72
|
-
class << self
|
73
|
-
alias_method :select, :select_for_test
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
# Major hack-and-a-half to add basic `Channel#request_pty` support to
|
79
|
-
# Net::SSH's testing framework. The `Net::SSH::Test::LocalPacket` does not
|
80
|
-
# recognize the `"pty-req"` request type, so bombs out whenever this channel
|
81
|
-
# request is sent.
|
82
|
-
#
|
83
|
-
# This "make-work" fix adds a method (`#sends_request_pty`) which works just
|
84
|
-
# like `#sends_exec` expcept that it enqueues a patched subclass of
|
85
|
-
# `LocalPacket` which can deal with the `"pty-req"` type.
|
86
|
-
#
|
87
|
-
# An upstream patch to Net::SSH will be required to retire this yak shave ;)
|
88
|
-
require "net/ssh/test/channel"
|
89
|
-
module Net
|
90
|
-
module SSH
|
91
|
-
module Test
|
92
|
-
class Channel
|
93
|
-
def sends_request_pty
|
94
|
-
pty_data = ["xterm", 80, 24, 640, 480, "\0"]
|
95
|
-
|
96
|
-
script.events << Class.new(Net::SSH::Test::LocalPacket) do
|
97
|
-
def types # rubocop:disable Lint/NestedMethodDefinition
|
98
|
-
if @type == 98 && @data[1] == "pty-req"
|
99
|
-
@types ||= [
|
100
|
-
:long, :string, :bool, :string,
|
101
|
-
:long, :long, :long, :long, :string
|
102
|
-
]
|
103
|
-
else
|
104
|
-
super
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end.new(:channel_request, remote_id, "pty-req", false, *pty_data)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
54
|
describe Kitchen::SSH do
|
115
55
|
include Net::SSH::Test
|
116
56
|
|
@@ -118,19 +58,14 @@ describe Kitchen::SSH do
|
|
118
58
|
let(:logger) { Logger.new(logged_output) }
|
119
59
|
let(:opts) { Hash.new }
|
120
60
|
let(:ssh) { Kitchen::SSH.new("foo", "me", opts) }
|
121
|
-
let(:conn) { connection }
|
61
|
+
let(:conn) { Net::SSH::Test::Extensions::IO.with_test_extension { connection } }
|
122
62
|
|
123
63
|
before do
|
124
|
-
repatch_io
|
125
64
|
logger.level = Logger::DEBUG
|
126
65
|
opts[:logger] = logger
|
127
66
|
Net::SSH.stubs(:start).returns(conn)
|
128
67
|
end
|
129
68
|
|
130
|
-
after do
|
131
|
-
depatch_io
|
132
|
-
end
|
133
|
-
|
134
69
|
describe "establishing a connection" do
|
135
70
|
[
|
136
71
|
Errno::EACCES, Errno::EADDRINUSE, Errno::ECONNREFUSED,
|
@@ -293,7 +228,7 @@ describe Kitchen::SSH do
|
|
293
228
|
end
|
294
229
|
|
295
230
|
it "raises an SSHFailed exception" do
|
296
|
-
err = proc { ssh.exec("doit") }.must_raise Kitchen::SSHFailed
|
231
|
+
err = proc { assert_scripted { ssh.exec("doit") } }.must_raise Kitchen::SSHFailed
|
297
232
|
err.message.must_equal "SSH exited (42) for command: [doit]"
|
298
233
|
end
|
299
234
|
end
|
@@ -479,8 +414,10 @@ describe Kitchen::SSH do
|
|
479
414
|
it "shuts down the connection when block closes" do
|
480
415
|
conn.expects(:shutdown!)
|
481
416
|
|
482
|
-
|
483
|
-
|
417
|
+
Net::SSH::Test::Extensions::IO.with_test_extension do
|
418
|
+
Kitchen::SSH.new("foo", "me", opts) do |ssh|
|
419
|
+
ssh.exec("doit")
|
420
|
+
end
|
484
421
|
end
|
485
422
|
end
|
486
423
|
end
|
@@ -576,16 +513,18 @@ describe Kitchen::SSH do
|
|
576
513
|
it "returns a truthy value" do
|
577
514
|
TCPSocket.stubs(:new).returns(tcp_socket)
|
578
515
|
|
579
|
-
|
580
|
-
|
581
|
-
|
516
|
+
Net::SSH::Test::Extensions::IO.with_test_extension do
|
517
|
+
result = ssh.send(:test_ssh)
|
518
|
+
result.wont_equal nil
|
519
|
+
result.wont_equal false
|
520
|
+
end
|
582
521
|
end
|
583
522
|
|
584
523
|
it "closes socket when finished" do
|
585
524
|
TCPSocket.stubs(:new).returns(tcp_socket)
|
586
525
|
tcp_socket.expects(:close)
|
587
526
|
|
588
|
-
ssh.send(:test_ssh)
|
527
|
+
Net::SSH::Test::Extensions::IO.with_test_extension { ssh.send(:test_ssh) }
|
589
528
|
end
|
590
529
|
|
591
530
|
[
|
@@ -631,7 +570,7 @@ describe Kitchen::SSH do
|
|
631
570
|
|
632
571
|
it "logs to info for each retry" do
|
633
572
|
TCPSocket.stubs(:new).returns(not_ready, not_ready, ready)
|
634
|
-
ssh.wait
|
573
|
+
Net::SSH::Test::Extensions::IO.with_test_extension { ssh.wait }
|
635
574
|
|
636
575
|
logged_output.string.lines.count do |l|
|
637
576
|
l =~ info_line_with("Waiting for foo:22...")
|
@@ -19,6 +19,7 @@
|
|
19
19
|
require_relative "../../spec_helper"
|
20
20
|
|
21
21
|
require "kitchen/transport/ssh"
|
22
|
+
require "net/ssh/test"
|
22
23
|
|
23
24
|
# Hack to sort results in `Dir.entries` only within the yielded block, to limit
|
24
25
|
# the "behavior pollution" to other code. This was needed for Net::SCP, as
|
@@ -49,67 +50,6 @@ def with_sorted_dir_entries
|
|
49
50
|
end
|
50
51
|
end
|
51
52
|
|
52
|
-
# Terrible hack to deal with Net::SSH:Test::Extensions which monkey patches
|
53
|
-
# `IO.select` with a version for testing Net::SSH code. Unfortunetly this
|
54
|
-
# impacts other code, so we'll "un-patch" this after each spec and "re-patch"
|
55
|
-
# it before the next one.
|
56
|
-
require "net/ssh/test"
|
57
|
-
def depatch_io
|
58
|
-
IO.class_exec do
|
59
|
-
class << self
|
60
|
-
alias_method :select, :select_for_real
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
# We need to immediately call depatch so that `IO.select` is in a good state
|
65
|
-
# _right now_. The require immediately monkeypatches it and we only want
|
66
|
-
# it monkey patched inside each ssh test
|
67
|
-
depatch_io
|
68
|
-
|
69
|
-
def repatch_io
|
70
|
-
IO.class_exec do
|
71
|
-
class << self
|
72
|
-
alias_method :select, :select_for_test
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
# Major hack-and-a-half to add basic `Channel#request_pty` support to
|
78
|
-
# Net::SSH's testing framework. The `Net::SSH::Test::LocalPacket` does not
|
79
|
-
# recognize the `"pty-req"` request type, so bombs out whenever this channel
|
80
|
-
# request is sent.
|
81
|
-
#
|
82
|
-
# This "make-work" fix adds a method (`#sends_request_pty`) which works just
|
83
|
-
# like `#sends_exec` expcept that it enqueues a patched subclass of
|
84
|
-
# `LocalPacket` which can deal with the `"pty-req"` type.
|
85
|
-
#
|
86
|
-
# An upstream patch to Net::SSH will be required to retire this yak shave ;)
|
87
|
-
require "net/ssh/test/channel"
|
88
|
-
module Net
|
89
|
-
module SSH
|
90
|
-
module Test
|
91
|
-
class Channel
|
92
|
-
def sends_request_pty
|
93
|
-
pty_data = ["xterm", 80, 24, 640, 480, "\0"]
|
94
|
-
|
95
|
-
script.events << Class.new(Net::SSH::Test::LocalPacket) do
|
96
|
-
def types # rubocop:disable Lint/NestedMethodDefinition
|
97
|
-
if @type == 98 && @data[1] == "pty-req"
|
98
|
-
@types ||= [
|
99
|
-
:long, :string, :bool, :string,
|
100
|
-
:long, :long, :long, :long, :string
|
101
|
-
]
|
102
|
-
else
|
103
|
-
super
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end.new(:channel_request, remote_id, "pty-req", false, *pty_data)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
53
|
describe Kitchen::Transport::Ssh do
|
114
54
|
let(:logged_output) { StringIO.new }
|
115
55
|
let(:logger) { Logger.new(logged_output) }
|
@@ -121,7 +61,7 @@ describe Kitchen::Transport::Ssh do
|
|
121
61
|
end
|
122
62
|
|
123
63
|
let(:transport) do
|
124
|
-
Kitchen::Transport::Ssh.new(config).finalize_config!(instance)
|
64
|
+
Net::SSH::Test::Extensions::IO.with_test_extension { Kitchen::Transport::Ssh.new(config).finalize_config!(instance) }
|
125
65
|
end
|
126
66
|
|
127
67
|
it "provisioner api_version is 1" do
|
@@ -195,6 +135,10 @@ describe Kitchen::Transport::Ssh do
|
|
195
135
|
transport[:ssh_key].must_equal nil
|
196
136
|
end
|
197
137
|
|
138
|
+
it "sets :ssh_key_only to nil by default" do
|
139
|
+
transport[:ssh_key_only].must_equal nil
|
140
|
+
end
|
141
|
+
|
198
142
|
it "expands :ssh_path path if set" do
|
199
143
|
config[:kitchen_root] = "/rooty"
|
200
144
|
config[:ssh_key] = "my_key"
|
@@ -582,6 +526,16 @@ describe Kitchen::Transport::Ssh do
|
|
582
526
|
make_connection
|
583
527
|
end
|
584
528
|
|
529
|
+
it "sets :auth_methods to only publickey if :ssh_key_only is set in config" do
|
530
|
+
config[:ssh_key_only] = true
|
531
|
+
|
532
|
+
klass.expects(:new).with do |hash|
|
533
|
+
hash[:auth_methods] == ["publickey"]
|
534
|
+
end
|
535
|
+
|
536
|
+
make_connection
|
537
|
+
end
|
538
|
+
|
585
539
|
it "passes in :password if set in config" do
|
586
540
|
config[:password] = "password_from_config"
|
587
541
|
|
@@ -697,7 +651,7 @@ describe Kitchen::Transport::Ssh::Connection do
|
|
697
651
|
|
698
652
|
let(:logged_output) { StringIO.new }
|
699
653
|
let(:logger) { Logger.new(logged_output) }
|
700
|
-
let(:conn) { net_ssh_connection }
|
654
|
+
let(:conn) { Net::SSH::Test::Extensions::IO.with_test_extension { net_ssh_connection } }
|
701
655
|
|
702
656
|
let(:options) do
|
703
657
|
{
|
@@ -714,15 +668,10 @@ describe Kitchen::Transport::Ssh::Connection do
|
|
714
668
|
end
|
715
669
|
|
716
670
|
before do
|
717
|
-
repatch_io
|
718
671
|
logger.level = Logger::DEBUG
|
719
672
|
Net::SSH.stubs(:start).returns(conn)
|
720
673
|
end
|
721
674
|
|
722
|
-
after do
|
723
|
-
depatch_io
|
724
|
-
end
|
725
|
-
|
726
675
|
describe "establishing a connection" do
|
727
676
|
[
|
728
677
|
Errno::EACCES, Errno::EADDRINUSE, Errno::ECONNREFUSED, Errno::ETIMEDOUT,
|
@@ -938,14 +887,14 @@ describe Kitchen::Transport::Ssh::Connection do
|
|
938
887
|
|
939
888
|
it "raises an SshFailed exception" do
|
940
889
|
err = proc do
|
941
|
-
connection.execute("doit")
|
890
|
+
assert_scripted { connection.execute("doit") }
|
942
891
|
end.must_raise Kitchen::Transport::SshFailed
|
943
892
|
err.message.must_equal "SSH exited (42) for command: [doit]"
|
944
893
|
end
|
945
894
|
|
946
895
|
it "returns the exit code with an SshFailed exception" do
|
947
896
|
begin
|
948
|
-
connection.execute("doit")
|
897
|
+
assert_scripted { connection.execute("doit") }
|
949
898
|
rescue Kitchen::Transport::SshFailed => e
|
950
899
|
e.exit_code.must_equal 42
|
951
900
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Handler to kill the run if any resource is updated
|
2
|
+
class UpdatedResources < ::Chef::Handler
|
3
|
+
def report
|
4
|
+
if updated_resources.size > 0
|
5
|
+
puts "First chef run should have reached a converged state."
|
6
|
+
puts "Resources updated in a second chef-client run:"
|
7
|
+
updated_resources.each do |r|
|
8
|
+
puts "- #{r}"
|
9
|
+
end
|
10
|
+
# exit 203 # chef handler catch Exception instead of StandardException
|
11
|
+
Process.kill("KILL", Process.pid)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
report_handlers << UpdatedResources.new
|
data/test-kitchen.gemspec
CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do |gem|
|
|
28
28
|
gem.add_dependency "net-ssh", ">= 2.9", "< 5.0"
|
29
29
|
gem.add_dependency "net-ssh-gateway", "~> 1.2"
|
30
30
|
gem.add_dependency "safe_yaml", "~> 1.0"
|
31
|
-
gem.add_dependency "thor", "~> 0.
|
31
|
+
gem.add_dependency "thor", "~> 0.19", "< 0.19.2"
|
32
32
|
gem.add_dependency "mixlib-install", ">= 1.2", "< 3.0"
|
33
33
|
|
34
34
|
gem.add_development_dependency "pry"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: test-kitchen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fletcher Nichol
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-03-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mixlib-shellout
|
@@ -98,14 +98,20 @@ dependencies:
|
|
98
98
|
requirements:
|
99
99
|
- - "~>"
|
100
100
|
- !ruby/object:Gem::Version
|
101
|
-
version: '0.
|
101
|
+
version: '0.19'
|
102
|
+
- - "<"
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: 0.19.2
|
102
105
|
type: :runtime
|
103
106
|
prerelease: false
|
104
107
|
version_requirements: !ruby/object:Gem::Requirement
|
105
108
|
requirements:
|
106
109
|
- - "~>"
|
107
110
|
- !ruby/object:Gem::Version
|
108
|
-
version: '0.
|
111
|
+
version: '0.19'
|
112
|
+
- - "<"
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: 0.19.2
|
109
115
|
- !ruby/object:Gem::Dependency
|
110
116
|
name: mixlib-install
|
111
117
|
requirement: !ruby/object:Gem::Requirement
|
@@ -584,6 +590,7 @@ files:
|
|
584
590
|
- spec/support/powershell_max_size_spec.rb
|
585
591
|
- support/busser_install_command.ps1
|
586
592
|
- support/busser_install_command.sh
|
593
|
+
- support/chef-client-fail-if-update-handler.rb
|
587
594
|
- support/chef-client-zero.rb
|
588
595
|
- support/chef_base_init_command.ps1
|
589
596
|
- support/chef_base_init_command.sh
|
@@ -634,7 +641,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
634
641
|
version: '0'
|
635
642
|
requirements: []
|
636
643
|
rubyforge_project:
|
637
|
-
rubygems_version: 2.6.
|
644
|
+
rubygems_version: 2.6.10
|
638
645
|
signing_key:
|
639
646
|
specification_version: 4
|
640
647
|
summary: Test Kitchen is an integration tool for developing and testing infrastructure
|