test-kitchen 1.23.3 → 1.23.4

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