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.
Files changed (254) hide show
  1. checksums.yaml +4 -4
  2. data/lib/kitchen/version.rb +1 -1
  3. data/support/chef-client-zero.rb +1 -1
  4. metadata +5 -324
  5. data/.gitattributes +0 -3
  6. data/.github/ISSUE_TEMPLATE.md +0 -56
  7. data/.github/lock.yml +0 -1
  8. data/.gitignore +0 -38
  9. data/.gitmodules +0 -0
  10. data/.kitchen.appveyor.yml +0 -25
  11. data/.kitchen.dokken.yml +0 -31
  12. data/.kitchen.proxy.yml +0 -27
  13. data/.rubocop.yml +0 -5
  14. data/.travis.yml +0 -57
  15. data/.yardopts +0 -3
  16. data/Berksfile +0 -3
  17. data/CHANGELOG.md +0 -1510
  18. data/CONTRIBUTING.md +0 -14
  19. data/ECOSYSTEM.md +0 -93
  20. data/Gemfile +0 -40
  21. data/Gemfile.proxy_tests +0 -4
  22. data/Guardfile +0 -42
  23. data/MAINTAINERS.md +0 -29
  24. data/README.md +0 -138
  25. data/RELEASE_NOTES.md +0 -167
  26. data/Rakefile +0 -77
  27. data/appveyor.yml +0 -47
  28. data/docs/CONTRIBUTING.md +0 -8
  29. data/docs/LICENSE +0 -22
  30. data/docs/README.md +0 -78
  31. data/docs/archetypes/default.md +0 -6
  32. data/docs/config.toml +0 -36
  33. data/docs/content/docs/_index.md +0 -5
  34. data/docs/content/docs/drivers/_index.md +0 -27
  35. data/docs/content/docs/drivers/azurerm.md +0 -44
  36. data/docs/content/docs/drivers/vagrant.md +0 -39
  37. data/docs/content/docs/getting-started/00-introduction.md +0 -14
  38. data/docs/content/docs/getting-started/01-installing.md +0 -64
  39. data/docs/content/docs/getting-started/02-getting-help.md +0 -59
  40. data/docs/content/docs/getting-started/03-creating-cookbook.md +0 -46
  41. data/docs/content/docs/getting-started/04-kitchen-yml.md +0 -56
  42. data/docs/content/docs/getting-started/05-instances.md +0 -79
  43. data/docs/content/docs/getting-started/06-writing-recipe.md +0 -21
  44. data/docs/content/docs/getting-started/07-running-converge.md +0 -134
  45. data/docs/content/docs/getting-started/08-manually-verifying.md +0 -55
  46. data/docs/content/docs/getting-started/09-writing-test.md +0 -49
  47. data/docs/content/docs/getting-started/10-running-verify.md +0 -120
  48. data/docs/content/docs/getting-started/11-running-test.md +0 -168
  49. data/docs/content/docs/getting-started/12-adding-platform.md +0 -206
  50. data/docs/content/docs/getting-started/13-adding-feature.md +0 -30
  51. data/docs/content/docs/getting-started/14-adding-suite.md +0 -60
  52. data/docs/content/docs/getting-started/15-adding-test.md +0 -66
  53. data/docs/content/docs/getting-started/16-adding-recipe.md +0 -53
  54. data/docs/content/docs/getting-started/17-excluding-platforms.md +0 -101
  55. data/docs/content/docs/getting-started/18-next-steps.md +0 -23
  56. data/docs/content/docs/getting-started/_index.md +0 -5
  57. data/docs/content/docs/provisioners/_index.md +0 -36
  58. data/docs/content/docs/provisioners/chef.md +0 -69
  59. data/docs/content/docs/provisioners/shell.md +0 -31
  60. data/docs/content/docs/reference/_index.md +0 -5
  61. data/docs/content/docs/reference/configuration.md +0 -53
  62. data/docs/content/docs/reference/examples.md +0 -97
  63. data/docs/content/docs/reference/faq.md +0 -58
  64. data/docs/content/docs/reference/fixtures.md +0 -32
  65. data/docs/content/docs/reference/glossary.md +0 -34
  66. data/docs/content/docs/reference/lifecycle-hooks.md +0 -68
  67. data/docs/content/docs/reference/reboots.md +0 -24
  68. data/docs/content/docs/verifiers/_index.md +0 -14
  69. data/docs/content/docs/verifiers/inspec.md +0 -44
  70. data/docs/content/docs/verifiers/serverspec.md +0 -20
  71. data/docs/static/images/chef-logo.png +0 -0
  72. data/docs/static/images/chef-logo.svg +0 -1
  73. data/docs/static/images/github-banner.png +0 -0
  74. data/docs/static/images/github-banner.svg +0 -71
  75. data/docs/static/images/kitchen-logo.png +0 -0
  76. data/docs/static/images/logo-block.svg +0 -222
  77. data/docs/static/images/logo.png +0 -0
  78. data/docs/static/images/logos-group.png +0 -0
  79. data/docs/static/images/terminal-1.png +0 -0
  80. data/docs/static/images/terminal-1.svg +0 -589
  81. data/docs/static/images/terminal-2.png +0 -0
  82. data/docs/static/images/terminal-2.svg +0 -235
  83. data/docs/static/images/terminal-3.png +0 -0
  84. data/docs/static/images/terminal-3.svg +0 -439
  85. data/docs/static/index.html +0 -59
  86. data/docs/static/javascripts/all.js +0 -348
  87. data/docs/static/javascripts/vendor/foundation.min.js +0 -4
  88. data/docs/static/javascripts/vendor/jquery.min.js +0 -5
  89. data/docs/static/javascripts/vendor/what-input.js +0 -336
  90. data/docs/static/stylesheets/site.css +0 -4667
  91. data/docs/themes/kitchen/layouts/_default/baseof.html +0 -53
  92. data/docs/themes/kitchen/layouts/_default/list.html +0 -4
  93. data/docs/themes/kitchen/layouts/_default/redirect.html +0 -10
  94. data/docs/themes/kitchen/layouts/_default/single.html +0 -6
  95. data/docs/themes/kitchen/layouts/partials/core/head.html +0 -6
  96. data/docs/themes/kitchen/layouts/partials/kitchen/footer.html +0 -18
  97. data/docs/themes/kitchen/layouts/partials/kitchen/head.html +0 -4
  98. data/docs/themes/kitchen/layouts/partials/kitchen/header.html +0 -26
  99. data/docs/themes/kitchen/layouts/partials/search-docs.html +0 -3
  100. data/docs/themes/kitchen/layouts/partials/sidebar.html +0 -33
  101. data/docs/themes/kitchen/layouts/shortcodes/button.html +0 -1
  102. data/docs/themes/kitchen/layouts/shortcodes/codeblock.html +0 -8
  103. data/docs/themes/kitchen/layouts/shortcodes/cta.html +0 -5
  104. data/docs/themes/kitchen/layouts/shortcodes/danger.html +0 -1
  105. data/docs/themes/kitchen/layouts/shortcodes/example_fqdn.html +0 -1
  106. data/docs/themes/kitchen/layouts/shortcodes/info.html +0 -1
  107. data/docs/themes/kitchen/layouts/shortcodes/ol-styled.html +0 -3
  108. data/docs/themes/kitchen/layouts/shortcodes/success.html +0 -1
  109. data/docs/themes/kitchen/layouts/shortcodes/tip.html +0 -1
  110. data/docs/themes/kitchen/layouts/shortcodes/warning.html +0 -1
  111. data/docs/themes/kitchen/static/css/kitchen.css +0 -10
  112. data/docs/themes/kitchen/static/css/kitchen.css.map +0 -7
  113. data/docs/themes/kitchen/static/fonts/Muli-Bold.ttf +0 -0
  114. data/docs/themes/kitchen/static/fonts/Muli-Regular.ttf +0 -0
  115. data/docs/themes/kitchen/static/fonts/Muli-SemiBold.ttf +0 -0
  116. data/docs/themes/kitchen/static/fonts/fontawesome/fa-brands-400.eot +0 -0
  117. data/docs/themes/kitchen/static/fonts/fontawesome/fa-brands-400.svg +0 -1104
  118. data/docs/themes/kitchen/static/fonts/fontawesome/fa-brands-400.ttf +0 -0
  119. data/docs/themes/kitchen/static/fonts/fontawesome/fa-brands-400.woff +0 -0
  120. data/docs/themes/kitchen/static/fonts/fontawesome/fa-brands-400.woff2 +0 -0
  121. data/docs/themes/kitchen/static/fonts/fontawesome/fa-regular-400.eot +0 -0
  122. data/docs/themes/kitchen/static/fonts/fontawesome/fa-regular-400.svg +0 -372
  123. data/docs/themes/kitchen/static/fonts/fontawesome/fa-regular-400.ttf +0 -0
  124. data/docs/themes/kitchen/static/fonts/fontawesome/fa-regular-400.woff +0 -0
  125. data/docs/themes/kitchen/static/fonts/fontawesome/fa-regular-400.woff2 +0 -0
  126. data/docs/themes/kitchen/static/fonts/fontawesome/fa-solid-900.eot +0 -0
  127. data/docs/themes/kitchen/static/fonts/fontawesome/fa-solid-900.svg +0 -1896
  128. data/docs/themes/kitchen/static/fonts/fontawesome/fa-solid-900.ttf +0 -0
  129. data/docs/themes/kitchen/static/fonts/fontawesome/fa-solid-900.woff +0 -0
  130. data/docs/themes/kitchen/static/fonts/fontawesome/fa-solid-900.woff2 +0 -0
  131. data/docs/themes/kitchen/static/images/chef-logo-light.svg +0 -36
  132. data/docs/themes/kitchen/static/images/chef-logo-white.svg +0 -38
  133. data/docs/themes/kitchen/static/images/chef-logo.svg +0 -37
  134. data/docs/themes/kitchen/static/images/favicon.ico +0 -0
  135. data/docs/themes/kitchen/static/js/scripts-all.js +0 -7
  136. data/docs/themes/kitchen/static/js/source/chef-hugo.js +0 -116
  137. data/docs/themes/kitchen/static/js/source/omnitruck.js +0 -82
  138. data/docs/themes/kitchen/static/js/source/segment.js +0 -52
  139. data/docs/themes/kitchen/static/sass/_buttons.scss +0 -161
  140. data/docs/themes/kitchen/static/sass/_core.scss +0 -24
  141. data/docs/themes/kitchen/static/sass/_forms.scss +0 -14
  142. data/docs/themes/kitchen/static/sass/_mixins.scss +0 -133
  143. data/docs/themes/kitchen/static/sass/_typography.scss +0 -34
  144. data/docs/themes/kitchen/static/sass/_variables.scss +0 -82
  145. data/docs/themes/kitchen/static/sass/kitchen.scss +0 -7
  146. data/docs/themes/kitchen/static/sass/kitchen/_footer.scss +0 -50
  147. data/docs/themes/kitchen/static/sass/kitchen/_header.scss +0 -187
  148. data/docs/themes/kitchen/static/sass/kitchen/_homepage.scss +0 -27
  149. data/docs/themes/kitchen/static/sass/kitchen/_utility-bar.scss +0 -173
  150. data/docs/themes/kitchen/static/sass/partials/_alerts.scss +0 -32
  151. data/docs/themes/kitchen/static/sass/partials/_bg.scss +0 -19
  152. data/docs/themes/kitchen/static/sass/partials/_blurbs.scss +0 -25
  153. data/docs/themes/kitchen/static/sass/partials/_callout.scss +0 -15
  154. data/docs/themes/kitchen/static/sass/partials/_cards.scss +0 -54
  155. data/docs/themes/kitchen/static/sass/partials/_dropdown.scss +0 -77
  156. data/docs/themes/kitchen/static/sass/partials/_grid.scss +0 -87
  157. data/docs/themes/kitchen/static/sass/partials/_padding.scss +0 -73
  158. data/docs/themes/kitchen/static/sass/partials/_sidebar.scss +0 -71
  159. data/docs/themes/kitchen/static/sass/partials/_tabs.scss +0 -125
  160. data/docs/themes/kitchen/static/sass/typography/_chroma.scss +0 -366
  161. data/docs/themes/kitchen/static/sass/typography/_code.scss +0 -72
  162. data/docs/themes/kitchen/static/sass/typography/_headers.scss +0 -90
  163. data/docs/themes/kitchen/static/sass/typography/_links.scss +0 -127
  164. data/docs/themes/kitchen/static/sass/typography/_lists.scss +0 -155
  165. data/docs/themes/kitchen/static/sass/typography/_prose.scss +0 -29
  166. data/docs/themes/kitchen/static/sass/typography/_text.scss +0 -221
  167. data/docs/themes/kitchen/static/sass/vendor/fontawesome/_animated.scss +0 -20
  168. data/docs/themes/kitchen/static/sass/vendor/fontawesome/_bordered-pulled.scss +0 -20
  169. data/docs/themes/kitchen/static/sass/vendor/fontawesome/_core.scss +0 -16
  170. data/docs/themes/kitchen/static/sass/vendor/fontawesome/_fixed-width.scss +0 -6
  171. data/docs/themes/kitchen/static/sass/vendor/fontawesome/_icons.scss +0 -992
  172. data/docs/themes/kitchen/static/sass/vendor/fontawesome/_larger.scss +0 -23
  173. data/docs/themes/kitchen/static/sass/vendor/fontawesome/_list.scss +0 -18
  174. data/docs/themes/kitchen/static/sass/vendor/fontawesome/_mixins.scss +0 -57
  175. data/docs/themes/kitchen/static/sass/vendor/fontawesome/_rotated-flipped.scss +0 -23
  176. data/docs/themes/kitchen/static/sass/vendor/fontawesome/_screen-reader.scss +0 -5
  177. data/docs/themes/kitchen/static/sass/vendor/fontawesome/_stacked.scss +0 -31
  178. data/docs/themes/kitchen/static/sass/vendor/fontawesome/_variables.scss +0 -1005
  179. data/docs/themes/kitchen/static/sass/vendor/fontawesome/fa-brands.scss +0 -21
  180. data/docs/themes/kitchen/static/sass/vendor/fontawesome/fa-regular.scss +0 -22
  181. data/docs/themes/kitchen/static/sass/vendor/fontawesome/fa-solid.scss +0 -23
  182. data/docs/themes/kitchen/static/sass/vendor/fontawesome/fontawesome.scss +0 -16
  183. data/docs/themes/kitchen/theme.toml +0 -8
  184. data/features/kitchen_action_commands.feature +0 -164
  185. data/features/kitchen_command.feature +0 -16
  186. data/features/kitchen_console_command.feature +0 -35
  187. data/features/kitchen_defaults.feature +0 -38
  188. data/features/kitchen_diagnose_command.feature +0 -96
  189. data/features/kitchen_help_command.feature +0 -16
  190. data/features/kitchen_init_command.feature +0 -254
  191. data/features/kitchen_list_command.feature +0 -140
  192. data/features/kitchen_login_command.feature +0 -62
  193. data/features/kitchen_sink_command.feature +0 -30
  194. data/features/kitchen_test_command.feature +0 -88
  195. data/features/step_definitions/gem_steps.rb +0 -24
  196. data/features/step_definitions/git_steps.rb +0 -5
  197. data/features/step_definitions/output_steps.rb +0 -5
  198. data/features/support/env.rb +0 -74
  199. data/spec/kitchen/base64_stream_spec.rb +0 -74
  200. data/spec/kitchen/cli_spec.rb +0 -54
  201. data/spec/kitchen/collection_spec.rb +0 -76
  202. data/spec/kitchen/color_spec.rb +0 -51
  203. data/spec/kitchen/config_spec.rb +0 -434
  204. data/spec/kitchen/configurable_spec.rb +0 -1113
  205. data/spec/kitchen/data_munger_spec.rb +0 -2800
  206. data/spec/kitchen/diagnostic_spec.rb +0 -128
  207. data/spec/kitchen/driver/base_spec.rb +0 -132
  208. data/spec/kitchen/driver/dummy_spec.rb +0 -193
  209. data/spec/kitchen/driver/exec_spec.rb +0 -75
  210. data/spec/kitchen/driver/proxy_spec.rb +0 -127
  211. data/spec/kitchen/driver/ssh_base_spec.rb +0 -1136
  212. data/spec/kitchen/driver_spec.rb +0 -106
  213. data/spec/kitchen/errors_spec.rb +0 -317
  214. data/spec/kitchen/instance_spec.rb +0 -1372
  215. data/spec/kitchen/lazy_hash_spec.rb +0 -113
  216. data/spec/kitchen/lifecycle_hooks_spec.rb +0 -171
  217. data/spec/kitchen/loader/yaml_spec.rb +0 -787
  218. data/spec/kitchen/logger_spec.rb +0 -425
  219. data/spec/kitchen/logging_spec.rb +0 -56
  220. data/spec/kitchen/login_command_spec.rb +0 -67
  221. data/spec/kitchen/metadata_chopper_spec.rb +0 -79
  222. data/spec/kitchen/platform_spec.rb +0 -88
  223. data/spec/kitchen/provisioner/base_spec.rb +0 -393
  224. data/spec/kitchen/provisioner/chef/policyfile_spec.rb +0 -140
  225. data/spec/kitchen/provisioner/chef_apply_spec.rb +0 -131
  226. data/spec/kitchen/provisioner/chef_base_spec.rb +0 -1565
  227. data/spec/kitchen/provisioner/chef_solo_spec.rb +0 -602
  228. data/spec/kitchen/provisioner/chef_zero_spec.rb +0 -1013
  229. data/spec/kitchen/provisioner/dummy_spec.rb +0 -96
  230. data/spec/kitchen/provisioner/shell_spec.rb +0 -623
  231. data/spec/kitchen/provisioner_spec.rb +0 -101
  232. data/spec/kitchen/shell_out_spec.rb +0 -146
  233. data/spec/kitchen/ssh_spec.rb +0 -584
  234. data/spec/kitchen/state_file_spec.rb +0 -122
  235. data/spec/kitchen/suite_spec.rb +0 -61
  236. data/spec/kitchen/transport/base_spec.rb +0 -140
  237. data/spec/kitchen/transport/exec_spec.rb +0 -79
  238. data/spec/kitchen/transport/ssh_spec.rb +0 -1317
  239. data/spec/kitchen/transport/winrm_spec.rb +0 -1320
  240. data/spec/kitchen/transport_spec.rb +0 -106
  241. data/spec/kitchen/util_spec.rb +0 -250
  242. data/spec/kitchen/verifier/base_spec.rb +0 -346
  243. data/spec/kitchen/verifier/busser_spec.rb +0 -580
  244. data/spec/kitchen/verifier/dummy_spec.rb +0 -96
  245. data/spec/kitchen/verifier/shell_spec.rb +0 -157
  246. data/spec/kitchen/verifier_spec.rb +0 -114
  247. data/spec/kitchen_spec.rb +0 -112
  248. data/spec/spec_helper.rb +0 -110
  249. data/spec/support/powershell_max_size_spec.rb +0 -39
  250. data/test-kitchen.gemspec +0 -49
  251. data/test/cookbooks/test_cookbook/metadata.rb +0 -6
  252. data/test/cookbooks/test_cookbook/recipes/default.rb +0 -1
  253. data/test/integration/default/default_spec.rb +0 -3
  254. 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