test-kitchen 1.23.3 → 1.23.4
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/lib/kitchen/version.rb +1 -1
- data/support/chef-client-zero.rb +1 -1
- metadata +5 -324
- data/.gitattributes +0 -3
- data/.github/ISSUE_TEMPLATE.md +0 -56
- data/.github/lock.yml +0 -1
- data/.gitignore +0 -38
- data/.gitmodules +0 -0
- data/.kitchen.appveyor.yml +0 -25
- data/.kitchen.dokken.yml +0 -31
- data/.kitchen.proxy.yml +0 -27
- data/.rubocop.yml +0 -5
- data/.travis.yml +0 -57
- data/.yardopts +0 -3
- data/Berksfile +0 -3
- data/CHANGELOG.md +0 -1510
- data/CONTRIBUTING.md +0 -14
- data/ECOSYSTEM.md +0 -93
- data/Gemfile +0 -40
- data/Gemfile.proxy_tests +0 -4
- data/Guardfile +0 -42
- data/MAINTAINERS.md +0 -29
- data/README.md +0 -138
- data/RELEASE_NOTES.md +0 -167
- data/Rakefile +0 -77
- data/appveyor.yml +0 -47
- data/docs/CONTRIBUTING.md +0 -8
- data/docs/LICENSE +0 -22
- data/docs/README.md +0 -78
- data/docs/archetypes/default.md +0 -6
- data/docs/config.toml +0 -36
- data/docs/content/docs/_index.md +0 -5
- data/docs/content/docs/drivers/_index.md +0 -27
- data/docs/content/docs/drivers/azurerm.md +0 -44
- data/docs/content/docs/drivers/vagrant.md +0 -39
- data/docs/content/docs/getting-started/00-introduction.md +0 -14
- data/docs/content/docs/getting-started/01-installing.md +0 -64
- data/docs/content/docs/getting-started/02-getting-help.md +0 -59
- data/docs/content/docs/getting-started/03-creating-cookbook.md +0 -46
- data/docs/content/docs/getting-started/04-kitchen-yml.md +0 -56
- data/docs/content/docs/getting-started/05-instances.md +0 -79
- data/docs/content/docs/getting-started/06-writing-recipe.md +0 -21
- data/docs/content/docs/getting-started/07-running-converge.md +0 -134
- data/docs/content/docs/getting-started/08-manually-verifying.md +0 -55
- data/docs/content/docs/getting-started/09-writing-test.md +0 -49
- data/docs/content/docs/getting-started/10-running-verify.md +0 -120
- data/docs/content/docs/getting-started/11-running-test.md +0 -168
- data/docs/content/docs/getting-started/12-adding-platform.md +0 -206
- data/docs/content/docs/getting-started/13-adding-feature.md +0 -30
- data/docs/content/docs/getting-started/14-adding-suite.md +0 -60
- data/docs/content/docs/getting-started/15-adding-test.md +0 -66
- data/docs/content/docs/getting-started/16-adding-recipe.md +0 -53
- data/docs/content/docs/getting-started/17-excluding-platforms.md +0 -101
- data/docs/content/docs/getting-started/18-next-steps.md +0 -23
- data/docs/content/docs/getting-started/_index.md +0 -5
- data/docs/content/docs/provisioners/_index.md +0 -36
- data/docs/content/docs/provisioners/chef.md +0 -69
- data/docs/content/docs/provisioners/shell.md +0 -31
- data/docs/content/docs/reference/_index.md +0 -5
- data/docs/content/docs/reference/configuration.md +0 -53
- data/docs/content/docs/reference/examples.md +0 -97
- data/docs/content/docs/reference/faq.md +0 -58
- data/docs/content/docs/reference/fixtures.md +0 -32
- data/docs/content/docs/reference/glossary.md +0 -34
- data/docs/content/docs/reference/lifecycle-hooks.md +0 -68
- data/docs/content/docs/reference/reboots.md +0 -24
- data/docs/content/docs/verifiers/_index.md +0 -14
- data/docs/content/docs/verifiers/inspec.md +0 -44
- data/docs/content/docs/verifiers/serverspec.md +0 -20
- data/docs/static/images/chef-logo.png +0 -0
- data/docs/static/images/chef-logo.svg +0 -1
- data/docs/static/images/github-banner.png +0 -0
- data/docs/static/images/github-banner.svg +0 -71
- data/docs/static/images/kitchen-logo.png +0 -0
- data/docs/static/images/logo-block.svg +0 -222
- data/docs/static/images/logo.png +0 -0
- data/docs/static/images/logos-group.png +0 -0
- data/docs/static/images/terminal-1.png +0 -0
- data/docs/static/images/terminal-1.svg +0 -589
- data/docs/static/images/terminal-2.png +0 -0
- data/docs/static/images/terminal-2.svg +0 -235
- data/docs/static/images/terminal-3.png +0 -0
- data/docs/static/images/terminal-3.svg +0 -439
- data/docs/static/index.html +0 -59
- data/docs/static/javascripts/all.js +0 -348
- data/docs/static/javascripts/vendor/foundation.min.js +0 -4
- data/docs/static/javascripts/vendor/jquery.min.js +0 -5
- data/docs/static/javascripts/vendor/what-input.js +0 -336
- data/docs/static/stylesheets/site.css +0 -4667
- data/docs/themes/kitchen/layouts/_default/baseof.html +0 -53
- data/docs/themes/kitchen/layouts/_default/list.html +0 -4
- data/docs/themes/kitchen/layouts/_default/redirect.html +0 -10
- data/docs/themes/kitchen/layouts/_default/single.html +0 -6
- data/docs/themes/kitchen/layouts/partials/core/head.html +0 -6
- data/docs/themes/kitchen/layouts/partials/kitchen/footer.html +0 -18
- data/docs/themes/kitchen/layouts/partials/kitchen/head.html +0 -4
- data/docs/themes/kitchen/layouts/partials/kitchen/header.html +0 -26
- data/docs/themes/kitchen/layouts/partials/search-docs.html +0 -3
- data/docs/themes/kitchen/layouts/partials/sidebar.html +0 -33
- data/docs/themes/kitchen/layouts/shortcodes/button.html +0 -1
- data/docs/themes/kitchen/layouts/shortcodes/codeblock.html +0 -8
- data/docs/themes/kitchen/layouts/shortcodes/cta.html +0 -5
- data/docs/themes/kitchen/layouts/shortcodes/danger.html +0 -1
- data/docs/themes/kitchen/layouts/shortcodes/example_fqdn.html +0 -1
- data/docs/themes/kitchen/layouts/shortcodes/info.html +0 -1
- data/docs/themes/kitchen/layouts/shortcodes/ol-styled.html +0 -3
- data/docs/themes/kitchen/layouts/shortcodes/success.html +0 -1
- data/docs/themes/kitchen/layouts/shortcodes/tip.html +0 -1
- data/docs/themes/kitchen/layouts/shortcodes/warning.html +0 -1
- data/docs/themes/kitchen/static/css/kitchen.css +0 -10
- data/docs/themes/kitchen/static/css/kitchen.css.map +0 -7
- data/docs/themes/kitchen/static/fonts/Muli-Bold.ttf +0 -0
- data/docs/themes/kitchen/static/fonts/Muli-Regular.ttf +0 -0
- data/docs/themes/kitchen/static/fonts/Muli-SemiBold.ttf +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-brands-400.eot +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-brands-400.svg +0 -1104
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-brands-400.ttf +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-brands-400.woff +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-brands-400.woff2 +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-regular-400.eot +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-regular-400.svg +0 -372
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-regular-400.ttf +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-regular-400.woff +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-regular-400.woff2 +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-solid-900.eot +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-solid-900.svg +0 -1896
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-solid-900.ttf +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-solid-900.woff +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-solid-900.woff2 +0 -0
- data/docs/themes/kitchen/static/images/chef-logo-light.svg +0 -36
- data/docs/themes/kitchen/static/images/chef-logo-white.svg +0 -38
- data/docs/themes/kitchen/static/images/chef-logo.svg +0 -37
- data/docs/themes/kitchen/static/images/favicon.ico +0 -0
- data/docs/themes/kitchen/static/js/scripts-all.js +0 -7
- data/docs/themes/kitchen/static/js/source/chef-hugo.js +0 -116
- data/docs/themes/kitchen/static/js/source/omnitruck.js +0 -82
- data/docs/themes/kitchen/static/js/source/segment.js +0 -52
- data/docs/themes/kitchen/static/sass/_buttons.scss +0 -161
- data/docs/themes/kitchen/static/sass/_core.scss +0 -24
- data/docs/themes/kitchen/static/sass/_forms.scss +0 -14
- data/docs/themes/kitchen/static/sass/_mixins.scss +0 -133
- data/docs/themes/kitchen/static/sass/_typography.scss +0 -34
- data/docs/themes/kitchen/static/sass/_variables.scss +0 -82
- data/docs/themes/kitchen/static/sass/kitchen.scss +0 -7
- data/docs/themes/kitchen/static/sass/kitchen/_footer.scss +0 -50
- data/docs/themes/kitchen/static/sass/kitchen/_header.scss +0 -187
- data/docs/themes/kitchen/static/sass/kitchen/_homepage.scss +0 -27
- data/docs/themes/kitchen/static/sass/kitchen/_utility-bar.scss +0 -173
- data/docs/themes/kitchen/static/sass/partials/_alerts.scss +0 -32
- data/docs/themes/kitchen/static/sass/partials/_bg.scss +0 -19
- data/docs/themes/kitchen/static/sass/partials/_blurbs.scss +0 -25
- data/docs/themes/kitchen/static/sass/partials/_callout.scss +0 -15
- data/docs/themes/kitchen/static/sass/partials/_cards.scss +0 -54
- data/docs/themes/kitchen/static/sass/partials/_dropdown.scss +0 -77
- data/docs/themes/kitchen/static/sass/partials/_grid.scss +0 -87
- data/docs/themes/kitchen/static/sass/partials/_padding.scss +0 -73
- data/docs/themes/kitchen/static/sass/partials/_sidebar.scss +0 -71
- data/docs/themes/kitchen/static/sass/partials/_tabs.scss +0 -125
- data/docs/themes/kitchen/static/sass/typography/_chroma.scss +0 -366
- data/docs/themes/kitchen/static/sass/typography/_code.scss +0 -72
- data/docs/themes/kitchen/static/sass/typography/_headers.scss +0 -90
- data/docs/themes/kitchen/static/sass/typography/_links.scss +0 -127
- data/docs/themes/kitchen/static/sass/typography/_lists.scss +0 -155
- data/docs/themes/kitchen/static/sass/typography/_prose.scss +0 -29
- data/docs/themes/kitchen/static/sass/typography/_text.scss +0 -221
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_animated.scss +0 -20
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_bordered-pulled.scss +0 -20
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_core.scss +0 -16
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_fixed-width.scss +0 -6
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_icons.scss +0 -992
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_larger.scss +0 -23
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_list.scss +0 -18
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_mixins.scss +0 -57
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_rotated-flipped.scss +0 -23
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_screen-reader.scss +0 -5
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_stacked.scss +0 -31
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_variables.scss +0 -1005
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/fa-brands.scss +0 -21
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/fa-regular.scss +0 -22
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/fa-solid.scss +0 -23
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/fontawesome.scss +0 -16
- data/docs/themes/kitchen/theme.toml +0 -8
- data/features/kitchen_action_commands.feature +0 -164
- data/features/kitchen_command.feature +0 -16
- data/features/kitchen_console_command.feature +0 -35
- data/features/kitchen_defaults.feature +0 -38
- data/features/kitchen_diagnose_command.feature +0 -96
- data/features/kitchen_help_command.feature +0 -16
- data/features/kitchen_init_command.feature +0 -254
- data/features/kitchen_list_command.feature +0 -140
- data/features/kitchen_login_command.feature +0 -62
- data/features/kitchen_sink_command.feature +0 -30
- data/features/kitchen_test_command.feature +0 -88
- data/features/step_definitions/gem_steps.rb +0 -24
- data/features/step_definitions/git_steps.rb +0 -5
- data/features/step_definitions/output_steps.rb +0 -5
- data/features/support/env.rb +0 -74
- data/spec/kitchen/base64_stream_spec.rb +0 -74
- data/spec/kitchen/cli_spec.rb +0 -54
- data/spec/kitchen/collection_spec.rb +0 -76
- data/spec/kitchen/color_spec.rb +0 -51
- data/spec/kitchen/config_spec.rb +0 -434
- data/spec/kitchen/configurable_spec.rb +0 -1113
- data/spec/kitchen/data_munger_spec.rb +0 -2800
- data/spec/kitchen/diagnostic_spec.rb +0 -128
- data/spec/kitchen/driver/base_spec.rb +0 -132
- data/spec/kitchen/driver/dummy_spec.rb +0 -193
- data/spec/kitchen/driver/exec_spec.rb +0 -75
- data/spec/kitchen/driver/proxy_spec.rb +0 -127
- data/spec/kitchen/driver/ssh_base_spec.rb +0 -1136
- data/spec/kitchen/driver_spec.rb +0 -106
- data/spec/kitchen/errors_spec.rb +0 -317
- data/spec/kitchen/instance_spec.rb +0 -1372
- data/spec/kitchen/lazy_hash_spec.rb +0 -113
- data/spec/kitchen/lifecycle_hooks_spec.rb +0 -171
- data/spec/kitchen/loader/yaml_spec.rb +0 -787
- data/spec/kitchen/logger_spec.rb +0 -425
- data/spec/kitchen/logging_spec.rb +0 -56
- data/spec/kitchen/login_command_spec.rb +0 -67
- data/spec/kitchen/metadata_chopper_spec.rb +0 -79
- data/spec/kitchen/platform_spec.rb +0 -88
- data/spec/kitchen/provisioner/base_spec.rb +0 -393
- data/spec/kitchen/provisioner/chef/policyfile_spec.rb +0 -140
- data/spec/kitchen/provisioner/chef_apply_spec.rb +0 -131
- data/spec/kitchen/provisioner/chef_base_spec.rb +0 -1565
- data/spec/kitchen/provisioner/chef_solo_spec.rb +0 -602
- data/spec/kitchen/provisioner/chef_zero_spec.rb +0 -1013
- data/spec/kitchen/provisioner/dummy_spec.rb +0 -96
- data/spec/kitchen/provisioner/shell_spec.rb +0 -623
- data/spec/kitchen/provisioner_spec.rb +0 -101
- data/spec/kitchen/shell_out_spec.rb +0 -146
- data/spec/kitchen/ssh_spec.rb +0 -584
- data/spec/kitchen/state_file_spec.rb +0 -122
- data/spec/kitchen/suite_spec.rb +0 -61
- data/spec/kitchen/transport/base_spec.rb +0 -140
- data/spec/kitchen/transport/exec_spec.rb +0 -79
- data/spec/kitchen/transport/ssh_spec.rb +0 -1317
- data/spec/kitchen/transport/winrm_spec.rb +0 -1320
- data/spec/kitchen/transport_spec.rb +0 -106
- data/spec/kitchen/util_spec.rb +0 -250
- data/spec/kitchen/verifier/base_spec.rb +0 -346
- data/spec/kitchen/verifier/busser_spec.rb +0 -580
- data/spec/kitchen/verifier/dummy_spec.rb +0 -96
- data/spec/kitchen/verifier/shell_spec.rb +0 -157
- data/spec/kitchen/verifier_spec.rb +0 -114
- data/spec/kitchen_spec.rb +0 -112
- data/spec/spec_helper.rb +0 -110
- data/spec/support/powershell_max_size_spec.rb +0 -39
- data/test-kitchen.gemspec +0 -49
- data/test/cookbooks/test_cookbook/metadata.rb +0 -6
- data/test/cookbooks/test_cookbook/recipes/default.rb +0 -1
- data/test/integration/default/default_spec.rb +0 -3
- data/testing_windows.md +0 -38
|
@@ -1,1320 +0,0 @@
|
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
|
2
|
-
#
|
|
3
|
-
# Author:: Matt Wrock (<matt@mattwrock.com>)
|
|
4
|
-
#
|
|
5
|
-
# Copyright (C) 2014, Matt Wrock
|
|
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/transport/winrm"
|
|
22
|
-
require "winrm"
|
|
23
|
-
require "winrm-fs"
|
|
24
|
-
require "winrm-elevated"
|
|
25
|
-
|
|
26
|
-
module Kitchen
|
|
27
|
-
module Transport
|
|
28
|
-
class WinRMConnectionDummy < Kitchen::Transport::Winrm::Connection
|
|
29
|
-
attr_reader :saved_command, :remote_path, :local_path
|
|
30
|
-
|
|
31
|
-
def upload(locals, remote)
|
|
32
|
-
@saved_command = IO.read(locals)
|
|
33
|
-
@local_path = locals
|
|
34
|
-
@remote_path = remote
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
describe Kitchen::Transport::Winrm do
|
|
41
|
-
before do
|
|
42
|
-
RbConfig::CONFIG.stubs(:[]).with("host_os").returns("blah")
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
let(:logged_output) { StringIO.new }
|
|
46
|
-
let(:logger) { Logger.new(logged_output) }
|
|
47
|
-
let(:config) { Hash.new }
|
|
48
|
-
let(:state) { Hash.new }
|
|
49
|
-
|
|
50
|
-
let(:instance) do
|
|
51
|
-
stub(name: "coolbeans", logger: logger, to_str: "instance")
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
let(:transport) do
|
|
55
|
-
t = Kitchen::Transport::Winrm.new(config)
|
|
56
|
-
# :load_winrm_s! is not cross-platform safe
|
|
57
|
-
# and gets initialized too early in the pipeline
|
|
58
|
-
t.stubs(:load_winrm_s!)
|
|
59
|
-
t.finalize_config!(instance)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
it "provisioner api_version is 1" do
|
|
63
|
-
transport.diagnose_plugin[:api_version].must_equal 1
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
it "plugin_version is set to Kitchen::VERSION" do
|
|
67
|
-
transport.diagnose_plugin[:version].must_equal Kitchen::VERSION
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
describe "default_config" do
|
|
71
|
-
it "sets :scheme to http by default" do
|
|
72
|
-
transport[:scheme].must_equal "http"
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
it "sets :port to 5985 by default" do
|
|
76
|
-
transport[:port].must_equal 5985
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
it "sets :username to administrator by default" do
|
|
80
|
-
transport[:username].must_equal "administrator"
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
it "sets :password to nil by default" do
|
|
84
|
-
transport[:password].must_be_nil
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
it "sets :rdp_port to 3389 by default" do
|
|
88
|
-
transport[:rdp_port].must_equal 3389
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
it "sets :connection_retries to 5 by default" do
|
|
92
|
-
transport[:connection_retries].must_equal 5
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
it "sets :connection_retry_sleep to 1 by default" do
|
|
96
|
-
transport[:connection_retry_sleep].must_equal 1
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
it "sets :max_wait_until_ready to 600 by default" do
|
|
100
|
-
transport[:max_wait_until_ready].must_equal 600
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
it "sets :winrm_transport to :negotiate" do
|
|
104
|
-
transport[:winrm_transport].must_equal :negotiate
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
it "sets :elevated to false" do
|
|
108
|
-
transport[:elevated].must_equal false
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
describe "#connection" do
|
|
113
|
-
let(:klass) { Kitchen::Transport::Winrm::Connection }
|
|
114
|
-
|
|
115
|
-
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
|
116
|
-
def self.common_connection_specs
|
|
117
|
-
before do
|
|
118
|
-
config[:hostname] = "here"
|
|
119
|
-
config[:kitchen_root] = "/i/am/root"
|
|
120
|
-
config[:password] = "password"
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
it "returns a Kitchen::Transport::Winrm::Connection object" do
|
|
124
|
-
transport.connection(state).must_be_kind_of klass
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
it "sets :instance_name to the instance's name" do
|
|
128
|
-
klass.expects(:new).with do |hash|
|
|
129
|
-
hash[:instance_name] == "coolbeans"
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
make_connection
|
|
133
|
-
end
|
|
134
|
-
it "sets :kitchen_root to the transport's kitchen_root" do
|
|
135
|
-
klass.expects(:new).with do |hash|
|
|
136
|
-
hash[:kitchen_root] == "/i/am/root"
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
make_connection
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
it "sets the :logger to the transport's logger" do
|
|
143
|
-
klass.expects(:new).with do |hash|
|
|
144
|
-
hash[:logger] == logger
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
make_connection
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
it "sets the :winrm_transport to :negotiate" do
|
|
151
|
-
klass.expects(:new).with do |hash|
|
|
152
|
-
hash[:transport] == :negotiate
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
make_connection
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
it "sets the :disable_sspi to false" do
|
|
159
|
-
klass.expects(:new).with do |hash|
|
|
160
|
-
hash[:disable_sspi] == false
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
make_connection
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
it "sets :endpoint when hostname is an IPv6 address" do
|
|
167
|
-
config[:hostname] = "caec:cec6:c4ef:bb7b:1a78:d055:216d:3a78"
|
|
168
|
-
|
|
169
|
-
klass.expects(:new).with do |hash|
|
|
170
|
-
hash[:endpoint] == "http://[caec:cec6:c4ef:bb7b:1a78:d055:216d:3a78]:5985/wsman"
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
make_connection
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
it "sets :endpoint from data in config" do
|
|
177
|
-
config[:hostname] = "host-from-config"
|
|
178
|
-
config[:port] = "42"
|
|
179
|
-
config[:winrm_transport] = "ssl"
|
|
180
|
-
|
|
181
|
-
klass.expects(:new).with do |hash|
|
|
182
|
-
hash[:endpoint] == "https://host-from-config:42/wsman"
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
make_connection
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
it "sets :endpoint from data in state over config data" do
|
|
189
|
-
state[:hostname] = "host-from-state"
|
|
190
|
-
config[:hostname] = "host-from-config"
|
|
191
|
-
state[:port] = "42"
|
|
192
|
-
config[:port] = "43"
|
|
193
|
-
config[:winrm_transport] = "ssl"
|
|
194
|
-
|
|
195
|
-
klass.expects(:new).with do |hash|
|
|
196
|
-
hash[:endpoint] == "https://host-from-state:42/wsman"
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
make_connection
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
it "sets :user from :username in config" do
|
|
203
|
-
config[:username] = "user_from_config"
|
|
204
|
-
|
|
205
|
-
klass.expects(:new).with do |hash|
|
|
206
|
-
hash[:user] == "user_from_config"
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
make_connection
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
it "sets :user from :username in state over config data" do
|
|
213
|
-
state[:username] = "user_from_state"
|
|
214
|
-
config[:username] = "user_from_config"
|
|
215
|
-
|
|
216
|
-
klass.expects(:new).with do |hash|
|
|
217
|
-
hash[:user] == "user_from_state"
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
make_connection
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
it "sets :pass from :password in config" do
|
|
224
|
-
config[:password] = "pass_from_config"
|
|
225
|
-
|
|
226
|
-
klass.expects(:new).with do |hash|
|
|
227
|
-
hash[:password] == "pass_from_config"
|
|
228
|
-
end
|
|
229
|
-
|
|
230
|
-
make_connection
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
it "sets :pass from :password in state over config data" do
|
|
234
|
-
state[:password] = "pass_from_state"
|
|
235
|
-
config[:password] = "pass_from_config"
|
|
236
|
-
|
|
237
|
-
klass.expects(:new).with do |hash|
|
|
238
|
-
hash[:password] == "pass_from_state"
|
|
239
|
-
end
|
|
240
|
-
|
|
241
|
-
make_connection
|
|
242
|
-
end
|
|
243
|
-
|
|
244
|
-
it "sets :rdp_port from config" do
|
|
245
|
-
config[:rdp_port] = "rdp_from_config"
|
|
246
|
-
|
|
247
|
-
klass.expects(:new).with do |hash|
|
|
248
|
-
hash[:rdp_port] == "rdp_from_config"
|
|
249
|
-
end
|
|
250
|
-
|
|
251
|
-
make_connection
|
|
252
|
-
end
|
|
253
|
-
|
|
254
|
-
it "sets :rdp_port from state over config data" do
|
|
255
|
-
state[:rdp_port] = "rdp_from_state"
|
|
256
|
-
config[:rdp_port] = "rdp_from_config"
|
|
257
|
-
|
|
258
|
-
klass.expects(:new).with do |hash|
|
|
259
|
-
hash[:rdp_port] == "rdp_from_state"
|
|
260
|
-
end
|
|
261
|
-
|
|
262
|
-
make_connection
|
|
263
|
-
end
|
|
264
|
-
|
|
265
|
-
it "sets :connection_retries from config" do
|
|
266
|
-
config[:connection_retries] = "retries_from_config"
|
|
267
|
-
|
|
268
|
-
klass.expects(:new).with do |hash|
|
|
269
|
-
hash[:connection_retries] == "retries_from_config"
|
|
270
|
-
end
|
|
271
|
-
|
|
272
|
-
make_connection
|
|
273
|
-
end
|
|
274
|
-
|
|
275
|
-
it "sets :connection_retries from state over config data" do
|
|
276
|
-
state[:connection_retries] = "retries_from_state"
|
|
277
|
-
config[:connection_retries] = "retries_from_config"
|
|
278
|
-
|
|
279
|
-
klass.expects(:new).with do |hash|
|
|
280
|
-
hash[:connection_retries] == "retries_from_state"
|
|
281
|
-
end
|
|
282
|
-
|
|
283
|
-
make_connection
|
|
284
|
-
end
|
|
285
|
-
|
|
286
|
-
it "sets :connection_retry_sleep from config" do
|
|
287
|
-
config[:connection_retry_sleep] = "sleep_from_config"
|
|
288
|
-
|
|
289
|
-
klass.expects(:new).with do |hash|
|
|
290
|
-
hash[:connection_retry_sleep] == "sleep_from_config"
|
|
291
|
-
end
|
|
292
|
-
|
|
293
|
-
make_connection
|
|
294
|
-
end
|
|
295
|
-
|
|
296
|
-
it "sets :connection_retry_sleep from state over config data" do
|
|
297
|
-
state[:connection_retry_sleep] = "sleep_from_state"
|
|
298
|
-
config[:connection_retry_sleep] = "sleep_from_config"
|
|
299
|
-
|
|
300
|
-
klass.expects(:new).with do |hash|
|
|
301
|
-
hash[:connection_retry_sleep] == "sleep_from_state"
|
|
302
|
-
end
|
|
303
|
-
|
|
304
|
-
make_connection
|
|
305
|
-
end
|
|
306
|
-
|
|
307
|
-
it "sets :max_wait_until_ready from config" do
|
|
308
|
-
config[:max_wait_until_ready] = "max_from_config"
|
|
309
|
-
|
|
310
|
-
klass.expects(:new).with do |hash|
|
|
311
|
-
hash[:max_wait_until_ready] == "max_from_config"
|
|
312
|
-
end
|
|
313
|
-
|
|
314
|
-
make_connection
|
|
315
|
-
end
|
|
316
|
-
|
|
317
|
-
it "sets :max_wait_until_ready from state over config data" do
|
|
318
|
-
state[:max_wait_until_ready] = "max_from_state"
|
|
319
|
-
config[:max_wait_until_ready] = "max_from_config"
|
|
320
|
-
|
|
321
|
-
klass.expects(:new).with do |hash|
|
|
322
|
-
hash[:max_wait_until_ready] == "max_from_state"
|
|
323
|
-
end
|
|
324
|
-
|
|
325
|
-
make_connection
|
|
326
|
-
end
|
|
327
|
-
|
|
328
|
-
it "sets :winrm_transport from config data" do
|
|
329
|
-
config[:winrm_transport] = "ssl"
|
|
330
|
-
|
|
331
|
-
klass.expects(:new).with do |hash|
|
|
332
|
-
hash[:transport] == :ssl
|
|
333
|
-
end
|
|
334
|
-
|
|
335
|
-
make_connection
|
|
336
|
-
end
|
|
337
|
-
|
|
338
|
-
it "sets elevated_username from user by default" do
|
|
339
|
-
config[:username] = "user"
|
|
340
|
-
|
|
341
|
-
klass.expects(:new).with do |hash|
|
|
342
|
-
hash[:elevated_username] == "user"
|
|
343
|
-
end
|
|
344
|
-
|
|
345
|
-
make_connection
|
|
346
|
-
end
|
|
347
|
-
|
|
348
|
-
it "sets elevated_username from overriden elevated_username" do
|
|
349
|
-
config[:username] = "user"
|
|
350
|
-
config[:elevated_username] = "elevated_user"
|
|
351
|
-
|
|
352
|
-
klass.expects(:new).with do |hash|
|
|
353
|
-
hash[:elevated_username] == "elevated_user"
|
|
354
|
-
end
|
|
355
|
-
|
|
356
|
-
make_connection
|
|
357
|
-
end
|
|
358
|
-
|
|
359
|
-
it "sets elevated_password from user by default" do
|
|
360
|
-
config[:password] = "pass"
|
|
361
|
-
|
|
362
|
-
klass.expects(:new).with do |hash|
|
|
363
|
-
hash[:elevated_password] == "pass"
|
|
364
|
-
end
|
|
365
|
-
|
|
366
|
-
make_connection
|
|
367
|
-
end
|
|
368
|
-
|
|
369
|
-
it "sets elevated_password from overriden elevated_password" do
|
|
370
|
-
config[:password] = "pass"
|
|
371
|
-
config[:elevated_password] = "elevated_pass"
|
|
372
|
-
|
|
373
|
-
klass.expects(:new).with do |hash|
|
|
374
|
-
hash[:elevated_password] == "elevated_pass"
|
|
375
|
-
end
|
|
376
|
-
|
|
377
|
-
make_connection
|
|
378
|
-
end
|
|
379
|
-
|
|
380
|
-
it "sets elevated_password to nil if overriden elevated_password is nil" do
|
|
381
|
-
config[:password] = "pass"
|
|
382
|
-
config[:elevated_password] = nil
|
|
383
|
-
|
|
384
|
-
klass.expects(:new).with do |hash|
|
|
385
|
-
hash[:elevated_password].nil?
|
|
386
|
-
end
|
|
387
|
-
|
|
388
|
-
make_connection
|
|
389
|
-
end
|
|
390
|
-
|
|
391
|
-
describe "when negotiate is set in config" do
|
|
392
|
-
before do
|
|
393
|
-
config[:winrm_transport] = "negotiate"
|
|
394
|
-
end
|
|
395
|
-
|
|
396
|
-
it "sets :winrm_transport to negotiate" do
|
|
397
|
-
klass.expects(:new).with do |hash|
|
|
398
|
-
hash[:transport] == :negotiate &&
|
|
399
|
-
hash[:disable_sspi] == false &&
|
|
400
|
-
hash[:basic_auth_only] == false
|
|
401
|
-
end
|
|
402
|
-
|
|
403
|
-
make_connection
|
|
404
|
-
end
|
|
405
|
-
end
|
|
406
|
-
|
|
407
|
-
it "returns the same connection when called again with same state" do
|
|
408
|
-
first_connection = make_connection(state)
|
|
409
|
-
second_connection = make_connection(state)
|
|
410
|
-
|
|
411
|
-
first_connection.object_id.must_equal second_connection.object_id
|
|
412
|
-
end
|
|
413
|
-
|
|
414
|
-
it "logs a debug message when the connection is reused" do
|
|
415
|
-
make_connection(state)
|
|
416
|
-
make_connection(state)
|
|
417
|
-
|
|
418
|
-
logged_output.string.lines.count do |l|
|
|
419
|
-
l =~ debug_line_with("[WinRM] reusing existing connection ")
|
|
420
|
-
end.must_equal 1
|
|
421
|
-
end
|
|
422
|
-
|
|
423
|
-
it "returns a new connection when called again if state differs" do
|
|
424
|
-
first_connection = make_connection(state)
|
|
425
|
-
second_connection = make_connection(state.merge(port: 9000))
|
|
426
|
-
|
|
427
|
-
first_connection.object_id.wont_equal second_connection.object_id
|
|
428
|
-
end
|
|
429
|
-
|
|
430
|
-
it "closes first connection when a second is created" do
|
|
431
|
-
first_connection = make_connection(state)
|
|
432
|
-
first_connection.expects(:close)
|
|
433
|
-
|
|
434
|
-
make_connection(state.merge(port: 9000))
|
|
435
|
-
end
|
|
436
|
-
|
|
437
|
-
it "logs a debug message a second connection is created" do
|
|
438
|
-
make_connection(state)
|
|
439
|
-
make_connection(state.merge(port: 9000))
|
|
440
|
-
|
|
441
|
-
logged_output.string.lines.count do |l|
|
|
442
|
-
l =~ debug_line_with("[WinRM] shutting previous connection ")
|
|
443
|
-
end.must_equal 1
|
|
444
|
-
end
|
|
445
|
-
end
|
|
446
|
-
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
|
447
|
-
|
|
448
|
-
describe "called without a block" do
|
|
449
|
-
def make_connection(s = state)
|
|
450
|
-
transport.connection(s)
|
|
451
|
-
end
|
|
452
|
-
|
|
453
|
-
common_connection_specs
|
|
454
|
-
end
|
|
455
|
-
|
|
456
|
-
describe "called with a block" do
|
|
457
|
-
def make_connection(s = state)
|
|
458
|
-
transport.connection(s) do |conn|
|
|
459
|
-
conn
|
|
460
|
-
end
|
|
461
|
-
end
|
|
462
|
-
|
|
463
|
-
common_connection_specs
|
|
464
|
-
end
|
|
465
|
-
end
|
|
466
|
-
|
|
467
|
-
describe "#load_needed_dependencies" do
|
|
468
|
-
describe "winrm-elevated" do
|
|
469
|
-
let(:transport) { Kitchen::Transport::Winrm.new(config) }
|
|
470
|
-
|
|
471
|
-
before do
|
|
472
|
-
transport.stubs(:require).with("winrm")
|
|
473
|
-
transport.stubs(:require).with("winrm-fs")
|
|
474
|
-
end
|
|
475
|
-
|
|
476
|
-
describe "elevated is false" do
|
|
477
|
-
it "does not require winrm-elevated" do
|
|
478
|
-
transport.expects(:require).with("winrm-elevated").never
|
|
479
|
-
transport.finalize_config!(instance)
|
|
480
|
-
end
|
|
481
|
-
end
|
|
482
|
-
|
|
483
|
-
describe "elevated is true" do
|
|
484
|
-
before { config[:elevated] = true }
|
|
485
|
-
|
|
486
|
-
it "does requires winrm-elevated" do
|
|
487
|
-
transport.expects(:require).with("winrm-elevated")
|
|
488
|
-
transport.finalize_config!(instance)
|
|
489
|
-
end
|
|
490
|
-
end
|
|
491
|
-
end
|
|
492
|
-
|
|
493
|
-
describe "winrm-fs" do
|
|
494
|
-
before do
|
|
495
|
-
# force loading of winrm-fs to get the version constant
|
|
496
|
-
require "winrm-fs"
|
|
497
|
-
end
|
|
498
|
-
|
|
499
|
-
it "logs a message to debug that code will be loaded" do
|
|
500
|
-
transport
|
|
501
|
-
|
|
502
|
-
logged_output.string.must_match debug_line_with(
|
|
503
|
-
"winrm-fs requested, loading winrm-fs gem")
|
|
504
|
-
end
|
|
505
|
-
|
|
506
|
-
it "logs a message to debug when library is initially loaded" do
|
|
507
|
-
transport = Kitchen::Transport::Winrm.new(config)
|
|
508
|
-
transport.stubs(:require).with("winrm", anything)
|
|
509
|
-
transport.stubs(:require).with("winrm-fs").returns(true)
|
|
510
|
-
transport.finalize_config!(instance)
|
|
511
|
-
|
|
512
|
-
logged_output.string.must_match(
|
|
513
|
-
/winrm-fs is loaded/
|
|
514
|
-
)
|
|
515
|
-
end
|
|
516
|
-
|
|
517
|
-
it "logs a message to debug when library is previously loaded" do
|
|
518
|
-
transport = Kitchen::Transport::Winrm.new(config)
|
|
519
|
-
transport.stubs(:require).with("winrm", anything)
|
|
520
|
-
transport.stubs(:require).with("winrm-fs").returns(false)
|
|
521
|
-
transport.finalize_config!(instance)
|
|
522
|
-
|
|
523
|
-
logged_output.string.must_match(
|
|
524
|
-
/winrm-fs was already loaded/
|
|
525
|
-
)
|
|
526
|
-
end
|
|
527
|
-
|
|
528
|
-
it "logs a message to fatal when libraries cannot be loaded" do
|
|
529
|
-
transport = Kitchen::Transport::Winrm.new(config)
|
|
530
|
-
transport.stubs(:require).with("winrm", anything)
|
|
531
|
-
transport.stubs(:require).with("winrm-fs")
|
|
532
|
-
.raises(LoadError, "uh oh")
|
|
533
|
-
begin
|
|
534
|
-
transport.finalize_config!(instance)
|
|
535
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
|
536
|
-
# we are interested in the log output, not this exception
|
|
537
|
-
end
|
|
538
|
-
|
|
539
|
-
logged_output.string.must_match fatal_line_with(
|
|
540
|
-
"The `winrm-fs` gem is missing and must be installed")
|
|
541
|
-
end
|
|
542
|
-
|
|
543
|
-
it "raises a UserError when libraries cannot be loaded" do
|
|
544
|
-
transport = Kitchen::Transport::Winrm.new(config)
|
|
545
|
-
transport.stubs(:require).with("winrm", anything)
|
|
546
|
-
transport.stubs(:require).with("winrm-fs")
|
|
547
|
-
.raises(LoadError, "uh oh")
|
|
548
|
-
|
|
549
|
-
err = proc do
|
|
550
|
-
transport.finalize_config!(instance)
|
|
551
|
-
end.must_raise Kitchen::UserError
|
|
552
|
-
err.message.must_match(/^Could not load or activate winrm-fs\. /)
|
|
553
|
-
end
|
|
554
|
-
end
|
|
555
|
-
|
|
556
|
-
describe "winrm" do
|
|
557
|
-
it "logs a message to debug that code will be loaded" do
|
|
558
|
-
transport = Kitchen::Transport::Winrm.new(config)
|
|
559
|
-
transport.stubs(:require).with("winrm-fs", anything)
|
|
560
|
-
transport.stubs(:require)
|
|
561
|
-
transport.finalize_config!(instance)
|
|
562
|
-
|
|
563
|
-
logged_output.string.must_match debug_line_with(
|
|
564
|
-
"winrm requested, loading winrm gem")
|
|
565
|
-
end
|
|
566
|
-
|
|
567
|
-
it "logs a message to debug when library is initially loaded" do
|
|
568
|
-
transport = Kitchen::Transport::Winrm.new(config)
|
|
569
|
-
transport.stubs(:require).with("winrm-fs", anything)
|
|
570
|
-
transport.stubs(:require).returns(true)
|
|
571
|
-
|
|
572
|
-
transport.finalize_config!(instance)
|
|
573
|
-
|
|
574
|
-
logged_output.string.must_match(
|
|
575
|
-
/winrm is loaded/
|
|
576
|
-
)
|
|
577
|
-
end
|
|
578
|
-
|
|
579
|
-
it "logs a message to debug when library is previously loaded" do
|
|
580
|
-
transport = Kitchen::Transport::Winrm.new(config)
|
|
581
|
-
transport.stubs(:require).with("winrm-fs", anything)
|
|
582
|
-
transport.stubs(:require).returns(false)
|
|
583
|
-
|
|
584
|
-
transport.finalize_config!(instance)
|
|
585
|
-
|
|
586
|
-
logged_output.string.must_match(
|
|
587
|
-
/winrm was already loaded/
|
|
588
|
-
)
|
|
589
|
-
end
|
|
590
|
-
|
|
591
|
-
it "logs a message to fatal when libraries cannot be loaded" do
|
|
592
|
-
transport = Kitchen::Transport::Winrm.new(config)
|
|
593
|
-
transport.stubs(:require).with("winrm-fs", anything)
|
|
594
|
-
transport.stubs(:require).raises(LoadError, "uh oh")
|
|
595
|
-
begin
|
|
596
|
-
transport.finalize_config!(instance)
|
|
597
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
|
598
|
-
# we are interested in the log output, not this exception
|
|
599
|
-
end
|
|
600
|
-
|
|
601
|
-
logged_output.string.must_match fatal_line_with(
|
|
602
|
-
"The `winrm` gem is missing and must be installed")
|
|
603
|
-
end
|
|
604
|
-
|
|
605
|
-
it "raises a UserError when libraries cannot be loaded" do
|
|
606
|
-
transport = Kitchen::Transport::Winrm.new(config)
|
|
607
|
-
transport.stubs(:require).with("winrm-fs", anything)
|
|
608
|
-
transport.stubs(:require).raises(LoadError, "uh oh")
|
|
609
|
-
|
|
610
|
-
err = proc do
|
|
611
|
-
transport.finalize_config!(instance)
|
|
612
|
-
end.must_raise Kitchen::UserError
|
|
613
|
-
err.message.must_match(/^Could not load or activate winrm\. /)
|
|
614
|
-
end
|
|
615
|
-
end
|
|
616
|
-
end
|
|
617
|
-
|
|
618
|
-
def debug_line_with(msg)
|
|
619
|
-
/^D, .* : #{Regexp.escape(msg)}/
|
|
620
|
-
end
|
|
621
|
-
|
|
622
|
-
def fatal_line_with(msg)
|
|
623
|
-
/^F, .* : #{Regexp.escape(msg)}/
|
|
624
|
-
end
|
|
625
|
-
end
|
|
626
|
-
|
|
627
|
-
describe Kitchen::Transport::Winrm::Connection do
|
|
628
|
-
let(:logged_output) { StringIO.new }
|
|
629
|
-
let(:logger) { Logger.new(logged_output) }
|
|
630
|
-
|
|
631
|
-
let(:options) do
|
|
632
|
-
{ logger: logger, user: "me", password: "haha",
|
|
633
|
-
endpoint: "http://foo:5985/wsman", winrm_transport: :plaintext,
|
|
634
|
-
kitchen_root: "/i/am/root", instance_name: "coolbeans",
|
|
635
|
-
rdp_port: "rdpyeah" }
|
|
636
|
-
end
|
|
637
|
-
|
|
638
|
-
let(:info) do
|
|
639
|
-
copts = {
|
|
640
|
-
user: "me",
|
|
641
|
-
password: "haha",
|
|
642
|
-
endpoint: "http://foo:5985/wsman",
|
|
643
|
-
winrm_transport: :plaintext,
|
|
644
|
-
}
|
|
645
|
-
"<#{copts}>"
|
|
646
|
-
end
|
|
647
|
-
|
|
648
|
-
let(:winrm_session) do
|
|
649
|
-
s = mock("winrm_session")
|
|
650
|
-
s.responds_like_instance_of(::WinRM::Connection)
|
|
651
|
-
s
|
|
652
|
-
end
|
|
653
|
-
|
|
654
|
-
let(:executor) do
|
|
655
|
-
s = mock("command_executor")
|
|
656
|
-
s.responds_like_instance_of(WinRM::Shells::Powershell)
|
|
657
|
-
s
|
|
658
|
-
end
|
|
659
|
-
|
|
660
|
-
let(:transporter) do
|
|
661
|
-
t = mock("file_transporter")
|
|
662
|
-
t.responds_like_instance_of(WinRM::FS::Core::FileTransporter)
|
|
663
|
-
t
|
|
664
|
-
end
|
|
665
|
-
|
|
666
|
-
let(:elevated_runner) do
|
|
667
|
-
r = mock("elevated_runner")
|
|
668
|
-
r.responds_like_instance_of(WinRM::Shells::Elevated)
|
|
669
|
-
r
|
|
670
|
-
end
|
|
671
|
-
|
|
672
|
-
let(:connection) do
|
|
673
|
-
Kitchen::Transport::Winrm::Connection.new(options)
|
|
674
|
-
end
|
|
675
|
-
|
|
676
|
-
before do
|
|
677
|
-
WinRM::Connection.stubs(:new).returns(winrm_session)
|
|
678
|
-
winrm_session.stubs(:logger=)
|
|
679
|
-
logger.level = Logger::DEBUG
|
|
680
|
-
end
|
|
681
|
-
|
|
682
|
-
describe "#close" do
|
|
683
|
-
let(:response) do
|
|
684
|
-
o = WinRM::Output.new
|
|
685
|
-
o.exitcode = 0
|
|
686
|
-
o << { stdout: "ok\r\n" }
|
|
687
|
-
o
|
|
688
|
-
end
|
|
689
|
-
|
|
690
|
-
before do
|
|
691
|
-
transporter.stubs(:upload)
|
|
692
|
-
elevated_runner.stubs(:run).returns(response)
|
|
693
|
-
winrm_session.stubs(:shell).with(:powershell).returns(executor)
|
|
694
|
-
executor.stubs(:close)
|
|
695
|
-
elevated_runner.stubs(:close)
|
|
696
|
-
executor.stubs(:run)
|
|
697
|
-
.with("doit").yields("ok\n", nil).returns(response)
|
|
698
|
-
executor.stubs(:run)
|
|
699
|
-
.with("$env:temp").yields("ok\n", nil).returns(response)
|
|
700
|
-
end
|
|
701
|
-
|
|
702
|
-
it "only closes the shell once for multiple calls" do
|
|
703
|
-
executor.expects(:close).once
|
|
704
|
-
|
|
705
|
-
connection.execute("doit")
|
|
706
|
-
connection.close
|
|
707
|
-
connection.close
|
|
708
|
-
connection.close
|
|
709
|
-
end
|
|
710
|
-
|
|
711
|
-
it "clears the file_transporter executor" do
|
|
712
|
-
WinRM::FS::Core::FileTransporter.expects(:new).returns(transporter).twice
|
|
713
|
-
|
|
714
|
-
connection.upload("local", "remote")
|
|
715
|
-
connection.close
|
|
716
|
-
connection.upload("local", "remote")
|
|
717
|
-
end
|
|
718
|
-
|
|
719
|
-
it "clears the elevated_runner executor" do
|
|
720
|
-
options[:elevated] = true
|
|
721
|
-
elevated_runner.stubs(:username=)
|
|
722
|
-
elevated_runner.stubs(:password=)
|
|
723
|
-
elevated_runner.expects(:close).once
|
|
724
|
-
winrm_session.expects(:shell).with(:elevated).returns(elevated_runner).twice
|
|
725
|
-
|
|
726
|
-
connection.execute("doit")
|
|
727
|
-
connection.close
|
|
728
|
-
connection.execute("doit")
|
|
729
|
-
end
|
|
730
|
-
end
|
|
731
|
-
|
|
732
|
-
describe "#execute" do
|
|
733
|
-
before do
|
|
734
|
-
winrm_session.stubs(:shell).with(:powershell).returns(executor)
|
|
735
|
-
end
|
|
736
|
-
|
|
737
|
-
describe "for a successful command" do
|
|
738
|
-
let(:response) do
|
|
739
|
-
o = WinRM::Output.new
|
|
740
|
-
o.exitcode = 0
|
|
741
|
-
o << { stdout: "ok\r\n" }
|
|
742
|
-
o << { stderr: "congrats\r\n" }
|
|
743
|
-
o
|
|
744
|
-
end
|
|
745
|
-
|
|
746
|
-
before do
|
|
747
|
-
executor.expects(:run)
|
|
748
|
-
.with("doit").yields("ok\n", nil).returns(response)
|
|
749
|
-
executor.expects(:close).once
|
|
750
|
-
end
|
|
751
|
-
|
|
752
|
-
it "logger displays command on debug" do
|
|
753
|
-
connection.execute("doit")
|
|
754
|
-
|
|
755
|
-
logged_output.string.must_match debug_line(
|
|
756
|
-
"[WinRM] #{info} (doit)")
|
|
757
|
-
end
|
|
758
|
-
|
|
759
|
-
it "logger captures stdout" do
|
|
760
|
-
connection.execute("doit")
|
|
761
|
-
|
|
762
|
-
logged_output.string.must_match(/^ok$/)
|
|
763
|
-
end
|
|
764
|
-
|
|
765
|
-
it "logger captures stderr on warn if logger is at debug level" do
|
|
766
|
-
logger.level = Logger::DEBUG
|
|
767
|
-
connection.execute("doit")
|
|
768
|
-
|
|
769
|
-
logged_output.string.must_match warn_line("congrats")
|
|
770
|
-
end
|
|
771
|
-
|
|
772
|
-
it "logger does not log stderr on warn if logger is below debug level" do
|
|
773
|
-
logger.level = Logger::INFO
|
|
774
|
-
connection.execute("doit")
|
|
775
|
-
|
|
776
|
-
logged_output.string.wont_match warn_line("congrats")
|
|
777
|
-
end
|
|
778
|
-
end
|
|
779
|
-
|
|
780
|
-
describe "elevated command" do
|
|
781
|
-
let(:response) do
|
|
782
|
-
o = WinRM::Output.new
|
|
783
|
-
o.exitcode = 0
|
|
784
|
-
o << { stdout: "ok\r\n" }
|
|
785
|
-
o << { stderr: "congrats\r\n" }
|
|
786
|
-
o
|
|
787
|
-
end
|
|
788
|
-
let(:env_temp_response) do
|
|
789
|
-
o = WinRM::Output.new
|
|
790
|
-
o.exitcode = 0
|
|
791
|
-
o << { stdout: "temp_dir" }
|
|
792
|
-
o
|
|
793
|
-
end
|
|
794
|
-
let(:elevated_runner) do
|
|
795
|
-
r = mock("elevated_runner")
|
|
796
|
-
r.responds_like_instance_of(WinRM::Shells::Elevated)
|
|
797
|
-
r
|
|
798
|
-
end
|
|
799
|
-
|
|
800
|
-
before do
|
|
801
|
-
options[:elevated] = true
|
|
802
|
-
winrm_session.stubs(:shell).with(:elevated).returns(elevated_runner)
|
|
803
|
-
executor.expects(:close).once
|
|
804
|
-
elevated_runner.expects(:close).once
|
|
805
|
-
end
|
|
806
|
-
|
|
807
|
-
describe "elevated user is not login user" do
|
|
808
|
-
before do
|
|
809
|
-
options[:elevated_username] = "username"
|
|
810
|
-
options[:elevated_password] = "password"
|
|
811
|
-
executor.expects(:run)
|
|
812
|
-
.with("$env:temp").returns(env_temp_response)
|
|
813
|
-
elevated_runner.expects(:run)
|
|
814
|
-
.with(
|
|
815
|
-
"$env:temp='temp_dir';doit"
|
|
816
|
-
).yields("ok\n", nil).returns(response)
|
|
817
|
-
elevated_runner.expects(:username=).with("username")
|
|
818
|
-
elevated_runner.expects(:password=).with("password")
|
|
819
|
-
end
|
|
820
|
-
|
|
821
|
-
it "logger captures stdout" do
|
|
822
|
-
connection.execute("doit")
|
|
823
|
-
|
|
824
|
-
logged_output.string.must_match(/^ok$/)
|
|
825
|
-
end
|
|
826
|
-
end
|
|
827
|
-
|
|
828
|
-
describe "elevated user is login user" do
|
|
829
|
-
before do
|
|
830
|
-
options[:elevated_username] = options[:user]
|
|
831
|
-
options[:elevated_password] = options[:password]
|
|
832
|
-
executor.expects(:run)
|
|
833
|
-
.with("$env:temp").returns(env_temp_response)
|
|
834
|
-
elevated_runner.expects(:run)
|
|
835
|
-
.with(
|
|
836
|
-
"$env:temp='temp_dir';doit"
|
|
837
|
-
).yields("ok\n", nil).returns(response)
|
|
838
|
-
elevated_runner.expects(:username=).with(options[:user])
|
|
839
|
-
elevated_runner.expects(:password=).with(options[:password])
|
|
840
|
-
end
|
|
841
|
-
|
|
842
|
-
it "logger captures stdout" do
|
|
843
|
-
connection.execute("doit")
|
|
844
|
-
|
|
845
|
-
logged_output.string.must_match(/^ok$/)
|
|
846
|
-
end
|
|
847
|
-
end
|
|
848
|
-
end
|
|
849
|
-
|
|
850
|
-
describe "for a failed command" do
|
|
851
|
-
let(:response) do
|
|
852
|
-
o = WinRM::Output.new
|
|
853
|
-
o.exitcode = 1
|
|
854
|
-
o << { stderr: "#< CLIXML\r\n" }
|
|
855
|
-
o << { stderr: '<Objs Version="1.1.0.1" xmlns="http://schemas.' }
|
|
856
|
-
o << { stderr: 'microsoft.com/powershell/2004/04"><S S="Error">' }
|
|
857
|
-
o << { stderr: "doit : The term 'doit' is not recognized as the " }
|
|
858
|
-
o << { stderr: "name of a cmdlet, function, _x000D__x000A_</S>" }
|
|
859
|
-
o << { stderr: '<S S="Error">script file, or operable program. ' }
|
|
860
|
-
o << { stderr: "Check the spelling of" }
|
|
861
|
-
o << { stderr: 'the name, or if a path _x000D__x000A_</S><S S="E' }
|
|
862
|
-
o << { stderr: 'rror">was included, verify that the path is corr' }
|
|
863
|
-
o << { stderr: 'ect and try again._x000D__x000A_</S><S S="Error' }
|
|
864
|
-
o << { stderr: '">At line:1 char:1_x000D__x000A_</S><S S="Error' }
|
|
865
|
-
o << { stderr: '">+ doit_x000D__x000A_</S><S S="Error">+ ~~~~_' }
|
|
866
|
-
o << { stderr: 'x000D__x000A_</S><S S="Error"> + CategoryInf' }
|
|
867
|
-
o << { stderr: "o : ObjectNotFound: (doit:String) [], Co" }
|
|
868
|
-
o << { stderr: 'mmandNotFoun _x000D__x000A_</S><S S="Error"> ' }
|
|
869
|
-
o << { stderr: 'dException_x000D__x000A_</S><S S="Error"> + ' }
|
|
870
|
-
o << { stderr: "FullyQualifiedErrorId : CommandNotFoundException_" }
|
|
871
|
-
o << { stderr: 'x000D__x000A_</S><S S="Error"> _x000D__x000A_</' }
|
|
872
|
-
o << { stderr: "S></Objs>" }
|
|
873
|
-
o
|
|
874
|
-
end
|
|
875
|
-
|
|
876
|
-
before do
|
|
877
|
-
executor.expects(:run)
|
|
878
|
-
.with("doit").yields("nope\n", nil).returns(response)
|
|
879
|
-
executor.expects(:close).once
|
|
880
|
-
end
|
|
881
|
-
|
|
882
|
-
# rubocop:disable Metrics/MethodLength
|
|
883
|
-
def self.common_failed_command_specs
|
|
884
|
-
it "logger displays command on debug" do
|
|
885
|
-
begin
|
|
886
|
-
connection.execute("doit")
|
|
887
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
|
888
|
-
# the raise is not what is being tested here, rather its side-effect
|
|
889
|
-
end
|
|
890
|
-
|
|
891
|
-
logged_output.string.must_match debug_line(
|
|
892
|
-
"[WinRM] #{info} (doit)"
|
|
893
|
-
)
|
|
894
|
-
end
|
|
895
|
-
|
|
896
|
-
it "logger captures stdout" do
|
|
897
|
-
begin
|
|
898
|
-
connection.execute("doit")
|
|
899
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
|
900
|
-
# the raise is not what is being tested here, rather its side-effect
|
|
901
|
-
end
|
|
902
|
-
|
|
903
|
-
logged_output.string.must_match(/^nope$/)
|
|
904
|
-
end
|
|
905
|
-
|
|
906
|
-
it "stderr is printed on logger warn level" do
|
|
907
|
-
begin
|
|
908
|
-
connection.execute("doit")
|
|
909
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
|
910
|
-
# the raise is not what is being tested here, rather its side-effect
|
|
911
|
-
end
|
|
912
|
-
|
|
913
|
-
message = <<~'MSG'.chomp!
|
|
914
|
-
doit : The term 'doit' is not recognized as the name of a cmdlet, function,
|
|
915
|
-
script file, or operable program. Check the spelling ofthe name, or if a path
|
|
916
|
-
was included, verify that the path is correct and try again.
|
|
917
|
-
At line:1 char:1
|
|
918
|
-
+ doit
|
|
919
|
-
+ ~~~~
|
|
920
|
-
+ CategoryInfo : ObjectNotFound: (doit:String) [], CommandNotFoun
|
|
921
|
-
dException
|
|
922
|
-
+ FullyQualifiedErrorId : CommandNotFoundException
|
|
923
|
-
MSG
|
|
924
|
-
|
|
925
|
-
message.lines.each do |line|
|
|
926
|
-
logged_output.string.must_match warn_line(line.chomp)
|
|
927
|
-
end
|
|
928
|
-
end
|
|
929
|
-
end
|
|
930
|
-
# rubocop:enable Metrics/MethodLength
|
|
931
|
-
|
|
932
|
-
describe "when a non-zero exit code is returned" do
|
|
933
|
-
common_failed_command_specs
|
|
934
|
-
|
|
935
|
-
it "raises a WinrmFailed exception" do
|
|
936
|
-
err = proc do
|
|
937
|
-
connection.execute("doit")
|
|
938
|
-
end.must_raise Kitchen::Transport::WinrmFailed
|
|
939
|
-
err.message.must_equal "WinRM exited (1) for command: [doit]"
|
|
940
|
-
end
|
|
941
|
-
|
|
942
|
-
it "raises WinrmFailed exception with the exit code of the failure" do
|
|
943
|
-
begin
|
|
944
|
-
connection.execute("doit")
|
|
945
|
-
rescue Kitchen::Transport::WinrmFailed => e
|
|
946
|
-
e.exit_code.must_equal 1
|
|
947
|
-
end
|
|
948
|
-
end
|
|
949
|
-
end
|
|
950
|
-
end
|
|
951
|
-
|
|
952
|
-
describe "for a nil command" do
|
|
953
|
-
it "does not log on debug" do
|
|
954
|
-
executor.expects(:open).never
|
|
955
|
-
connection.execute(nil)
|
|
956
|
-
|
|
957
|
-
logged_output.string.must_equal ""
|
|
958
|
-
end
|
|
959
|
-
end
|
|
960
|
-
|
|
961
|
-
[
|
|
962
|
-
Errno::EACCES, Errno::EADDRINUSE, Errno::ECONNREFUSED,
|
|
963
|
-
Errno::ECONNRESET, Errno::ENETUNREACH, Errno::EHOSTUNREACH,
|
|
964
|
-
::WinRM::WinRMHTTPTransportError, ::WinRM::WinRMAuthorizationError,
|
|
965
|
-
HTTPClient::KeepAliveDisconnected, HTTPClient::ConnectTimeoutError
|
|
966
|
-
].each do |klass|
|
|
967
|
-
describe "raising #{klass}" do
|
|
968
|
-
before do
|
|
969
|
-
k = if klass == ::WinRM::WinRMHTTPTransportError
|
|
970
|
-
# this exception takes 2 args in its constructor, which is not stock
|
|
971
|
-
klass.new("dang", 200)
|
|
972
|
-
else
|
|
973
|
-
klass
|
|
974
|
-
end
|
|
975
|
-
|
|
976
|
-
options[:connection_retries] = 3
|
|
977
|
-
options[:connection_retry_sleep] = 7
|
|
978
|
-
winrm_session.stubs(:shell).with(:powershell).raises(k)
|
|
979
|
-
end
|
|
980
|
-
|
|
981
|
-
it "reraises the #{klass} exception" do
|
|
982
|
-
proc { connection.execute("nope") }.must_raise klass
|
|
983
|
-
end
|
|
984
|
-
end
|
|
985
|
-
end
|
|
986
|
-
end
|
|
987
|
-
|
|
988
|
-
describe "#login_command" do
|
|
989
|
-
let(:login_command) { connection.login_command }
|
|
990
|
-
let(:args) { login_command.arguments.join(" ") }
|
|
991
|
-
let(:exec_args) { login_command.exec_args }
|
|
992
|
-
|
|
993
|
-
let(:rdp_doc) do
|
|
994
|
-
File.join(File.join(options[:kitchen_root], ".kitchen", "coolbeans.rdp"))
|
|
995
|
-
end
|
|
996
|
-
|
|
997
|
-
describe "for Mac-based workstations" do
|
|
998
|
-
before do
|
|
999
|
-
RbConfig::CONFIG.stubs(:[]).with("host_os").returns("darwin14")
|
|
1000
|
-
end
|
|
1001
|
-
|
|
1002
|
-
it "returns a LoginCommand" do
|
|
1003
|
-
with_fake_fs do
|
|
1004
|
-
FileUtils.mkdir_p(File.dirname(rdp_doc))
|
|
1005
|
-
login_command.must_be_instance_of Kitchen::LoginCommand
|
|
1006
|
-
end
|
|
1007
|
-
end
|
|
1008
|
-
|
|
1009
|
-
it "creates an rdp document" do
|
|
1010
|
-
actual = nil
|
|
1011
|
-
with_fake_fs do
|
|
1012
|
-
FileUtils.mkdir_p(File.dirname(rdp_doc))
|
|
1013
|
-
login_command
|
|
1014
|
-
actual = IO.read(rdp_doc)
|
|
1015
|
-
end
|
|
1016
|
-
|
|
1017
|
-
actual.must_equal Kitchen::Util.outdent!(<<-RDP)
|
|
1018
|
-
drivestoredirect:s:*
|
|
1019
|
-
full address:s:foo:rdpyeah
|
|
1020
|
-
prompt for credentials:i:1
|
|
1021
|
-
username:s:me
|
|
1022
|
-
RDP
|
|
1023
|
-
end
|
|
1024
|
-
|
|
1025
|
-
it "prints the rdp document on debug" do
|
|
1026
|
-
with_fake_fs do
|
|
1027
|
-
FileUtils.mkdir_p(File.dirname(rdp_doc))
|
|
1028
|
-
login_command
|
|
1029
|
-
end
|
|
1030
|
-
|
|
1031
|
-
expected = Kitchen::Util.outdent!(<<-OUTPUT)
|
|
1032
|
-
Creating RDP document for coolbeans (/i/am/root/.kitchen/coolbeans.rdp)
|
|
1033
|
-
------------
|
|
1034
|
-
drivestoredirect:s:*
|
|
1035
|
-
full address:s:foo:rdpyeah
|
|
1036
|
-
prompt for credentials:i:1
|
|
1037
|
-
username:s:me
|
|
1038
|
-
------------
|
|
1039
|
-
OUTPUT
|
|
1040
|
-
debug_output(logged_output.string).must_match expected
|
|
1041
|
-
end
|
|
1042
|
-
|
|
1043
|
-
it "returns a LoginCommand which calls open on the rdp document" do
|
|
1044
|
-
actual = nil
|
|
1045
|
-
with_fake_fs do
|
|
1046
|
-
FileUtils.mkdir_p(File.dirname(rdp_doc))
|
|
1047
|
-
actual = login_command
|
|
1048
|
-
end
|
|
1049
|
-
|
|
1050
|
-
actual.exec_args.must_equal ["open", rdp_doc, {}]
|
|
1051
|
-
end
|
|
1052
|
-
end
|
|
1053
|
-
|
|
1054
|
-
describe "for Windows-based workstations" do
|
|
1055
|
-
before do
|
|
1056
|
-
RbConfig::CONFIG.stubs(:[]).with("host_os").returns("mingw32")
|
|
1057
|
-
end
|
|
1058
|
-
|
|
1059
|
-
it "returns a LoginCommand" do
|
|
1060
|
-
with_fake_fs do
|
|
1061
|
-
FileUtils.mkdir_p(File.dirname(rdp_doc))
|
|
1062
|
-
login_command.must_be_instance_of Kitchen::LoginCommand
|
|
1063
|
-
end
|
|
1064
|
-
end
|
|
1065
|
-
|
|
1066
|
-
it "creates an rdp document" do
|
|
1067
|
-
actual = nil
|
|
1068
|
-
with_fake_fs do
|
|
1069
|
-
FileUtils.mkdir_p(File.dirname(rdp_doc))
|
|
1070
|
-
login_command
|
|
1071
|
-
actual = IO.read(rdp_doc)
|
|
1072
|
-
end
|
|
1073
|
-
|
|
1074
|
-
actual.must_equal Kitchen::Util.outdent!(<<-RDP)
|
|
1075
|
-
full address:s:foo:rdpyeah
|
|
1076
|
-
prompt for credentials:i:1
|
|
1077
|
-
username:s:me
|
|
1078
|
-
RDP
|
|
1079
|
-
end
|
|
1080
|
-
|
|
1081
|
-
it "prints the rdp document on debug" do
|
|
1082
|
-
with_fake_fs do
|
|
1083
|
-
FileUtils.mkdir_p(File.dirname(rdp_doc))
|
|
1084
|
-
login_command
|
|
1085
|
-
end
|
|
1086
|
-
|
|
1087
|
-
expected = Kitchen::Util.outdent!(<<-OUTPUT)
|
|
1088
|
-
Creating RDP document for coolbeans (/i/am/root/.kitchen/coolbeans.rdp)
|
|
1089
|
-
------------
|
|
1090
|
-
full address:s:foo:rdpyeah
|
|
1091
|
-
prompt for credentials:i:1
|
|
1092
|
-
username:s:me
|
|
1093
|
-
------------
|
|
1094
|
-
OUTPUT
|
|
1095
|
-
debug_output(logged_output.string).must_match expected
|
|
1096
|
-
end
|
|
1097
|
-
|
|
1098
|
-
it "returns a LoginCommand which calls mstsc on the rdp document" do
|
|
1099
|
-
actual = nil
|
|
1100
|
-
with_fake_fs do
|
|
1101
|
-
FileUtils.mkdir_p(File.dirname(rdp_doc))
|
|
1102
|
-
actual = login_command
|
|
1103
|
-
end
|
|
1104
|
-
|
|
1105
|
-
actual.exec_args.must_equal ["mstsc", rdp_doc, {}]
|
|
1106
|
-
end
|
|
1107
|
-
end
|
|
1108
|
-
|
|
1109
|
-
describe "for Linux-based workstations" do
|
|
1110
|
-
before do
|
|
1111
|
-
RbConfig::CONFIG.stubs(:[]).with("host_os").returns("linux-gnu")
|
|
1112
|
-
end
|
|
1113
|
-
|
|
1114
|
-
it "returns a LoginCommand" do
|
|
1115
|
-
login_command.must_be_instance_of Kitchen::LoginCommand
|
|
1116
|
-
end
|
|
1117
|
-
|
|
1118
|
-
it "is an rdesktop command" do
|
|
1119
|
-
login_command.command.must_equal "rdesktop"
|
|
1120
|
-
args.must_match %r{ foo:rdpyeah$}
|
|
1121
|
-
end
|
|
1122
|
-
|
|
1123
|
-
it "sets the user" do
|
|
1124
|
-
args.must_match regexify("-u me ")
|
|
1125
|
-
end
|
|
1126
|
-
|
|
1127
|
-
it "sets the pass if given" do
|
|
1128
|
-
args.must_match regexify(" -p haha ")
|
|
1129
|
-
end
|
|
1130
|
-
|
|
1131
|
-
it "won't set the pass if not given" do
|
|
1132
|
-
options.delete(:password)
|
|
1133
|
-
|
|
1134
|
-
args.wont_match regexify(" -p haha ")
|
|
1135
|
-
end
|
|
1136
|
-
end
|
|
1137
|
-
|
|
1138
|
-
describe "for unknown workstation platforms" do
|
|
1139
|
-
before do
|
|
1140
|
-
RbConfig::CONFIG.stubs(:[]).with("host_os").returns("cray")
|
|
1141
|
-
end
|
|
1142
|
-
|
|
1143
|
-
it "raises an ActionFailed error" do
|
|
1144
|
-
err = proc { login_command }.must_raise Kitchen::ActionFailed
|
|
1145
|
-
err.message.must_equal "Remote login not supported in " \
|
|
1146
|
-
"Kitchen::Transport::Winrm::Connection from host OS 'cray'."
|
|
1147
|
-
end
|
|
1148
|
-
end
|
|
1149
|
-
end
|
|
1150
|
-
|
|
1151
|
-
describe "#upload" do
|
|
1152
|
-
before do
|
|
1153
|
-
winrm_session.stubs(:shell).with(:powershell).returns(executor)
|
|
1154
|
-
|
|
1155
|
-
WinRM::FS::Core::FileTransporter.stubs(:new)
|
|
1156
|
-
.with(executor).returns(transporter)
|
|
1157
|
-
transporter.stubs(:upload)
|
|
1158
|
-
end
|
|
1159
|
-
|
|
1160
|
-
def self.common_specs_for_upload
|
|
1161
|
-
it "builds a Winrm::FileTransporter" do
|
|
1162
|
-
WinRM::FS::Core::FileTransporter.unstub(:new)
|
|
1163
|
-
|
|
1164
|
-
WinRM::FS::Core::FileTransporter.expects(:new)
|
|
1165
|
-
.with(executor).returns(transporter)
|
|
1166
|
-
|
|
1167
|
-
upload
|
|
1168
|
-
end
|
|
1169
|
-
|
|
1170
|
-
it "reuses the Winrm::FileTransporter" do
|
|
1171
|
-
WinRM::FS::Core::FileTransporter.unstub(:new)
|
|
1172
|
-
|
|
1173
|
-
WinRM::FS::Core::FileTransporter.expects(:new)
|
|
1174
|
-
.with(executor).returns(transporter).once
|
|
1175
|
-
|
|
1176
|
-
upload
|
|
1177
|
-
upload
|
|
1178
|
-
upload
|
|
1179
|
-
end
|
|
1180
|
-
end
|
|
1181
|
-
|
|
1182
|
-
describe "for a file" do
|
|
1183
|
-
def upload # execute every time, not lazily once
|
|
1184
|
-
connection.upload("/tmp/file.txt", 'C:\\dest')
|
|
1185
|
-
end
|
|
1186
|
-
|
|
1187
|
-
common_specs_for_upload
|
|
1188
|
-
end
|
|
1189
|
-
|
|
1190
|
-
describe "for a collection of files" do
|
|
1191
|
-
def upload # execute every time, not lazily once
|
|
1192
|
-
connection.upload(%w{/tmp/file1.txt /tmp/file2.txt}, 'C:\\dest')
|
|
1193
|
-
end
|
|
1194
|
-
|
|
1195
|
-
common_specs_for_upload
|
|
1196
|
-
end
|
|
1197
|
-
end
|
|
1198
|
-
|
|
1199
|
-
describe "#wait_until_ready" do
|
|
1200
|
-
before do
|
|
1201
|
-
winrm_session.stubs(:shell).with(:powershell).returns(executor)
|
|
1202
|
-
options[:max_wait_until_ready] = 300
|
|
1203
|
-
end
|
|
1204
|
-
|
|
1205
|
-
describe "when connection is successful" do
|
|
1206
|
-
let(:response) do
|
|
1207
|
-
o = WinRM::Output.new
|
|
1208
|
-
o.exitcode = 0
|
|
1209
|
-
o << { stdout: "[WinRM] Established\r\n" }
|
|
1210
|
-
o
|
|
1211
|
-
end
|
|
1212
|
-
|
|
1213
|
-
before do
|
|
1214
|
-
executor.expects(:run)
|
|
1215
|
-
.with("Write-Host '[WinRM] Established\n'").returns(response)
|
|
1216
|
-
executor.expects(:close).once
|
|
1217
|
-
end
|
|
1218
|
-
|
|
1219
|
-
it "executes an empty command string to ensure working" do
|
|
1220
|
-
connection.wait_until_ready
|
|
1221
|
-
end
|
|
1222
|
-
end
|
|
1223
|
-
|
|
1224
|
-
describe "when connection suceeds but command fails, sad panda" do
|
|
1225
|
-
let(:response) do
|
|
1226
|
-
o = WinRM::Output.new
|
|
1227
|
-
o.exitcode = 42
|
|
1228
|
-
o << { stderr: "Ah crap.\r\n" }
|
|
1229
|
-
o
|
|
1230
|
-
end
|
|
1231
|
-
|
|
1232
|
-
before do
|
|
1233
|
-
executor.expects(:run)
|
|
1234
|
-
.with("Write-Host '[WinRM] Established\n'").returns(response)
|
|
1235
|
-
executor.expects(:close).once
|
|
1236
|
-
end
|
|
1237
|
-
|
|
1238
|
-
it "executes an empty command string to ensure working" do
|
|
1239
|
-
err = proc do
|
|
1240
|
-
connection.wait_until_ready
|
|
1241
|
-
end.must_raise Kitchen::Transport::WinrmFailed
|
|
1242
|
-
err.message.must_equal "WinRM exited (42) for command: " \
|
|
1243
|
-
"[Write-Host '[WinRM] Established\n']"
|
|
1244
|
-
end
|
|
1245
|
-
|
|
1246
|
-
it "stderr is printed on logger warn level" do
|
|
1247
|
-
begin
|
|
1248
|
-
connection.wait_until_ready
|
|
1249
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
|
1250
|
-
# the raise is not what is being tested here, rather its side-effect
|
|
1251
|
-
end
|
|
1252
|
-
|
|
1253
|
-
logged_output.string.must_match warn_line("Ah crap.\n")
|
|
1254
|
-
end
|
|
1255
|
-
end
|
|
1256
|
-
|
|
1257
|
-
describe "when connection is over HTTPS" do
|
|
1258
|
-
before do
|
|
1259
|
-
executor.expects(:run)
|
|
1260
|
-
.with("Write-Host '[WinRM] Established\n'").raises(OpenSSL::SSL::SSLError)
|
|
1261
|
-
executor.expects(:close)
|
|
1262
|
-
end
|
|
1263
|
-
|
|
1264
|
-
it "fails with SSL error" do
|
|
1265
|
-
proc do
|
|
1266
|
-
connection.wait_until_ready
|
|
1267
|
-
end.must_raise OpenSSL::SSL::SSLError
|
|
1268
|
-
end
|
|
1269
|
-
end
|
|
1270
|
-
|
|
1271
|
-
describe "when connection is over HTTPS and there are retries" do
|
|
1272
|
-
before do
|
|
1273
|
-
executor.expects(:run).times(2)
|
|
1274
|
-
.with("Write-Host '[WinRM] Established\n'").raises(OpenSSL::SSL::SSLError)
|
|
1275
|
-
executor.expects(:close).times(2)
|
|
1276
|
-
options[:connection_retries] = 1
|
|
1277
|
-
options[:connection_retry_sleep] = 1
|
|
1278
|
-
end
|
|
1279
|
-
|
|
1280
|
-
it "fails with SSL error" do
|
|
1281
|
-
proc do
|
|
1282
|
-
connection.wait_until_ready
|
|
1283
|
-
end.must_raise OpenSSL::SSL::SSLError
|
|
1284
|
-
end
|
|
1285
|
-
end
|
|
1286
|
-
end
|
|
1287
|
-
|
|
1288
|
-
def debug_output(output)
|
|
1289
|
-
regexp = /^D, .* DEBUG -- : /
|
|
1290
|
-
output.lines.grep(/^D, .* DEBUG -- : /).map { |l| l.sub(regexp, "") }.join
|
|
1291
|
-
end
|
|
1292
|
-
|
|
1293
|
-
def debug_line(msg)
|
|
1294
|
-
/^D, .* : #{Regexp.escape(msg)}$/
|
|
1295
|
-
end
|
|
1296
|
-
|
|
1297
|
-
def debug_line_with(msg)
|
|
1298
|
-
/^D, .* : #{Regexp.escape(msg)}/
|
|
1299
|
-
end
|
|
1300
|
-
|
|
1301
|
-
def info_line(msg)
|
|
1302
|
-
/^I, .* : #{Regexp.escape(msg)}$/
|
|
1303
|
-
end
|
|
1304
|
-
|
|
1305
|
-
def info_line_with(msg)
|
|
1306
|
-
/^I, .* : #{Regexp.escape(msg)}/
|
|
1307
|
-
end
|
|
1308
|
-
|
|
1309
|
-
def regexify(string)
|
|
1310
|
-
Regexp.new(Regexp.escape(string))
|
|
1311
|
-
end
|
|
1312
|
-
|
|
1313
|
-
def warn_line(msg)
|
|
1314
|
-
/^W, .* : #{Regexp.escape(msg)}$/
|
|
1315
|
-
end
|
|
1316
|
-
|
|
1317
|
-
def warn_line_with(msg)
|
|
1318
|
-
/^W, .* : #{Regexp.escape(msg)}/
|
|
1319
|
-
end
|
|
1320
|
-
end
|