test-kitchen 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/CHANGELOG.md +977 -863
- data/CONTRIBUTING.md +3 -6
- data/Rakefile +9 -0
- data/lib/kitchen/command/driver_discover.rb +10 -4
- data/lib/kitchen/driver/ssh_base.rb +4 -0
- data/lib/kitchen/instance.rb +19 -1
- data/lib/kitchen/platform.rb +8 -2
- data/lib/kitchen/provisioner/base.rb +10 -2
- data/lib/kitchen/provisioner/chef_apply.rb +125 -0
- data/lib/kitchen/provisioner/chef_base.rb +12 -5
- data/lib/kitchen/transport/winrm.rb +36 -148
- data/lib/kitchen/version.rb +1 -1
- data/spec/kitchen/provisioner/base_spec.rb +33 -0
- data/spec/kitchen/provisioner/chef_apply_spec.rb +136 -0
- data/spec/kitchen/provisioner/chef_base_spec.rb +11 -5
- data/spec/kitchen/ssh_spec.rb +6 -3
- data/spec/kitchen/transport/ssh_spec.rb +6 -4
- data/spec/kitchen/transport/winrm_spec.rb +70 -254
- data/spec/kitchen/verifier/shell_spec.rb +1 -0
- data/test-kitchen.gemspec +3 -3
- data/testing_windows.md +37 -0
- metadata +25 -27
data/lib/kitchen/version.rb
CHANGED
@@ -330,6 +330,39 @@ describe Kitchen::Provisioner::Base do
|
|
330
330
|
end
|
331
331
|
end
|
332
332
|
|
333
|
+
describe "#sudo_command" do
|
334
|
+
|
335
|
+
describe "with :sudo set" do
|
336
|
+
|
337
|
+
before { config[:sudo] = true }
|
338
|
+
|
339
|
+
it "returns the default sudo_command" do
|
340
|
+
provisioner.send(:sudo_command).must_equal("sudo -E")
|
341
|
+
end
|
342
|
+
|
343
|
+
it "returns the custom sudo_command" do
|
344
|
+
config[:sudo_command] = "mysudo"
|
345
|
+
|
346
|
+
provisioner.send(:sudo_command).must_equal("mysudo")
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
describe "with :sudo falsey" do
|
351
|
+
|
352
|
+
before { config[:sudo] = false }
|
353
|
+
|
354
|
+
it "returns empty string for default sudo_command" do
|
355
|
+
provisioner.send(:sudo_command).must_equal("")
|
356
|
+
end
|
357
|
+
|
358
|
+
it "returns empty string for custom sudo_command" do
|
359
|
+
config[:sudo_command] = "mysudo"
|
360
|
+
|
361
|
+
provisioner.send(:sudo_command).must_equal("")
|
362
|
+
end
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
333
366
|
describe "#prefix_command" do
|
334
367
|
|
335
368
|
describe "with :command_prefix set" do
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Author:: SAWANOBORI Yukihiko <sawanoboriyu@higanworks.com>)
|
4
|
+
#
|
5
|
+
# Copyright (C) 2015, HiganWorks LLC
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
18
|
+
|
19
|
+
require_relative "../../spec_helper"
|
20
|
+
|
21
|
+
require "kitchen"
|
22
|
+
require "kitchen/provisioner/chef_apply"
|
23
|
+
|
24
|
+
describe Kitchen::Provisioner::ChefApply do
|
25
|
+
|
26
|
+
let(:logged_output) { StringIO.new }
|
27
|
+
let(:logger) { Logger.new(logged_output) }
|
28
|
+
let(:platform) { stub(:os_type => nil) }
|
29
|
+
let(:suite) { stub(:name => "fries") }
|
30
|
+
|
31
|
+
let(:config) do
|
32
|
+
{ :test_base_path => "/b", :kitchen_root => "/r", :log_level => :info }
|
33
|
+
end
|
34
|
+
|
35
|
+
let(:instance) do
|
36
|
+
stub(
|
37
|
+
:name => "coolbeans",
|
38
|
+
:logger => logger,
|
39
|
+
:suite => suite,
|
40
|
+
:platform => platform
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
let(:provisioner) do
|
45
|
+
Kitchen::Provisioner::ChefApply.new(config).finalize_config!(instance)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "provisioner api_version is 2" do
|
49
|
+
provisioner.diagnose_plugin[:api_version].must_equal 2
|
50
|
+
end
|
51
|
+
|
52
|
+
it "plugin_version is set to Kitchen::VERSION" do
|
53
|
+
provisioner.diagnose_plugin[:version].must_equal Kitchen::VERSION
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "default config" do
|
57
|
+
|
58
|
+
it "sets :chef_apply_path to a path using :chef_omnibus_root" do
|
59
|
+
config[:chef_omnibus_root] = "/nice/place"
|
60
|
+
|
61
|
+
provisioner[:chef_apply_path].must_equal "/nice/place/bin/chef-apply"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "#create_sandbox" do
|
66
|
+
|
67
|
+
before do
|
68
|
+
@root = Dir.mktmpdir
|
69
|
+
config[:kitchen_root] = @root
|
70
|
+
end
|
71
|
+
|
72
|
+
after do
|
73
|
+
FileUtils.remove_entry(@root)
|
74
|
+
begin
|
75
|
+
provisioner.cleanup_sandbox
|
76
|
+
rescue # rubocop:disable Lint/HandleExceptions
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#run_command" do
|
82
|
+
|
83
|
+
before do
|
84
|
+
config[:run_list] = %w[appry_recipe1 appry_recipe2]
|
85
|
+
end
|
86
|
+
|
87
|
+
let(:cmd) { provisioner.run_command }
|
88
|
+
|
89
|
+
describe "for bourne shells" do
|
90
|
+
|
91
|
+
before { platform.stubs(:shell_type).returns("bourne") }
|
92
|
+
|
93
|
+
it "uses bourne shell" do
|
94
|
+
cmd.must_match(/\Ash -c '$/)
|
95
|
+
cmd.must_match(/'\Z/)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "uses sudo for chef-apply when configured" do
|
99
|
+
config[:chef_omnibus_root] = "/c"
|
100
|
+
config[:sudo] = true
|
101
|
+
|
102
|
+
cmd.must_match regexify("sudo -E /c/bin/chef-apply apply/appry_recipe1.rb ", :partial_line)
|
103
|
+
cmd.must_match regexify("sudo -E /c/bin/chef-apply apply/appry_recipe2.rb ", :partial_line)
|
104
|
+
end
|
105
|
+
|
106
|
+
it "does not use sudo for chef-apply when configured" do
|
107
|
+
config[:chef_omnibus_root] = "/c"
|
108
|
+
config[:sudo] = false
|
109
|
+
|
110
|
+
cmd.must_match regexify("chef-apply apply/appry_recipe1.rb ", :partial_line)
|
111
|
+
cmd.must_match regexify("chef-apply apply/appry_recipe2.rb ", :partial_line)
|
112
|
+
cmd.wont_match regexify("sudo -E /c/bin/chef-apply ")
|
113
|
+
end
|
114
|
+
|
115
|
+
it "sets log level flag on chef-apply to auto by default" do
|
116
|
+
cmd.must_match regexify(" --log_level auto", :partial_line)
|
117
|
+
end
|
118
|
+
|
119
|
+
it "set log level flag for custom level" do
|
120
|
+
config[:log_level] = :extreme
|
121
|
+
|
122
|
+
cmd.must_match regexify(" --log_level extreme", :partial_line)
|
123
|
+
end
|
124
|
+
|
125
|
+
it "sets no color flag on chef-apply" do
|
126
|
+
cmd.must_match regexify(" --no-color", :partial_line)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def regexify(str, line = :whole_line)
|
132
|
+
r = Regexp.escape(str)
|
133
|
+
r = "^\s*#{r}$" if line == :whole_line
|
134
|
+
Regexp.new(r)
|
135
|
+
end
|
136
|
+
end
|
@@ -150,8 +150,8 @@ describe Kitchen::Provisioner::ChefBase do
|
|
150
150
|
|
151
151
|
let(:install_opts) {
|
152
152
|
{ :omnibus_url => "https://www.chef.io/chef/install.sh",
|
153
|
-
:project => nil, :install_flags => nil, :
|
154
|
-
:https_proxy => nil }
|
153
|
+
:project => nil, :install_flags => nil, :sudo_command => "sudo -E",
|
154
|
+
:http_proxy => nil, :https_proxy => nil }
|
155
155
|
}
|
156
156
|
|
157
157
|
it "returns nil if :require_chef_omnibus is falsey" do
|
@@ -323,17 +323,21 @@ describe Kitchen::Provisioner::ChefBase do
|
|
323
323
|
it "prepends sudo for sh commands when :sudo is set" do
|
324
324
|
config[:sudo] = true
|
325
325
|
config[:sudo_command] = "my_sudo_command"
|
326
|
+
install_opts_clone = install_opts.clone
|
327
|
+
install_opts_clone[:sudo_command] = config[:sudo_command]
|
326
328
|
|
327
329
|
Mixlib::Install.expects(:new).
|
328
|
-
with(default_version, false,
|
330
|
+
with(default_version, false, install_opts_clone).returns(installer)
|
329
331
|
cmd.must_equal "my_sudo_command my_install_command"
|
330
332
|
end
|
331
333
|
|
332
334
|
it "does not sudo for sh commands when :sudo is falsey" do
|
333
335
|
config[:sudo] = false
|
334
336
|
|
337
|
+
install_opts_clone = install_opts.clone
|
338
|
+
install_opts_clone[:sudo_command] = ""
|
335
339
|
Mixlib::Install.expects(:new).
|
336
|
-
with(default_version, false,
|
340
|
+
with(default_version, false, install_opts_clone).returns(installer)
|
337
341
|
cmd.must_equal "my_install_command"
|
338
342
|
end
|
339
343
|
end
|
@@ -347,8 +351,10 @@ describe Kitchen::Provisioner::ChefBase do
|
|
347
351
|
end
|
348
352
|
|
349
353
|
it "sets the powershell flag for Mixlib::Install" do
|
354
|
+
install_opts_clone = install_opts.clone
|
355
|
+
install_opts_clone[:sudo_command] = ""
|
350
356
|
Mixlib::Install.expects(:new).
|
351
|
-
with("", true,
|
357
|
+
with("", true, install_opts_clone).returns(installer)
|
352
358
|
cmd
|
353
359
|
end
|
354
360
|
end
|
data/spec/kitchen/ssh_spec.rb
CHANGED
@@ -18,7 +18,6 @@
|
|
18
18
|
|
19
19
|
require_relative "../spec_helper"
|
20
20
|
|
21
|
-
require "net/ssh/test"
|
22
21
|
require "kitchen/ssh"
|
23
22
|
require "tmpdir"
|
24
23
|
|
@@ -55,7 +54,7 @@ end
|
|
55
54
|
# `IO.select` with a version for testing Net::SSH code. Unfortunetly this
|
56
55
|
# impacts other code, so we'll "un-patch" this after each spec and "re-patch"
|
57
56
|
# it before the next one.
|
58
|
-
|
57
|
+
require "net/ssh/test"
|
59
58
|
def depatch_io
|
60
59
|
IO.class_exec do
|
61
60
|
class << self
|
@@ -63,6 +62,10 @@ def depatch_io
|
|
63
62
|
end
|
64
63
|
end
|
65
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
|
66
69
|
|
67
70
|
def repatch_io
|
68
71
|
IO.class_exec do
|
@@ -82,7 +85,7 @@ end
|
|
82
85
|
# `LocalPacket` which can deal with the `"pty-req"` type.
|
83
86
|
#
|
84
87
|
# An upstream patch to Net::SSH will be required to retire this yak shave ;)
|
85
|
-
|
88
|
+
require "net/ssh/test/channel"
|
86
89
|
module Net
|
87
90
|
|
88
91
|
module SSH
|
@@ -18,8 +18,6 @@
|
|
18
18
|
|
19
19
|
require_relative "../../spec_helper"
|
20
20
|
|
21
|
-
require "net/ssh/test"
|
22
|
-
|
23
21
|
require "kitchen/transport/ssh"
|
24
22
|
|
25
23
|
# Hack to sort results in `Dir.entries` only within the yielded block, to limit
|
@@ -55,7 +53,7 @@ end
|
|
55
53
|
# `IO.select` with a version for testing Net::SSH code. Unfortunetly this
|
56
54
|
# impacts other code, so we'll "un-patch" this after each spec and "re-patch"
|
57
55
|
# it before the next one.
|
58
|
-
|
56
|
+
require "net/ssh/test"
|
59
57
|
def depatch_io
|
60
58
|
IO.class_exec do
|
61
59
|
class << self
|
@@ -63,6 +61,10 @@ def depatch_io
|
|
63
61
|
end
|
64
62
|
end
|
65
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
|
66
68
|
|
67
69
|
def repatch_io
|
68
70
|
IO.class_exec do
|
@@ -82,7 +84,7 @@ end
|
|
82
84
|
# `LocalPacket` which can deal with the `"pty-req"` type.
|
83
85
|
#
|
84
86
|
# An upstream patch to Net::SSH will be required to retire this yak shave ;)
|
85
|
-
|
87
|
+
require "net/ssh/test/channel"
|
86
88
|
module Net
|
87
89
|
|
88
90
|
module SSH
|
@@ -20,9 +20,7 @@ require_relative "../../spec_helper"
|
|
20
20
|
|
21
21
|
require "kitchen/transport/winrm"
|
22
22
|
require "winrm"
|
23
|
-
require "winrm
|
24
|
-
require "winrm/transport/shell_closer"
|
25
|
-
require "winrm/transport/file_transporter"
|
23
|
+
require "winrm-fs"
|
26
24
|
|
27
25
|
module Kitchen
|
28
26
|
|
@@ -107,8 +105,8 @@ describe Kitchen::Transport::Winrm do
|
|
107
105
|
transport[:max_wait_until_ready].must_equal 600
|
108
106
|
end
|
109
107
|
|
110
|
-
it "sets :winrm_transport to :
|
111
|
-
transport[:winrm_transport].must_equal :
|
108
|
+
it "sets :winrm_transport to :negotiate" do
|
109
|
+
transport[:winrm_transport].must_equal :negotiate
|
112
110
|
end
|
113
111
|
end
|
114
112
|
|
@@ -150,25 +148,17 @@ describe Kitchen::Transport::Winrm do
|
|
150
148
|
make_connection
|
151
149
|
end
|
152
150
|
|
153
|
-
it "sets the :winrm_transport to :
|
151
|
+
it "sets the :winrm_transport to :negotiate" do
|
154
152
|
klass.expects(:new).with do |hash|
|
155
|
-
hash[:winrm_transport] == :
|
153
|
+
hash[:winrm_transport] == :negotiate
|
156
154
|
end
|
157
155
|
|
158
156
|
make_connection
|
159
157
|
end
|
160
158
|
|
161
|
-
it "sets the :disable_sspi to
|
159
|
+
it "sets the :disable_sspi to false" do
|
162
160
|
klass.expects(:new).with do |hash|
|
163
|
-
hash[:disable_sspi] ==
|
164
|
-
end
|
165
|
-
|
166
|
-
make_connection
|
167
|
-
end
|
168
|
-
|
169
|
-
it "sets the :basic_auth_only to true" do
|
170
|
-
klass.expects(:new).with do |hash|
|
171
|
-
hash[:basic_auth_only] == true
|
161
|
+
hash[:disable_sspi] == false
|
172
162
|
end
|
173
163
|
|
174
164
|
make_connection
|
@@ -336,42 +326,20 @@ describe Kitchen::Transport::Winrm do
|
|
336
326
|
make_connection
|
337
327
|
end
|
338
328
|
|
339
|
-
describe "when
|
329
|
+
describe "when negotiate is set in config" do
|
340
330
|
before do
|
341
|
-
config[:winrm_transport] = "
|
331
|
+
config[:winrm_transport] = "negotiate"
|
342
332
|
end
|
343
333
|
|
344
|
-
|
345
|
-
before do
|
346
|
-
RbConfig::CONFIG.stubs(:[]).with("host_os").returns("mingw32")
|
347
|
-
end
|
348
|
-
|
349
|
-
it "sets :winrm_transport to sspinegotiate on Windows" do
|
350
|
-
|
351
|
-
klass.expects(:new).with do |hash|
|
352
|
-
hash[:winrm_transport] == :sspinegotiate &&
|
353
|
-
hash[:disable_sspi] == false &&
|
354
|
-
hash[:basic_auth_only] == false
|
355
|
-
end
|
334
|
+
it "sets :winrm_transport to negotiate" do
|
356
335
|
|
357
|
-
|
336
|
+
klass.expects(:new).with do |hash|
|
337
|
+
hash[:winrm_transport] == :negotiate &&
|
338
|
+
hash[:disable_sspi] == false &&
|
339
|
+
hash[:basic_auth_only] == false
|
358
340
|
end
|
359
|
-
end
|
360
341
|
|
361
|
-
|
362
|
-
before do
|
363
|
-
RbConfig::CONFIG.stubs(:[]).with("host_os").returns("darwin14")
|
364
|
-
end
|
365
|
-
|
366
|
-
it "sets :winrm_transport to plaintext" do
|
367
|
-
klass.expects(:new).with do |hash|
|
368
|
-
hash[:winrm_transport] == :plaintext &&
|
369
|
-
hash[:disable_sspi] == true &&
|
370
|
-
hash[:basic_auth_only] == true
|
371
|
-
end
|
372
|
-
|
373
|
-
make_connection
|
374
|
-
end
|
342
|
+
make_connection
|
375
343
|
end
|
376
344
|
end
|
377
345
|
|
@@ -438,48 +406,46 @@ describe Kitchen::Transport::Winrm do
|
|
438
406
|
end
|
439
407
|
|
440
408
|
describe "#load_needed_dependencies" do
|
441
|
-
describe "winrm-
|
409
|
+
describe "winrm-fs" do
|
442
410
|
before do
|
443
|
-
# force loading of winrm-
|
444
|
-
require "winrm
|
411
|
+
# force loading of winrm-fs to get the version constant
|
412
|
+
require "winrm-fs"
|
445
413
|
end
|
446
414
|
|
447
415
|
it "logs a message to debug that code will be loaded" do
|
448
|
-
transport.stubs(:require)
|
449
416
|
transport
|
450
417
|
|
451
418
|
logged_output.string.must_match debug_line_with(
|
452
|
-
"
|
419
|
+
"winrm-fs requested, loading winrm-fs gem")
|
453
420
|
end
|
454
421
|
|
455
422
|
it "logs a message to debug when library is initially loaded" do
|
456
423
|
transport = Kitchen::Transport::Winrm.new(config)
|
457
|
-
transport.stubs(:require)
|
458
|
-
transport.stubs(:
|
459
|
-
|
424
|
+
transport.stubs(:require).with("winrm", anything)
|
425
|
+
transport.stubs(:require).with("winrm-fs").returns(true)
|
460
426
|
transport.finalize_config!(instance)
|
461
427
|
|
462
428
|
logged_output.string.must_match(
|
463
|
-
/
|
429
|
+
/winrm-fs is loaded/
|
464
430
|
)
|
465
431
|
end
|
466
432
|
|
467
433
|
it "logs a message to debug when library is previously loaded" do
|
468
434
|
transport = Kitchen::Transport::Winrm.new(config)
|
469
|
-
transport.stubs(:require)
|
470
|
-
transport.stubs(:
|
471
|
-
|
435
|
+
transport.stubs(:require).with("winrm", anything)
|
436
|
+
transport.stubs(:require).with("winrm-fs").returns(false)
|
472
437
|
transport.finalize_config!(instance)
|
473
438
|
|
474
439
|
logged_output.string.must_match(
|
475
|
-
/
|
440
|
+
/winrm-fs was already loaded/
|
476
441
|
)
|
477
442
|
end
|
478
443
|
|
479
444
|
it "logs a message to fatal when libraries cannot be loaded" do
|
480
445
|
transport = Kitchen::Transport::Winrm.new(config)
|
481
|
-
transport.stubs(:require)
|
482
|
-
transport.stubs(:
|
446
|
+
transport.stubs(:require).with("winrm", anything)
|
447
|
+
transport.stubs(:require).with("winrm-fs").
|
448
|
+
raises(LoadError, "uh oh")
|
483
449
|
begin
|
484
450
|
transport.finalize_config!(instance)
|
485
451
|
rescue # rubocop:disable Lint/HandleExceptions
|
@@ -487,64 +453,61 @@ describe Kitchen::Transport::Winrm do
|
|
487
453
|
end
|
488
454
|
|
489
455
|
logged_output.string.must_match fatal_line_with(
|
490
|
-
"The `winrm-
|
456
|
+
"The `winrm-fs` gem is missing and must be installed")
|
491
457
|
end
|
492
458
|
|
493
459
|
it "raises a UserError when libraries cannot be loaded" do
|
494
460
|
transport = Kitchen::Transport::Winrm.new(config)
|
495
|
-
transport.stubs(:require)
|
496
|
-
transport.stubs(:
|
461
|
+
transport.stubs(:require).with("winrm", anything)
|
462
|
+
transport.stubs(:require).with("winrm-fs").
|
463
|
+
raises(LoadError, "uh oh")
|
497
464
|
|
498
465
|
err = proc {
|
499
466
|
transport.finalize_config!(instance)
|
500
467
|
}.must_raise Kitchen::UserError
|
501
|
-
err.message.must_match(/^Could not load or activate winrm-
|
468
|
+
err.message.must_match(/^Could not load or activate winrm-fs\. /)
|
502
469
|
end
|
503
470
|
end
|
504
471
|
|
505
|
-
describe "winrm
|
506
|
-
before do
|
507
|
-
RbConfig::CONFIG.stubs(:[]).with("host_os").returns("mingw32")
|
508
|
-
end
|
509
|
-
|
472
|
+
describe "winrm" do
|
510
473
|
it "logs a message to debug that code will be loaded" do
|
511
474
|
transport = Kitchen::Transport::Winrm.new(config)
|
512
|
-
transport.stubs(:
|
475
|
+
transport.stubs(:require).with("winrm-fs", anything)
|
513
476
|
transport.stubs(:require)
|
514
477
|
transport.finalize_config!(instance)
|
515
478
|
|
516
479
|
logged_output.string.must_match debug_line_with(
|
517
|
-
"
|
480
|
+
"winrm requested, loading winrm gem")
|
518
481
|
end
|
519
482
|
|
520
483
|
it "logs a message to debug when library is initially loaded" do
|
521
484
|
transport = Kitchen::Transport::Winrm.new(config)
|
522
|
-
transport.stubs(:
|
523
|
-
transport.stubs(:
|
485
|
+
transport.stubs(:require).with("winrm-fs", anything)
|
486
|
+
transport.stubs(:require).returns(true)
|
524
487
|
|
525
488
|
transport.finalize_config!(instance)
|
526
489
|
|
527
490
|
logged_output.string.must_match(
|
528
|
-
/winrm
|
491
|
+
/winrm is loaded/
|
529
492
|
)
|
530
493
|
end
|
531
494
|
|
532
495
|
it "logs a message to debug when library is previously loaded" do
|
533
496
|
transport = Kitchen::Transport::Winrm.new(config)
|
534
|
-
transport.stubs(:
|
535
|
-
transport.stubs(:
|
497
|
+
transport.stubs(:require).with("winrm-fs", anything)
|
498
|
+
transport.stubs(:require).returns(false)
|
536
499
|
|
537
500
|
transport.finalize_config!(instance)
|
538
501
|
|
539
502
|
logged_output.string.must_match(
|
540
|
-
/winrm
|
503
|
+
/winrm was already loaded/
|
541
504
|
)
|
542
505
|
end
|
543
506
|
|
544
507
|
it "logs a message to fatal when libraries cannot be loaded" do
|
545
508
|
transport = Kitchen::Transport::Winrm.new(config)
|
546
|
-
transport.stubs(:
|
547
|
-
transport.stubs(:
|
509
|
+
transport.stubs(:require).with("winrm-fs", anything)
|
510
|
+
transport.stubs(:require).raises(LoadError, "uh oh")
|
548
511
|
begin
|
549
512
|
transport.finalize_config!(instance)
|
550
513
|
rescue # rubocop:disable Lint/HandleExceptions
|
@@ -552,18 +515,18 @@ describe Kitchen::Transport::Winrm do
|
|
552
515
|
end
|
553
516
|
|
554
517
|
logged_output.string.must_match fatal_line_with(
|
555
|
-
"The `winrm
|
518
|
+
"The `winrm` gem is missing and must be installed")
|
556
519
|
end
|
557
520
|
|
558
521
|
it "raises a UserError when libraries cannot be loaded" do
|
559
522
|
transport = Kitchen::Transport::Winrm.new(config)
|
560
|
-
transport.stubs(:
|
561
|
-
transport.stubs(:
|
523
|
+
transport.stubs(:require).with("winrm-fs", anything)
|
524
|
+
transport.stubs(:require).raises(LoadError, "uh oh")
|
562
525
|
|
563
526
|
err = proc {
|
564
527
|
transport.finalize_config!(instance)
|
565
528
|
}.must_raise Kitchen::UserError
|
566
|
-
err.message.must_match(/^Could not load or activate winrm
|
529
|
+
err.message.must_match(/^Could not load or activate winrm\. /)
|
567
530
|
end
|
568
531
|
end
|
569
532
|
end
|
@@ -602,7 +565,7 @@ describe Kitchen::Transport::Winrm::Connection do
|
|
602
565
|
|
603
566
|
let(:executor) do
|
604
567
|
s = mock("command_executor")
|
605
|
-
s.responds_like_instance_of(WinRM::
|
568
|
+
s.responds_like_instance_of(WinRM::CommandExecutor)
|
606
569
|
s
|
607
570
|
end
|
608
571
|
|
@@ -611,6 +574,8 @@ describe Kitchen::Transport::Winrm::Connection do
|
|
611
574
|
end
|
612
575
|
|
613
576
|
before do
|
577
|
+
WinRM::WinRMWebService.stubs(:new).returns(winrm_session)
|
578
|
+
winrm_session.stubs(:logger=)
|
614
579
|
logger.level = Logger::DEBUG
|
615
580
|
end
|
616
581
|
|
@@ -624,29 +589,12 @@ describe Kitchen::Transport::Winrm::Connection do
|
|
624
589
|
end
|
625
590
|
|
626
591
|
before do
|
627
|
-
|
628
|
-
# disable finalizer as service is a fake anyway
|
629
|
-
ObjectSpace.stubs(:define_finalizer).
|
630
|
-
with { |obj, _| obj.class == Kitchen::Transport::Winrm::Connection }
|
631
|
-
executor.stubs(:open).returns("shell-123")
|
632
|
-
executor.stubs(:shell).returns("shell-123")
|
592
|
+
winrm_session.stubs(:create_executor).returns(executor)
|
633
593
|
executor.stubs(:close)
|
634
594
|
executor.stubs(:run_powershell_script).
|
635
595
|
with("doit").yields("ok\n", nil).returns(response)
|
636
596
|
end
|
637
597
|
|
638
|
-
it "logger displays closing connection on debug" do
|
639
|
-
connection.execute("doit")
|
640
|
-
connection.close
|
641
|
-
|
642
|
-
logged_output.string.must_match debug_line(
|
643
|
-
"[WinRM] closing remote shell shell-123 on #{info}"
|
644
|
-
)
|
645
|
-
logged_output.string.must_match debug_line(
|
646
|
-
"[WinRM] remote shell shell-123 closed"
|
647
|
-
)
|
648
|
-
end
|
649
|
-
|
650
598
|
it "only closes the shell once for multiple calls" do
|
651
599
|
executor.expects(:close).once
|
652
600
|
|
@@ -660,10 +608,7 @@ describe Kitchen::Transport::Winrm::Connection do
|
|
660
608
|
describe "#execute" do
|
661
609
|
|
662
610
|
before do
|
663
|
-
|
664
|
-
# disable finalizer as service is a fake anyway
|
665
|
-
ObjectSpace.stubs(:define_finalizer).
|
666
|
-
with { |obj, _| obj.class == Kitchen::Transport::Winrm::Connection }
|
611
|
+
winrm_session.stubs(:create_executor).returns(executor)
|
667
612
|
end
|
668
613
|
|
669
614
|
describe "for a successful command" do
|
@@ -679,7 +624,6 @@ describe Kitchen::Transport::Winrm::Connection do
|
|
679
624
|
end
|
680
625
|
|
681
626
|
before do
|
682
|
-
executor.expects(:open).returns("shell-123")
|
683
627
|
executor.expects(:run_powershell_script).
|
684
628
|
with("doit").yields("ok\n", nil).returns(response)
|
685
629
|
end
|
@@ -691,17 +635,6 @@ describe Kitchen::Transport::Winrm::Connection do
|
|
691
635
|
"[WinRM] #{info} (doit)")
|
692
636
|
end
|
693
637
|
|
694
|
-
it "logger displays establishing connection on debug" do
|
695
|
-
connection.execute("doit")
|
696
|
-
|
697
|
-
logged_output.string.must_match debug_line(
|
698
|
-
"[WinRM] opening remote shell on #{info}"
|
699
|
-
)
|
700
|
-
logged_output.string.must_match debug_line(
|
701
|
-
"[WinRM] remote shell shell-123 is open on #{info}"
|
702
|
-
)
|
703
|
-
end
|
704
|
-
|
705
638
|
it "logger captures stdout" do
|
706
639
|
connection.execute("doit")
|
707
640
|
|
@@ -741,10 +674,9 @@ describe Kitchen::Transport::Winrm::Connection do
|
|
741
674
|
end
|
742
675
|
|
743
676
|
before do
|
744
|
-
executor.expects(:
|
745
|
-
|
746
|
-
|
747
|
-
yields("ok\n", nil).returns(response)
|
677
|
+
executor.expects(:run_powershell_script).with(
|
678
|
+
%{powershell -ExecutionPolicy Bypass -File "$env:TEMP/kitchen/coolbeans-long_script.ps1"}
|
679
|
+
).yields("ok\n", nil).returns(response)
|
748
680
|
end
|
749
681
|
|
750
682
|
it "uploads the long command" do
|
@@ -786,12 +718,11 @@ describe Kitchen::Transport::Winrm::Connection do
|
|
786
718
|
end
|
787
719
|
|
788
720
|
before do
|
789
|
-
executor.expects(:open).returns("shell-123")
|
790
721
|
executor.expects(:run_powershell_script).
|
791
722
|
with("doit").yields("nope\n", nil).returns(response)
|
792
723
|
end
|
793
724
|
|
794
|
-
# rubocop:disable Metrics/MethodLength
|
725
|
+
# rubocop:disable Metrics/MethodLength
|
795
726
|
def self.common_failed_command_specs
|
796
727
|
it "logger displays command on debug" do
|
797
728
|
begin
|
@@ -805,21 +736,6 @@ describe Kitchen::Transport::Winrm::Connection do
|
|
805
736
|
)
|
806
737
|
end
|
807
738
|
|
808
|
-
it "logger displays establishing connection on debug" do
|
809
|
-
begin
|
810
|
-
connection.execute("doit")
|
811
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
812
|
-
# the raise is not what is being tested here, rather its side-effect
|
813
|
-
end
|
814
|
-
|
815
|
-
logged_output.string.must_match debug_line(
|
816
|
-
"[WinRM] opening remote shell on #{info}"
|
817
|
-
)
|
818
|
-
logged_output.string.must_match debug_line(
|
819
|
-
"[WinRM] remote shell shell-123 is open on #{info}"
|
820
|
-
)
|
821
|
-
end
|
822
|
-
|
823
739
|
it "logger captures stdout" do
|
824
740
|
begin
|
825
741
|
connection.execute("doit")
|
@@ -854,7 +770,7 @@ MSG
|
|
854
770
|
end
|
855
771
|
end
|
856
772
|
end
|
857
|
-
# rubocop:enable Metrics/MethodLength
|
773
|
+
# rubocop:enable Metrics/MethodLength
|
858
774
|
|
859
775
|
describe "when a non-zero exit code is returned" do
|
860
776
|
|
@@ -897,64 +813,12 @@ MSG
|
|
897
813
|
|
898
814
|
options[:connection_retries] = 3
|
899
815
|
options[:connection_retry_sleep] = 7
|
900
|
-
|
901
|
-
executor.stubs(:open).raises(k)
|
816
|
+
winrm_session.stubs(:create_executor).raises(k)
|
902
817
|
end
|
903
818
|
|
904
819
|
it "reraises the #{klass} exception" do
|
905
820
|
proc { connection.execute("nope") }.must_raise klass
|
906
821
|
end
|
907
|
-
|
908
|
-
it "attempts to connect :connection_retries times" do
|
909
|
-
begin
|
910
|
-
connection.execute("nope")
|
911
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
912
|
-
# the raise is not what is being tested here, rather its side-effect
|
913
|
-
end
|
914
|
-
|
915
|
-
logged_output.string.lines.count { |l|
|
916
|
-
l =~ debug_line("[WinRM] opening remote shell on #{info}")
|
917
|
-
}.must_equal 3
|
918
|
-
logged_output.string.lines.count { |l|
|
919
|
-
l =~ debug_line("[WinRM] remote shell shell-123 is open on #{info}")
|
920
|
-
}.must_equal 0
|
921
|
-
end
|
922
|
-
|
923
|
-
it "sleeps for :connection_retry_sleep seconds between retries" do
|
924
|
-
connection.unstub(:sleep)
|
925
|
-
connection.expects(:sleep).with(7).twice
|
926
|
-
|
927
|
-
begin
|
928
|
-
connection.execute("nope")
|
929
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
930
|
-
# the raise is not what is being tested here, rather its side-effect
|
931
|
-
end
|
932
|
-
end
|
933
|
-
|
934
|
-
it "logs the first 2 retry failures on info" do
|
935
|
-
begin
|
936
|
-
connection.execute("nope")
|
937
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
938
|
-
# the raise is not what is being tested here, rather its side-effect
|
939
|
-
end
|
940
|
-
|
941
|
-
logged_output.string.lines.count { |l|
|
942
|
-
l =~ info_line_with(
|
943
|
-
"[WinRM] connection failed, retrying in 7 seconds")
|
944
|
-
}.must_equal 2
|
945
|
-
end
|
946
|
-
|
947
|
-
it "logs the last retry failures on warn" do
|
948
|
-
begin
|
949
|
-
connection.execute("nope")
|
950
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
951
|
-
# the raise is not what is being tested here, rather its side-effect
|
952
|
-
end
|
953
|
-
|
954
|
-
logged_output.string.lines.count { |l|
|
955
|
-
l =~ warn_line_with("[WinRM] connection failed, terminating ")
|
956
|
-
}.must_equal 1
|
957
|
-
end
|
958
822
|
end
|
959
823
|
end
|
960
824
|
end
|
@@ -1131,38 +995,33 @@ MSG
|
|
1131
995
|
|
1132
996
|
let(:transporter) do
|
1133
997
|
t = mock("file_transporter")
|
1134
|
-
t.responds_like_instance_of(WinRM::
|
998
|
+
t.responds_like_instance_of(WinRM::FS::Core::FileTransporter)
|
1135
999
|
t
|
1136
1000
|
end
|
1137
1001
|
|
1138
1002
|
before do
|
1139
|
-
|
1140
|
-
ObjectSpace.stubs(:define_finalizer).
|
1141
|
-
with { |obj, _| obj.class == Kitchen::Transport::Winrm::Connection }
|
1003
|
+
winrm_session.stubs(:create_executor).returns(executor)
|
1142
1004
|
|
1143
|
-
WinRM::
|
1144
|
-
|
1145
|
-
|
1146
|
-
WinRM::Transport::FileTransporter.stubs(:new).
|
1147
|
-
with(executor, logger).returns(transporter)
|
1005
|
+
WinRM::FS::Core::FileTransporter.stubs(:new).
|
1006
|
+
with(executor).returns(transporter)
|
1148
1007
|
transporter.stubs(:upload)
|
1149
1008
|
end
|
1150
1009
|
|
1151
1010
|
def self.common_specs_for_upload
|
1152
1011
|
it "builds a Winrm::FileTransporter" do
|
1153
|
-
WinRM::
|
1012
|
+
WinRM::FS::Core::FileTransporter.unstub(:new)
|
1154
1013
|
|
1155
|
-
WinRM::
|
1156
|
-
with(executor
|
1014
|
+
WinRM::FS::Core::FileTransporter.expects(:new).
|
1015
|
+
with(executor).returns(transporter)
|
1157
1016
|
|
1158
1017
|
upload
|
1159
1018
|
end
|
1160
1019
|
|
1161
1020
|
it "reuses the Winrm::FileTransporter" do
|
1162
|
-
WinRM::
|
1021
|
+
WinRM::FS::Core::FileTransporter.unstub(:new)
|
1163
1022
|
|
1164
|
-
WinRM::
|
1165
|
-
with(executor
|
1023
|
+
WinRM::FS::Core::FileTransporter.expects(:new).
|
1024
|
+
with(executor).returns(transporter).once
|
1166
1025
|
|
1167
1026
|
upload
|
1168
1027
|
upload
|
@@ -1192,49 +1051,8 @@ MSG
|
|
1192
1051
|
describe "#wait_until_ready" do
|
1193
1052
|
|
1194
1053
|
before do
|
1195
|
-
|
1196
|
-
# disable finalizer as service is a fake anyway
|
1197
|
-
ObjectSpace.stubs(:define_finalizer).
|
1198
|
-
with { |obj, _| obj.class == Kitchen::Transport::Winrm::Connection }
|
1054
|
+
winrm_session.stubs(:create_executor).returns(executor)
|
1199
1055
|
options[:max_wait_until_ready] = 300
|
1200
|
-
connection.stubs(:sleep)
|
1201
|
-
end
|
1202
|
-
|
1203
|
-
describe "when failing to connect" do
|
1204
|
-
|
1205
|
-
before do
|
1206
|
-
executor.stubs(:open).raises(Errno::ECONNREFUSED)
|
1207
|
-
end
|
1208
|
-
|
1209
|
-
it "attempts to connect :max_wait_until_ready / 3 times if failing" do
|
1210
|
-
begin
|
1211
|
-
connection.wait_until_ready
|
1212
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
1213
|
-
# the raise is not what is being tested here, rather its side-effect
|
1214
|
-
end
|
1215
|
-
|
1216
|
-
logged_output.string.lines.count { |l|
|
1217
|
-
l =~ info_line_with(
|
1218
|
-
"Waiting for WinRM service on http://foo:5985/wsman, retrying in 3 seconds")
|
1219
|
-
}.must_equal((300 / 3) - 1)
|
1220
|
-
logged_output.string.lines.count { |l|
|
1221
|
-
l =~ debug_line_with("[WinRM] connection failed ")
|
1222
|
-
}.must_equal((300 / 3) - 1)
|
1223
|
-
logged_output.string.lines.count { |l|
|
1224
|
-
l =~ warn_line_with("[WinRM] connection failed, terminating ")
|
1225
|
-
}.must_equal 1
|
1226
|
-
end
|
1227
|
-
|
1228
|
-
it "sleeps for 3 seconds between retries" do
|
1229
|
-
connection.unstub(:sleep)
|
1230
|
-
connection.expects(:sleep).with(3).times((300 / 3) - 1)
|
1231
|
-
|
1232
|
-
begin
|
1233
|
-
connection.wait_until_ready
|
1234
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
1235
|
-
# the raise is not what is being tested here, rather its side-effect
|
1236
|
-
end
|
1237
|
-
end
|
1238
1056
|
end
|
1239
1057
|
|
1240
1058
|
describe "when connection is successful" do
|
@@ -1247,7 +1065,6 @@ MSG
|
|
1247
1065
|
end
|
1248
1066
|
|
1249
1067
|
before do
|
1250
|
-
executor.stubs(:open).returns("shell-123")
|
1251
1068
|
executor.expects(:run_powershell_script).
|
1252
1069
|
with("Write-Host '[WinRM] Established\n'").returns(response)
|
1253
1070
|
end
|
@@ -1267,7 +1084,6 @@ MSG
|
|
1267
1084
|
end
|
1268
1085
|
|
1269
1086
|
before do
|
1270
|
-
executor.stubs(:open).returns("shell-123")
|
1271
1087
|
executor.expects(:run_powershell_script).
|
1272
1088
|
with("Write-Host '[WinRM] Established\n'").returns(response)
|
1273
1089
|
end
|