test-kitchen 1.15.0 → 1.16.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|