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,122 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
- #
5
- # Copyright (C) 2013, Fletcher Nichol
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/errors"
22
- require "kitchen/state_file"
23
- require "kitchen/util"
24
-
25
- class YamledState
26
- attr_accessor :yoinks
27
- end
28
-
29
- describe Kitchen::StateFile do
30
- let(:state_file) { Kitchen::StateFile.new("/tmp", "oftheunion") }
31
- let(:file_name) { "/tmp/.kitchen/oftheunion.yml" }
32
-
33
- before do
34
- FakeFS.activate!
35
- FileUtils.mkdir_p("/tmp")
36
- end
37
-
38
- after do
39
- FakeFS.deactivate!
40
- FakeFS::FileSystem.clear
41
- end
42
-
43
- describe "#read" do
44
- it "returns an empty hash if the file does not exist" do
45
- state_file.read.must_equal({})
46
- end
47
-
48
- it "returns and empty hash if the file is zero length" do
49
- stub_state_file!("")
50
-
51
- state_file.read.must_equal({})
52
- end
53
-
54
- it "returns a Hash with symbolized keys from the state file" do
55
- stub_state_file!
56
-
57
- state_file.read.must_equal(
58
- cloud_id: 42,
59
- flavor: "extra_crispy"
60
- )
61
- end
62
-
63
- it "arbitrary objects aren't deserialized from state file" do
64
- stub_state_file! <<-'YAML'.gsub(/^ {8}/, "")
65
- --- !ruby/object:YamledState
66
- yoinks: zoinks
67
- YAML
68
-
69
- proc { state_file.read }.must_raise Kitchen::StateFileLoadError
70
- end
71
-
72
- it "raises a StateFileLoadError if the state file cannot be parsed" do
73
- stub_state_file!("&*%^*")
74
-
75
- proc { state_file.read }.must_raise Kitchen::StateFileLoadError
76
- end
77
- end
78
-
79
- describe "#write" do
80
- it "creates the directory path to the state file" do
81
- File.directory?("/tmp/.kitchen").must_equal false
82
- state_file.write({})
83
- File.directory?("/tmp/.kitchen").must_equal true
84
- end
85
-
86
- it "writes a state file with stringified keys" do
87
- state_file.write(thekey: "thyself")
88
-
89
- IO.read(file_name).split("\n").must_include "thekey: thyself"
90
- end
91
- end
92
-
93
- describe "#destroy" do
94
- it "executes if no file exists" do
95
- File.exist?(file_name).must_equal false
96
- state_file.destroy
97
- File.exist?(file_name).must_equal false
98
- end
99
-
100
- it "deletes the state file" do
101
- stub_state_file!
102
- state_file.destroy
103
-
104
- File.exist?(file_name).must_equal false
105
- end
106
- end
107
-
108
- private
109
-
110
- def stub_state_file!(yaml_string = nil)
111
- if yaml_string.nil?
112
- yaml_string = <<-'YAML'.gsub(/^ {8}/, "")
113
- ---
114
- cloud_id: 42
115
- flavor: extra_crispy
116
- YAML
117
- end
118
-
119
- FileUtils.mkdir_p(File.dirname(file_name))
120
- File.open(file_name, "wb") { |f| f.write(yaml_string) }
121
- end
122
- end
@@ -1,61 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
- #
5
- # Copyright (C) 2012, Fletcher Nichol
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/errors"
22
- require "kitchen/suite"
23
-
24
- describe Kitchen::Suite do
25
- let(:opts) do
26
- {
27
- name: "suitezy",
28
- includes: %w{testbuntu testcent},
29
- excludes: %w{prodbuntu},
30
- }
31
- end
32
-
33
- let(:suite) { Kitchen::Suite.new(opts) }
34
-
35
- it "returns the name" do
36
- suite.name.must_equal "suitezy"
37
- end
38
-
39
- it "raises an ArgumentError if name is missing" do
40
- opts.delete(:name)
41
- proc { Kitchen::Suite.new(opts) }.must_raise Kitchen::ClientError
42
- end
43
-
44
- it "returns the includes" do
45
- suite.includes.must_equal %w{testbuntu testcent}
46
- end
47
-
48
- it "returns an empty Array when includes not given" do
49
- opts.delete(:includes)
50
- suite.includes.must_equal []
51
- end
52
-
53
- it "returns the excludes" do
54
- suite.excludes.must_equal %w{prodbuntu}
55
- end
56
-
57
- it "returns an empty Array when excludes not given" do
58
- opts.delete(:excludes)
59
- suite.excludes.must_equal []
60
- end
61
- end
@@ -1,140 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
- #
5
- # Copyright (C) 2015, Fletcher Nichol
6
- #
7
- # Licensed under the Apache License, Version 2.0 (the "License");
8
- # you may not use this file except in compliance with the License.
9
- # You may obtain a copy of the License at
10
- #
11
- # http://www.apache.org/licenses/LICENSE-2.0
12
- #
13
- # Unless required by applicable law or agreed to in writing, software
14
- # distributed under the License is distributed on an "AS IS" BASIS,
15
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- # See the License for the specific language governing permissions and
17
- # limitations under the License.
18
-
19
- require_relative "../../spec_helper"
20
-
21
- require "kitchen"
22
-
23
- describe Kitchen::Transport::Base do
24
- let(:logged_output) { StringIO.new }
25
- let(:logger) { Logger.new(logged_output) }
26
- let(:config) { Hash.new }
27
-
28
- let(:instance) do
29
- stub(name: "coolbeans", logger: logger)
30
- end
31
-
32
- let(:transport) do
33
- Kitchen::Transport::Base.new(config).finalize_config!(instance)
34
- end
35
-
36
- it "has an #connection method which raises a ClientError" do
37
- proc { transport.connection({}) }.must_raise Kitchen::ClientError
38
- end
39
-
40
- describe "#logger" do
41
- before { @klog = Kitchen.logger }
42
- after { Kitchen.logger = @klog }
43
-
44
- it "returns the instance's logger" do
45
- transport.send(:logger).must_equal logger
46
- end
47
-
48
- it "returns the default logger if instance's logger is not set" do
49
- transport = Kitchen::Transport::Base.new(config)
50
- Kitchen.logger = "yep"
51
-
52
- transport.send(:logger).must_equal Kitchen.logger
53
- end
54
- end
55
-
56
- describe Kitchen::Transport::TransportFailed do
57
- let(:failure_with_no_exit_code) { Kitchen::Transport::TransportFailed.new("Boom") }
58
- let(:failure_with_exit_code) { Kitchen::Transport::TransportFailed.new("Boom", 123) }
59
-
60
- describe "when no exit code is provided" do
61
- it "#exit_code is nil" do
62
- failure_with_no_exit_code.exit_code.must_be_nil
63
- end
64
- end
65
-
66
- describe "when an exit code is provided" do
67
- it "#exit_code returns the supplied exit code" do
68
- failure_with_exit_code.exit_code.must_equal 123
69
- end
70
- end
71
- end
72
- end
73
-
74
- describe Kitchen::Transport::Base::Connection do
75
- let(:logged_output) { StringIO.new }
76
- let(:logger) { Logger.new(logged_output) }
77
- let(:options) { { logger: logger } }
78
-
79
- let(:connection) do
80
- Kitchen::Transport::Base::Connection.new(options)
81
- end
82
-
83
- it "has a #close method that does nothing" do
84
- connection.close.must_be_nil
85
- end
86
-
87
- it "has an #execute method which raises a ClientError" do
88
- proc { connection.execute("boo") }.must_raise Kitchen::ClientError
89
- end
90
-
91
- it "has a #login_command method which raises an ActionFailed" do
92
- proc { connection.login_command }.must_raise Kitchen::ActionFailed
93
- end
94
-
95
- it "has an #upload method which raises a ClientError" do
96
- proc { connection.upload(["file"], "/path/to") }
97
- .must_raise Kitchen::ClientError
98
- end
99
-
100
- it "has an #download method which raises a ClientError" do
101
- proc { connection.download(["remote"], "local") }
102
- .must_raise Kitchen::ClientError
103
- end
104
-
105
- it "has a #wait_until_ready method that does nothing" do
106
- connection.wait_until_ready.must_be_nil
107
- end
108
-
109
- describe "#execute_with_retry" do
110
- let(:failure_with_exit_code) { Kitchen::Transport::TransportFailed.new("Boom", 123) }
111
-
112
- it "raises ClientError with no retries" do
113
- proc { connection.execute_with_retry("hi", [], nil, nil) }
114
- .must_raise Kitchen::ClientError
115
- end
116
-
117
- it "retries three times" do
118
- connection.expects(:execute).with("Hi").returns("Hello")
119
- connection.expects(:debug).with("Attempting to execute command - try 3 of 3.")
120
- connection.expects(:execute).with("Hi").raises(failure_with_exit_code)
121
- connection.expects(:debug).with("Attempting to execute command - try 2 of 3.")
122
- connection.expects(:execute).with("Hi").raises(failure_with_exit_code)
123
- connection.expects(:debug).with("Attempting to execute command - try 1 of 3.")
124
-
125
- connection.execute_with_retry("Hi", [123], 3, 1).must_equal "Hello"
126
- end
127
- end
128
-
129
- describe "#retry?" do
130
- it "raises an exception when multiple retryable exit codes are passed as a String" do
131
- proc { connection.retry?(2, 2, "35 1", 35) }
132
- .must_raise("undefined method `flatten' for \"35 1\":String")
133
- end
134
-
135
- it "returns true when the retryable exit codes are formatted in a nested array" do
136
- connection.retry?(1, 2, [[35, 1]], 35).must_equal true
137
- end
138
- end
139
-
140
- end
@@ -1,79 +0,0 @@
1
- #
2
- # Licensed under the Apache License, Version 2.0 (the "License");
3
- # you may not use this file except in compliance with the License.
4
- # You may obtain a copy of the License at
5
- #
6
- # http://www.apache.org/licenses/LICENSE-2.0
7
- #
8
- # Unless required by applicable law or agreed to in writing, software
9
- # distributed under the License is distributed on an "AS IS" BASIS,
10
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
- # See the License for the specific language governing permissions and
12
- # limitations under the License.
13
- #
14
-
15
- require_relative "../../spec_helper"
16
-
17
- require "kitchen/transport/exec"
18
-
19
- describe Kitchen::Transport::Ssh do
20
- let(:logged_output) { StringIO.new }
21
- let(:logger) { Logger.new(logged_output) }
22
- let(:config) { Hash.new }
23
- let(:state) { Hash.new }
24
-
25
- let(:instance) do
26
- stub(name: "coolbeans", logger: logger, to_str: "instance")
27
- end
28
-
29
- let(:transport) do
30
- Kitchen::Transport::Exec.new(config).finalize_config!(instance)
31
- end
32
-
33
- it "provisioner api_version is 1" do
34
- transport.diagnose_plugin[:api_version].must_equal 1
35
- end
36
-
37
- it "plugin_version is set to Kitchen::VERSION" do
38
- transport.diagnose_plugin[:version].must_equal Kitchen::VERSION
39
- end
40
-
41
- describe "#connection" do
42
- it "returns a Kitchen::Transport::Exec::Connection object" do
43
- transport.connection(state).must_be_kind_of Kitchen::Transport::Exec::Connection
44
- end
45
- end
46
- end
47
-
48
- describe Kitchen::Transport::Exec::Connection do
49
- let(:logged_output) { StringIO.new }
50
- let(:logger) { Logger.new(logged_output) }
51
-
52
- let(:options) do
53
- { logger: logger }
54
- end
55
-
56
- let(:connection) do
57
- Kitchen::Transport::Exec::Connection.new(options)
58
- end
59
-
60
- describe "#execute" do
61
- it "runs the command" do
62
- connection.expects(:run_command).with("do the thing")
63
- connection.execute("do the thing")
64
- end
65
-
66
- it "ignores nil" do
67
- connection.expects(:run_command).never
68
- connection.execute(nil)
69
- end
70
- end
71
-
72
- describe "#upload" do
73
- it "copies files" do
74
- FileUtils.expects(:mkdir_p).with("/tmp/kitchen")
75
- FileUtils.expects(:cp_r).with("/tmp/sandbox/cookbooks", "/tmp/kitchen")
76
- connection.upload(%w{/tmp/sandbox/cookbooks}, "/tmp/kitchen")
77
- end
78
- end
79
- end
@@ -1,1317 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
- #
5
- # Copyright (C) 2015, Fletcher Nichol
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/ssh"
22
- require "net/ssh/test"
23
-
24
- describe Kitchen::Transport::Ssh do
25
- let(:logged_output) { StringIO.new }
26
- let(:logger) { Logger.new(logged_output) }
27
- let(:config) { Hash.new }
28
- let(:state) { Hash.new }
29
-
30
- let(:instance) do
31
- stub(name: "coolbeans", logger: logger, to_str: "instance")
32
- end
33
-
34
- let(:transport) do
35
- Net::SSH::Test::Extensions::IO.with_test_extension { Kitchen::Transport::Ssh.new(config).finalize_config!(instance) }
36
- end
37
-
38
- it "provisioner api_version is 1" do
39
- transport.diagnose_plugin[:api_version].must_equal 1
40
- end
41
-
42
- it "plugin_version is set to Kitchen::VERSION" do
43
- transport.diagnose_plugin[:version].must_equal Kitchen::VERSION
44
- end
45
-
46
- describe "default_config" do
47
- it "sets :port to 22 by default" do
48
- transport[:port].must_equal 22
49
- end
50
-
51
- it "sets :username to root by default" do
52
- transport[:username].must_equal "root"
53
- end
54
-
55
- it "sets :compression to true by default" do
56
- transport[:compression].must_equal false
57
- end
58
-
59
- it "sets :compression to false if set to none" do
60
- config[:compression] = "none"
61
-
62
- transport[:compression].must_equal false
63
- end
64
-
65
- it "sets :compression to zlib@openssh.com if set to zlib" do
66
- config[:compression] = "zlib"
67
-
68
- transport[:compression].must_equal "zlib@openssh.com"
69
- end
70
-
71
- it "sets :compression_level to 6 by default" do
72
- transport[:compression_level].must_equal 0
73
- end
74
-
75
- it "sets :compression_level to 6 if :compression is set to true" do
76
- config[:compression] = true
77
-
78
- transport[:compression_level].must_equal 6
79
- end
80
-
81
- it "sets :keepalive to true by default" do
82
- transport[:keepalive].must_equal true
83
- end
84
-
85
- it "sets :keepalive_interval to 60 by default" do
86
- transport[:keepalive_interval].must_equal 60
87
- end
88
-
89
- it "sets :connection_timeout to 15 by default" do
90
- transport[:connection_timeout].must_equal 15
91
- end
92
-
93
- it "sets :connection_retries to 5 by default" do
94
- transport[:connection_retries].must_equal 5
95
- end
96
-
97
- it "sets :connection_retry_sleep to 1 by default" do
98
- transport[:connection_retry_sleep].must_equal 1
99
- end
100
-
101
- it "sets :max_wait_until_ready to 600 by default" do
102
- transport[:max_wait_until_ready].must_equal 600
103
- end
104
-
105
- it "sets :ssh_key to nil by default" do
106
- transport[:ssh_key].must_be_nil
107
- end
108
-
109
- it "sets :ssh_key_only to nil by default" do
110
- transport[:ssh_key_only].must_be_nil
111
- end
112
-
113
- it "expands :ssh_path path if set" do
114
- config[:kitchen_root] = "/rooty"
115
- config[:ssh_key] = "my_key"
116
-
117
- transport[:ssh_key].must_equal os_safe_root_path("/rooty/my_key")
118
- end
119
-
120
- it "sets :max_ssh_sessions to 9 by default" do
121
- transport[:max_ssh_sessions].must_equal 9
122
- end
123
-
124
- it "sets :ssh_http_proxy to nil by default" do
125
- transport[:ssh_http_proxy].must_be_nil
126
- end
127
-
128
- it "sets :ssh_http_proxy_port to nil by default" do
129
- transport[:ssh_http_proxy_port].must_be_nil
130
- end
131
-
132
- it "sets :ssh_http_proxy_user to nil by default" do
133
- transport[:ssh_http_proxy_user].must_be_nil
134
- end
135
-
136
- it "sets :ssh_http_proxy_password to nil by default" do
137
- transport[:ssh_http_proxy_password].must_be_nil
138
- end
139
-
140
- it "sets :ssh_gateway to nil by default" do
141
- transport[:ssh_gateway].must_be_nil
142
- end
143
-
144
- it "sets :ssh_gateway_username to nil by default" do
145
- transport[:ssh_gateway_username].must_be_nil
146
- end
147
-
148
- it "sets :ssh_gateway_port to 22 by default" do
149
- transport[:ssh_gateway_port].must_equal 22
150
- end
151
- end
152
-
153
- describe "#connection" do
154
- let(:klass) { Kitchen::Transport::Ssh::Connection }
155
- let(:options_http_proxy) { Hash.new }
156
- let(:proxy_conn) do
157
- state[:ssh_http_proxy] = "ssh_http_proxy_from_state"
158
- state[:ssh_http_proxy_port] = "ssh_http_proxy_port_from_state"
159
- options_http_proxy[:user] = state[:ssh_http_proxy_user]
160
- options_http_proxy[:password] = state[:ssh_http_proxy_password]
161
- Net::SSH::Proxy::HTTP.new(state[:ssh_http_proxy], state[:ssh_http_proxy_port], options_http_proxy)
162
- end
163
-
164
- # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
165
- def self.common_connection_specs
166
- before do
167
- Net::SSH::Proxy::HTTP.stubs(:new).returns(proxy_conn)
168
- end
169
-
170
- it "returns a Kitchen::Transport::Ssh::Connection object" do
171
- transport.connection(state).must_be_kind_of klass
172
- end
173
-
174
- it "sets the :logger to the transport's logger" do
175
- klass.expects(:new).with do |hash|
176
- hash[:logger] == logger
177
- end
178
-
179
- make_connection
180
- end
181
-
182
- it "sets the :user_known_hosts_file to /dev/null" do
183
- klass.expects(:new).with do |hash|
184
- hash[:user_known_hosts_file] == "/dev/null"
185
- end
186
-
187
- make_connection
188
- end
189
-
190
- it "sets the :verify_host_key flag to false" do
191
- klass.expects(:new).with do |hash|
192
- hash[:verify_host_key] == false
193
- end
194
-
195
- make_connection
196
- end
197
-
198
- it "sets :hostname from config" do
199
- config[:hostname] = "host_from_config"
200
-
201
- klass.expects(:new).with do |hash|
202
- hash[:hostname] == "host_from_config"
203
- end
204
-
205
- make_connection
206
- end
207
-
208
- it "sets :hostname from state over config data" do
209
- state[:hostname] = "host_from_state"
210
- config[:hostname] = "host_from_config"
211
-
212
- klass.expects(:new).with do |hash|
213
- hash[:hostname] == "host_from_state"
214
- end
215
-
216
- make_connection
217
- end
218
-
219
- it "sets :port from config" do
220
- config[:port] = "port_from_config"
221
-
222
- klass.expects(:new).with do |hash|
223
- hash[:port] == "port_from_config"
224
- end
225
-
226
- make_connection
227
- end
228
-
229
- it "sets :port from state over config data" do
230
- state[:port] = "port_from_state"
231
- config[:port] = "port_from_config"
232
-
233
- klass.expects(:new).with do |hash|
234
- hash[:port] == "port_from_state"
235
- end
236
-
237
- make_connection
238
- end
239
-
240
- it "sets :username from config" do
241
- config[:username] = "user_from_config"
242
-
243
- klass.expects(:new).with do |hash|
244
- hash[:username] == "user_from_config"
245
- end
246
-
247
- make_connection
248
- end
249
-
250
- it "sets :username from state over config data" do
251
- state[:username] = "user_from_state"
252
- config[:username] = "user_from_config"
253
-
254
- klass.expects(:new).with do |hash|
255
- hash[:username] == "user_from_state"
256
- end
257
-
258
- make_connection
259
- end
260
-
261
- it "sets :compression from config" do
262
- config[:compression] = "none"
263
-
264
- klass.expects(:new).with do |hash|
265
- hash[:compression] == false
266
- end
267
-
268
- make_connection
269
- end
270
-
271
- it "sets :compression from state over config data" do
272
- state[:compression] = "none"
273
- config[:compression] = "zlib"
274
-
275
- klass.expects(:new).with do |hash|
276
- hash[:compression] == "none"
277
- end
278
-
279
- make_connection
280
- end
281
-
282
- it "sets :compression_level from config" do
283
- config[:compression_level] = 9999
284
-
285
- klass.expects(:new).with do |hash|
286
- hash[:compression_level] == 9999
287
- end
288
-
289
- make_connection
290
- end
291
-
292
- it "sets :compression_level from state over config data" do
293
- state[:compression_level] = 9999
294
- config[:compression_level] = 1111
295
-
296
- klass.expects(:new).with do |hash|
297
- hash[:compression_level] == 9999
298
- end
299
-
300
- make_connection
301
- end
302
-
303
- it "sets :timeout from :connection_timeout in config" do
304
- config[:connection_timeout] = "timeout_from_config"
305
-
306
- klass.expects(:new).with do |hash|
307
- hash[:timeout] == "timeout_from_config"
308
- end
309
-
310
- make_connection
311
- end
312
-
313
- it "sets :timeout from :connection_timeout in state over config data" do
314
- state[:connection_timeout] = "timeout_from_state"
315
- config[:connection_timeout] = "timeout_from_config"
316
-
317
- klass.expects(:new).with do |hash|
318
- hash[:timeout] == "timeout_from_state"
319
- end
320
-
321
- make_connection
322
- end
323
-
324
- it "sets :keepalive from config" do
325
- config[:keepalive] = "keepalive_from_config"
326
-
327
- klass.expects(:new).with do |hash|
328
- hash[:keepalive] == "keepalive_from_config"
329
- end
330
-
331
- make_connection
332
- end
333
-
334
- it "sets :keepalive from state over config data" do
335
- state[:keepalive] = "keepalive_from_state"
336
- config[:keepalive] = "keepalive_from_config"
337
-
338
- klass.expects(:new).with do |hash|
339
- hash[:keepalive] == "keepalive_from_state"
340
- end
341
-
342
- make_connection
343
- end
344
-
345
- it "sets :keepalive_interval from config" do
346
- config[:keepalive_interval] = "interval_from_config"
347
-
348
- klass.expects(:new).with do |hash|
349
- hash[:keepalive_interval] == "interval_from_config"
350
- end
351
-
352
- make_connection
353
- end
354
-
355
- it "sets :keepalive_interval from state over config data" do
356
- state[:keepalive_interval] = "interval_from_state"
357
- config[:keepalive_interval] = "interval_from_config"
358
-
359
- klass.expects(:new).with do |hash|
360
- hash[:keepalive_interval] == "interval_from_state"
361
- end
362
-
363
- make_connection
364
- end
365
-
366
- it "sets :connection_retries from config" do
367
- config[:connection_retries] = "retries_from_config"
368
-
369
- klass.expects(:new).with do |hash|
370
- hash[:connection_retries] == "retries_from_config"
371
- end
372
-
373
- make_connection
374
- end
375
-
376
- it "sets :connection_retries from state over config data" do
377
- state[:connection_retries] = "retries_from_state"
378
- config[:connection_retries] = "retries_from_config"
379
-
380
- klass.expects(:new).with do |hash|
381
- hash[:connection_retries] == "retries_from_state"
382
- end
383
-
384
- make_connection
385
- end
386
-
387
- it "sets :connection_retry_sleep from config" do
388
- config[:connection_retry_sleep] = "sleep_from_config"
389
-
390
- klass.expects(:new).with do |hash|
391
- hash[:connection_retry_sleep] == "sleep_from_config"
392
- end
393
-
394
- make_connection
395
- end
396
-
397
- it "sets :connection_retry_sleep from state over config data" do
398
- state[:connection_retry_sleep] = "sleep_from_state"
399
- config[:connection_retry_sleep] = "sleep_from_config"
400
-
401
- klass.expects(:new).with do |hash|
402
- hash[:connection_retry_sleep] == "sleep_from_state"
403
- end
404
-
405
- make_connection
406
- end
407
-
408
- it "sets :max_wait_until_ready from config" do
409
- config[:max_wait_until_ready] = "max_from_config"
410
-
411
- klass.expects(:new).with do |hash|
412
- hash[:max_wait_until_ready] == "max_from_config"
413
- end
414
-
415
- make_connection
416
- end
417
-
418
- it "sets :max_wait_until_ready from state over config data" do
419
- state[:max_wait_until_ready] = "max_from_state"
420
- config[:max_wait_until_ready] = "max_from_config"
421
-
422
- klass.expects(:new).with do |hash|
423
- hash[:max_wait_until_ready] == "max_from_state"
424
- end
425
-
426
- make_connection
427
- end
428
-
429
- it "sets :keys_only to true if :ssh_key is set in config" do
430
- config[:ssh_key] = "ssh_key_from_config"
431
-
432
- klass.expects(:new).with do |hash|
433
- hash[:keys_only] == true
434
- end
435
-
436
- make_connection
437
- end
438
-
439
- it "sets :auth_methods to only publickey if :ssh_key is set in config" do
440
- config[:ssh_key] = "ssh_key_from_config"
441
-
442
- klass.expects(:new).with do |hash|
443
- hash[:auth_methods] == ["publickey"]
444
- end
445
-
446
- make_connection
447
- end
448
-
449
- it "sets :keys_only to true if :ssh_key is set in state" do
450
- state[:ssh_key] = "ssh_key_from_config"
451
- config[:ssh_key] = false
452
-
453
- klass.expects(:new).with do |hash|
454
- hash[:keys_only] == true
455
- end
456
-
457
- make_connection
458
- end
459
-
460
- it "sets :proxy to proxy if :ssh_http_proxy is set in state" do
461
- config[:ssh_http_proxy] = true
462
-
463
- klass.expects(:new).with do |hash|
464
- hash[:proxy] == proxy_conn
465
- end
466
-
467
- make_connection
468
- end
469
-
470
- it "sets :keys to an array if :ssh_key is set in config" do
471
- config[:kitchen_root] = "/r"
472
- config[:ssh_key] = "ssh_key_from_config"
473
-
474
- klass.expects(:new).with do |hash|
475
- hash[:keys] == [os_safe_root_path("/r/ssh_key_from_config")]
476
- end
477
-
478
- make_connection
479
- end
480
-
481
- it "sets :keys to an array if :ssh_key is set in state" do
482
- state[:ssh_key] = "ssh_key_from_state"
483
- config[:ssh_key] = "ssh_key_from_config"
484
-
485
- klass.expects(:new).with do |hash|
486
- hash[:keys] == ["ssh_key_from_state"]
487
- end
488
-
489
- make_connection
490
- end
491
-
492
- it "does not set :keys_only if :ssh_key is set in config but password is set" do
493
- config[:ssh_key] = "ssh_key_from_config"
494
- config[:password] = "password"
495
-
496
- klass.expects(:new).with do |hash|
497
- hash[:keys_only].nil?
498
- end
499
-
500
- make_connection
501
- end
502
-
503
- it "does not set :auth_methods if :ssh_key is set in config but password is set" do
504
- config[:ssh_key] = "ssh_key_from_config"
505
- config[:password] = "password"
506
-
507
- klass.expects(:new).with do |hash|
508
- hash[:auth_methods].nil?
509
- end
510
-
511
- make_connection
512
- end
513
-
514
- it "does not set :keys_only if :ssh_key is set in state but password is set" do
515
- state[:ssh_key] = "ssh_key_from_config"
516
- config[:ssh_key] = false
517
- config[:password] = "password"
518
-
519
- klass.expects(:new).with do |hash|
520
- hash[:keys_only].nil?
521
- end
522
-
523
- make_connection
524
- end
525
-
526
- it "does not set :keys to an array if :ssh_key is set in config but password is set" do
527
- config[:kitchen_root] = "/r"
528
- config[:ssh_key] = "ssh_key_from_config"
529
- config[:password] = "password"
530
-
531
- klass.expects(:new).with do |hash|
532
- hash[:keys].nil?
533
- end
534
-
535
- make_connection
536
- end
537
-
538
- it "does not set :keys to an array if :ssh_key is set in state but password is set" do
539
- state[:ssh_key] = "ssh_key_from_state"
540
- config[:ssh_key] = "ssh_key_from_config"
541
- config[:password] = "password"
542
-
543
- klass.expects(:new).with do |hash|
544
- hash[:keys].nil?
545
- end
546
-
547
- make_connection
548
- end
549
-
550
- it "sets :auth_methods to only publickey if :ssh_key_only is set in config" do
551
- config[:ssh_key_only] = true
552
-
553
- klass.expects(:new).with do |hash|
554
- hash[:auth_methods] == ["publickey"]
555
- end
556
-
557
- make_connection
558
- end
559
-
560
- it "passes in :password if set in config" do
561
- config[:password] = "password_from_config"
562
-
563
- klass.expects(:new).with do |hash|
564
- hash[:password] == "password_from_config"
565
- end
566
-
567
- make_connection
568
- end
569
-
570
- it "passes in :password from state over config data" do
571
- state[:password] = "password_from_state"
572
- config[:password] = "password_from_config"
573
-
574
- klass.expects(:new).with do |hash|
575
- hash[:password] == "password_from_state"
576
- end
577
-
578
- make_connection
579
- end
580
-
581
- it "passes in :forward_agent if set in config" do
582
- config[:forward_agent] = "forward_agent_from_config"
583
-
584
- klass.expects(:new).with do |hash|
585
- hash[:forward_agent] == "forward_agent_from_config"
586
- end
587
-
588
- make_connection
589
- end
590
-
591
- it "passes in :forward_agent from state over config data" do
592
- state[:forward_agent] = "forward_agent_from_state"
593
- config[:forward_agent] = "forward_agent_from_config"
594
-
595
- klass.expects(:new).with do |hash|
596
- hash[:forward_agent] == "forward_agent_from_state"
597
- end
598
-
599
- make_connection
600
- end
601
-
602
- it "returns the same connection when called again with same state" do
603
- first_connection = make_connection(state)
604
- second_connection = make_connection(state)
605
-
606
- first_connection.object_id.must_equal second_connection.object_id
607
- end
608
-
609
- it "logs a debug message when the connection is reused" do
610
- make_connection(state)
611
- make_connection(state)
612
-
613
- logged_output.string.lines.count do |l|
614
- l =~ debug_line_with("[SSH] reusing existing connection ")
615
- end.must_equal 1
616
- end
617
-
618
- it "returns a new connection when called again if state differs" do
619
- first_connection = make_connection(state)
620
- second_connection = make_connection(state.merge(port: 9000))
621
-
622
- first_connection.object_id.wont_equal second_connection.object_id
623
- end
624
-
625
- it "closes first connection when a second is created" do
626
- first_connection = make_connection(state)
627
- first_connection.expects(:close)
628
-
629
- make_connection(state.merge(port: 9000))
630
- end
631
-
632
- it "logs a debug message a second connection is created" do
633
- make_connection(state)
634
- make_connection(state.merge(port: 9000))
635
-
636
- logged_output.string.lines.count do |l|
637
- l =~ debug_line_with("[SSH] shutting previous connection ")
638
- end.must_equal 1
639
- end
640
- end
641
- # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
642
-
643
- describe "called without a block" do
644
- def make_connection(s = state)
645
- transport.connection(s)
646
- end
647
-
648
- common_connection_specs
649
- end
650
-
651
- describe "called with a block" do
652
- def make_connection(s = state)
653
- transport.connection(s) do |conn|
654
- conn
655
- end
656
- end
657
-
658
- common_connection_specs
659
- end
660
- end
661
-
662
- def debug_line_with(msg)
663
- /^D, .* : #{Regexp.escape(msg)}/
664
- end
665
- end
666
-
667
- describe Kitchen::Transport::Ssh::Connection do
668
- include Net::SSH::Test
669
- # sadly, Net:SSH::Test includes a #connection method so we'll alias this one
670
- # before redefining it
671
- alias_method :net_ssh_connection, :connection
672
-
673
- let(:logged_output) { StringIO.new }
674
- let(:logger) { Logger.new(logged_output) }
675
- let(:conn) { Net::SSH::Test::Extensions::IO.with_test_extension { net_ssh_connection } }
676
-
677
- let(:options) do
678
- {
679
- logger: logger,
680
- username: "me",
681
- hostname: "foo",
682
- port: 22,
683
- max_ssh_sessions: 9,
684
- }
685
- end
686
-
687
- let(:connection) do
688
- Kitchen::Transport::Ssh::Connection.new(options)
689
- end
690
-
691
- before do
692
- logger.level = Logger::DEBUG
693
- Net::SSH.stubs(:start).returns(conn)
694
- end
695
-
696
- describe "establishing a connection" do
697
- [
698
- Errno::EACCES, Errno::EALREADY, Errno::EADDRINUSE, Errno::ECONNREFUSED, Errno::ETIMEDOUT,
699
- Errno::ECONNRESET, Errno::ENETUNREACH, Errno::EHOSTUNREACH, Errno::EPIPE,
700
- Net::SSH::Disconnect, Net::SSH::AuthenticationFailed, Net::SSH::ConnectionTimeout,
701
- Timeout::Error
702
- ].each do |klass|
703
- describe "raising #{klass}" do
704
- before do
705
- Net::SSH.stubs(:start).raises(klass)
706
- options[:connection_retries] = 3
707
- options[:connection_retry_sleep] = 7
708
- connection.stubs(:sleep)
709
- end
710
-
711
- it "raises an SshFailed exception" do
712
- e = proc do
713
- connection.execute("nope")
714
- end.must_raise Kitchen::Transport::SshFailed
715
- e.message.must_match regexify("SSH session could not be established")
716
- end
717
-
718
- it "attempts to connect :connection_retries times" do
719
- begin
720
- connection.execute("nope")
721
- rescue # rubocop:disable Lint/HandleExceptions
722
- # the raise is not what is being tested here, rather its side-effect
723
- end
724
-
725
- logged_output.string.lines.count do |l|
726
- l =~ debug_line("[SSH] opening connection to me@foo<{:port=>22}>")
727
- end.must_equal 3
728
- end
729
-
730
- it "sleeps for :connection_retry_sleep seconds between retries" do
731
- connection.unstub(:sleep)
732
- connection.expects(:sleep).with(7).twice
733
-
734
- begin
735
- connection.execute("nope")
736
- rescue # rubocop:disable Lint/HandleExceptions
737
- # the raise is not what is being tested here, rather its side-effect
738
- end
739
- end
740
-
741
- it "logs the first 2 retry failures on info" do
742
- begin
743
- connection.execute("nope")
744
- rescue # rubocop:disable Lint/HandleExceptions
745
- # the raise is not what is being tested here, rather its side-effect
746
- end
747
-
748
- logged_output.string.lines.count do |l|
749
- l =~ info_line_with(
750
- "[SSH] connection failed, retrying in 7 seconds")
751
- end.must_equal 2
752
- end
753
-
754
- it "logs the last retry failures on warn" do
755
- begin
756
- connection.execute("nope")
757
- rescue # rubocop:disable Lint/HandleExceptions
758
- # the raise is not what is being tested here, rather its side-effect
759
- end
760
-
761
- logged_output.string.lines.count do |l|
762
- l =~ warn_line_with("[SSH] connection failed, terminating ")
763
- end.must_equal 1
764
- end
765
- end
766
- end
767
- end
768
-
769
- describe "#close" do
770
- before do
771
- story do |script|
772
- channel = script.opens_channel
773
- channel.sends_request_pty
774
- channel.sends_exec("doit")
775
- channel.gets_data("ok\n")
776
- channel.gets_exit_status(0)
777
- channel.gets_close
778
- channel.sends_close
779
- end
780
- end
781
-
782
- it "logger displays closing connection on debug" do
783
- conn.expects(:close)
784
-
785
- assert_scripted do
786
- connection.execute("doit")
787
- connection.close
788
- end
789
-
790
- logged_output.string.must_match debug_line(
791
- "[SSH] closing connection to me@foo<{:port=>22}>"
792
- )
793
- end
794
-
795
- it "only closes the connection once for multiple calls" do
796
- conn.expects(:close).once
797
-
798
- assert_scripted do
799
- connection.execute("doit")
800
- connection.close
801
- connection.close
802
- connection.close
803
- end
804
- end
805
- end
806
-
807
- describe "#execute" do
808
- describe "for a successful command" do
809
- before do
810
- story do |script|
811
- channel = script.opens_channel
812
- channel.sends_request_pty
813
- channel.sends_exec("doit")
814
- channel.gets_data("ok\n")
815
- channel.gets_extended_data("some stderr stuffs\n")
816
- channel.gets_exit_status(0)
817
- channel.gets_close
818
- channel.sends_close
819
- end
820
- end
821
-
822
- it "logger displays command on debug" do
823
- assert_scripted { connection.execute("doit") }
824
-
825
- logged_output.string.must_match debug_line(
826
- "[SSH] me@foo<{:port=>22}> (doit)"
827
- )
828
- end
829
-
830
- it "logger displays establishing connection on debug" do
831
- assert_scripted { connection.execute("doit") }
832
-
833
- logged_output.string.must_match debug_line(
834
- "[SSH] opening connection to me@foo<{:port=>22}>"
835
- )
836
- end
837
-
838
- it "logger captures stdout" do
839
- assert_scripted { connection.execute("doit") }
840
-
841
- logged_output.string.must_match(/^ok$/)
842
- end
843
-
844
- it "logger captures stderr" do
845
- assert_scripted { connection.execute("doit") }
846
-
847
- logged_output.string.must_match(/^some stderr stuffs$/)
848
- end
849
- end
850
-
851
- describe "for a failed command" do
852
- before do
853
- story do |script|
854
- channel = script.opens_channel
855
- channel.sends_request_pty
856
- channel.sends_exec("doit")
857
- channel.gets_data("nope\n")
858
- channel.gets_extended_data("youdead\n")
859
- channel.gets_exit_status(42)
860
- channel.gets_close
861
- channel.sends_close
862
- end
863
- end
864
-
865
- it "logger displays command on debug" do
866
- begin
867
- assert_scripted { connection.execute("doit") }
868
- rescue # rubocop:disable Lint/HandleExceptions
869
- # the raise is not what is being tested here, rather its side-effect
870
- end
871
-
872
- logged_output.string.must_match debug_line(
873
- "[SSH] me@foo<{:port=>22}> (doit)"
874
- )
875
- end
876
-
877
- it "logger displays establishing connection on debug" do
878
- begin
879
- assert_scripted { connection.execute("doit") }
880
- rescue # rubocop:disable Lint/HandleExceptions
881
- # the raise is not what is being tested here, rather its side-effect
882
- end
883
-
884
- logged_output.string.must_match debug_line(
885
- "[SSH] opening connection to me@foo<{:port=>22}>"
886
- )
887
- end
888
-
889
- it "logger captures stdout" do
890
- begin
891
- assert_scripted { connection.execute("doit") }
892
- rescue # rubocop:disable Lint/HandleExceptions
893
- # the raise is not what is being tested here, rather its side-effect
894
- end
895
-
896
- logged_output.string.must_match(/^nope$/)
897
- end
898
-
899
- it "logger captures stderr" do
900
- begin
901
- assert_scripted { connection.execute("doit") }
902
- rescue # rubocop:disable Lint/HandleExceptions
903
- # the raise is not what is being tested here, rather its side-effect
904
- end
905
-
906
- logged_output.string.must_match(/^youdead$/)
907
- end
908
-
909
- it "raises an SshFailed exception" do
910
- err = proc do
911
- assert_scripted { connection.execute("doit") }
912
- end.must_raise Kitchen::Transport::SshFailed
913
- err.message.must_equal "SSH exited (42) for command: [doit]"
914
- end
915
-
916
- it "returns the exit code with an SshFailed exception" do
917
- begin
918
- assert_scripted { connection.execute("doit") }
919
- rescue Kitchen::Transport::SshFailed => e
920
- e.exit_code.must_equal 42
921
- end
922
- end
923
- end
924
-
925
- describe "for an interrupted command" do
926
- let(:conn) { mock("session") }
927
-
928
- before do
929
- Net::SSH.stubs(:start).returns(conn)
930
- end
931
-
932
- it "raises SshFailed when an SSH exception is raised" do
933
- conn.stubs(:open_channel).raises(Net::SSH::Exception)
934
-
935
- e = proc do
936
- connection.execute("nope")
937
- end.must_raise Kitchen::Transport::SshFailed
938
- e.message.must_match regexify("SSH command failed")
939
- end
940
- end
941
-
942
- describe "for a nil command" do
943
- it "does not log on debug" do
944
- connection.execute(nil)
945
-
946
- logged_output.string.must_equal ""
947
- end
948
- end
949
- end
950
-
951
- describe "#login_command" do
952
- let(:login_command) { connection.login_command }
953
- let(:args) { login_command.arguments.join(" ") }
954
-
955
- it "returns a LoginCommand" do
956
- login_command.must_be_instance_of Kitchen::LoginCommand
957
- end
958
-
959
- it "is an SSH command" do
960
- login_command.command.must_equal "ssh"
961
- args.must_match %r{ me@foo$}
962
- end
963
-
964
- it "sets the UserKnownHostsFile option" do
965
- args.must_match regexify("-o UserKnownHostsFile=/dev/null ")
966
- end
967
-
968
- it "sets the StrictHostKeyChecking option" do
969
- args.must_match regexify(" -o StrictHostKeyChecking=no ")
970
- end
971
-
972
- it "won't set IdentitiesOnly option by default" do
973
- args.wont_match regexify(" -o IdentitiesOnly=")
974
- end
975
-
976
- it "sets the IdentiesOnly option if :keys option is given" do
977
- options[:keys] = ["yep"]
978
-
979
- args.must_match regexify(" -o IdentitiesOnly=yes ")
980
- end
981
-
982
- it "sets the LogLevel option to VERBOSE if logger is set to debug" do
983
- logger.level = ::Logger::DEBUG
984
- options[:logger] = logger
985
-
986
- args.must_match regexify(" -o LogLevel=VERBOSE ")
987
- end
988
-
989
- it "sets the LogLevel option to ERROR if logger is not set to debug" do
990
- logger.level = ::Logger::INFO
991
- options[:logger] = logger
992
-
993
- args.must_match regexify(" -o LogLevel=ERROR ")
994
- end
995
-
996
- it "won't set the ForwardAgent option by default" do
997
- args.wont_match regexify(" -o ForwardAgent=")
998
- end
999
-
1000
- it "sets the ForwardAgent option to yes if truthy" do
1001
- options[:forward_agent] = "yep"
1002
-
1003
- args.must_match regexify(" -o ForwardAgent=yes")
1004
- end
1005
-
1006
- it "sets the ForwardAgent option to no if falsey" do
1007
- options[:forward_agent] = false
1008
-
1009
- args.must_match regexify(" -o ForwardAgent=no")
1010
- end
1011
-
1012
- it "won't add any SSH keys by default" do
1013
- args.wont_match regexify(" -i ")
1014
- end
1015
-
1016
- it "sets SSH keys options if given" do
1017
- options[:keys] = %w{one two}
1018
-
1019
- args.must_match regexify(" -i one ")
1020
- args.must_match regexify(" -i two ")
1021
- end
1022
-
1023
- it "sets the port option to 22 by default" do
1024
- args.must_match regexify(" -p 22 ")
1025
- end
1026
-
1027
- it "sets the port option" do
1028
- options[:port] = 1234
1029
-
1030
- args.must_match regexify(" -p 1234 ")
1031
- end
1032
- end
1033
-
1034
- describe "#upload" do
1035
- describe "for a file" do
1036
- let(:content) { "a" * 1234 }
1037
-
1038
- let(:src) do
1039
- file = Tempfile.new("file")
1040
- file.write("a" * 1234)
1041
- file.close
1042
- FileUtils.chmod(0755, file.path)
1043
- file
1044
- end
1045
-
1046
- before do
1047
- expect_scp_session("-t /tmp/remote") do |channel|
1048
- file_mode = running_tests_on_windows? ? 0644 : 0755
1049
- channel.gets_data("\0")
1050
- channel.sends_data("C#{padded_octal_string(file_mode)} 1234 #{File.basename(src.path)}\n")
1051
- channel.gets_data("\0")
1052
- channel.sends_data("a" * 1234)
1053
- channel.sends_data("\0")
1054
- channel.gets_data("\0")
1055
- end
1056
- end
1057
-
1058
- after do
1059
- src.unlink
1060
- end
1061
-
1062
- it "uploads a file to remote over scp" do
1063
- assert_scripted do
1064
- connection.upload(src.path, "/tmp/remote")
1065
- end
1066
- end
1067
- end
1068
-
1069
- describe "for a path" do
1070
- before do
1071
- @dir = Dir.mktmpdir("local")
1072
-
1073
- # Since File.chmod is a NOOP on Windows
1074
- @tmp_dir_mode = running_tests_on_windows? ? 0755 : 0700
1075
- @alpha_file_mode = running_tests_on_windows? ? 0644 : 0644
1076
- @beta_file_mode = running_tests_on_windows? ? 0444 : 0555
1077
-
1078
- FileUtils.chmod(0700, @dir)
1079
- File.open("#{@dir}/alpha", "wb") { |f| f.write("alpha-contents\n") }
1080
- FileUtils.chmod(0644, "#{@dir}/alpha")
1081
- FileUtils.mkdir_p("#{@dir}/subdir")
1082
- FileUtils.chmod(0755, "#{@dir}/subdir")
1083
- File.open("#{@dir}/subdir/beta", "wb") { |f| f.write("beta-contents\n") }
1084
- FileUtils.chmod(0555, "#{@dir}/subdir/beta")
1085
- File.open("#{@dir}/zulu", "wb") { |f| f.write("zulu-contents\n") }
1086
- FileUtils.chmod(0444, "#{@dir}/zulu")
1087
-
1088
- expect_scp_session("-t -r /tmp/remote") do |channel|
1089
- channel.gets_data("\0")
1090
- channel.sends_data("D#{padded_octal_string(@tmp_dir_mode)} 0 #{File.basename(@dir)}\n")
1091
- channel.gets_data("\0")
1092
- channel.sends_data("C#{padded_octal_string(@alpha_file_mode)} 15 alpha\n")
1093
- channel.gets_data("\0")
1094
- channel.sends_data("alpha-contents\n")
1095
- channel.sends_data("\0")
1096
- channel.gets_data("\0")
1097
- channel.sends_data("D0755 0 subdir\n")
1098
- channel.gets_data("\0")
1099
- channel.sends_data("C#{padded_octal_string(@beta_file_mode)} 14 beta\n")
1100
- channel.gets_data("\0")
1101
- channel.sends_data("beta-contents\n")
1102
- channel.sends_data("\0")
1103
- channel.gets_data("\0")
1104
- channel.sends_data("E\n")
1105
- channel.gets_data("\0")
1106
- channel.sends_data("C0444 14 zulu\n")
1107
- channel.gets_data("\0")
1108
- channel.sends_data("zulu-contents\n")
1109
- channel.sends_data("\0")
1110
- channel.gets_data("\0")
1111
- channel.sends_data("E\n")
1112
- channel.gets_data("\0")
1113
- end
1114
- end
1115
-
1116
- after do
1117
- FileUtils.remove_entry_secure(@dir)
1118
- end
1119
-
1120
- it "uploads a file to remote over scp" do
1121
- with_sorted_dir_entries do
1122
- assert_scripted { connection.upload(@dir, "/tmp/remote") }
1123
- end
1124
- end
1125
- end
1126
-
1127
- describe "for a failed upload" do
1128
- let(:conn) { mock("session") }
1129
-
1130
- before do
1131
- Net::SSH.stubs(:start).returns(conn)
1132
- end
1133
-
1134
- it "raises SshFailed when an SSH exception is raised" do
1135
- conn.stubs(:scp).raises(Net::SSH::Exception)
1136
-
1137
- e = proc do
1138
- connection.upload("nope", "fail")
1139
- end.must_raise Kitchen::Transport::SshFailed
1140
- e.message.must_match regexify("SCP upload failed")
1141
- end
1142
- end
1143
- end
1144
-
1145
- describe "#download" do
1146
- let(:conn) { mock("session") }
1147
- let(:scp) { mock("scp") }
1148
-
1149
- before do
1150
- Net::SSH.stubs(:start).returns(conn)
1151
- conn.stubs(:scp).returns(scp)
1152
- @local_parent = Dir.mktmpdir("dir")
1153
- @local = File.join(@local_parent, "local")
1154
- end
1155
-
1156
- after do
1157
- FileUtils.remove_entry_secure(@local_parent)
1158
- end
1159
-
1160
- describe "for a file" do
1161
- it "downloads a file from a remote over scp" do
1162
- FileUtils.expects(:mkdir_p).with(@local_parent)
1163
- scp.expects(:download!).with("/remote", @local)
1164
-
1165
- connection.download("/remote", @local)
1166
- end
1167
- end
1168
-
1169
- describe "for a list of files" do
1170
- it "downloads the files from a remote over scp" do
1171
- FileUtils.expects(:mkdir_p).with(@local_parent)
1172
- scp.expects(:download!).with("/remote-1", @local)
1173
- scp.expects(:download!).with("/remote-2", @local)
1174
-
1175
- connection.download(["/remote-1", "/remote-2"], @local)
1176
- end
1177
- end
1178
-
1179
- describe "for a directory" do
1180
- it "downloads the directory from a remote over scp" do
1181
- FileUtils.expects(:mkdir_p).with(@local_parent)
1182
- scp.expects(:download!).with("/remote-dir", @local).raises(Net::SCP::Error)
1183
- scp.expects(:download!).with("/remote-dir", @local, recursive: true)
1184
-
1185
- connection.download("/remote-dir", @local)
1186
- end
1187
- end
1188
-
1189
- describe "for a file that does not exist" do
1190
- it "logs a warning" do
1191
- FileUtils.expects(:mkdir_p).with(@local_parent)
1192
- scp.expects(:download!).with("/remote", @local).raises(Net::SCP::Error)
1193
- scp.expects(:download!).with("/remote", @local, recursive: true)
1194
- .raises(Net::SCP::Error)
1195
-
1196
- connection.download("/remote", @local)
1197
-
1198
- logged_output.string.lines.count do |l|
1199
- l =~ warn_line_with(
1200
- "SCP download failed for file or directory '/remote', perhaps it does not exist?"
1201
- )
1202
- end.must_equal 1
1203
- end
1204
- end
1205
-
1206
- describe "for a failed download" do
1207
- it "raises SshFailed when an SSH exception is raised" do
1208
- conn.stubs(:scp).raises(Net::SSH::Exception)
1209
-
1210
- e = proc do
1211
- connection.download("nope", "fail")
1212
- end.must_raise Kitchen::Transport::SshFailed
1213
- e.message.must_match regexify("SCP download failed")
1214
- end
1215
- end
1216
- end
1217
-
1218
- describe "#wait_until_ready" do
1219
- before do
1220
- options[:max_wait_until_ready] = 300
1221
- connection.stubs(:sleep)
1222
- end
1223
-
1224
- describe "when failing to connect" do
1225
- before do
1226
- Net::SSH.stubs(:start).raises(Errno::ECONNREFUSED)
1227
- end
1228
-
1229
- it "attempts to connect :max_wait_until_ready / 3 times if failing" do
1230
- begin
1231
- connection.wait_until_ready
1232
- rescue # rubocop:disable Lint/HandleExceptions
1233
- # the raise is not what is being tested here, rather its side-effect
1234
- end
1235
-
1236
- logged_output.string.lines.count do |l|
1237
- l =~ info_line_with(
1238
- "Waiting for SSH service on foo:22, retrying in 3 seconds")
1239
- end.must_equal((300 / 3) - 1)
1240
- logged_output.string.lines.count do |l|
1241
- l =~ debug_line_with("[SSH] connection failed ")
1242
- end.must_equal((300 / 3) - 1)
1243
- logged_output.string.lines.count do |l|
1244
- l =~ warn_line_with("[SSH] connection failed, terminating ")
1245
- end.must_equal 1
1246
- end
1247
-
1248
- it "sleeps for 3 seconds between retries" do
1249
- connection.unstub(:sleep)
1250
- connection.expects(:sleep).with(3).times((300 / 3) - 1)
1251
-
1252
- begin
1253
- connection.wait_until_ready
1254
- rescue # rubocop:disable Lint/HandleExceptions
1255
- # the raise is not what is being tested here, rather its side-effect
1256
- end
1257
- end
1258
- end
1259
-
1260
- describe "when connection is successful" do
1261
- before do
1262
- story do |script|
1263
- channel = script.opens_channel
1264
- channel.sends_request_pty
1265
- channel.sends_exec("echo '[SSH] Established'")
1266
- channel.gets_data("[SSH] Established\n")
1267
- channel.gets_exit_status(0)
1268
- channel.gets_close
1269
- channel.sends_close
1270
- end
1271
- end
1272
-
1273
- it "executes an ping command string to ensure working" do
1274
- assert_scripted { connection.wait_until_ready }
1275
- end
1276
-
1277
- it "logger captures stdout" do
1278
- assert_scripted { connection.wait_until_ready }
1279
-
1280
- logged_output.string.must_match(/^\[SSH\] Established$/)
1281
- end
1282
- end
1283
- end
1284
-
1285
- def expect_scp_session(args)
1286
- story do |script|
1287
- channel = script.opens_channel
1288
- channel.sends_exec("scp #{args}")
1289
- yield channel if block_given?
1290
- channel.sends_eof
1291
- channel.gets_exit_status(0)
1292
- channel.gets_eof
1293
- channel.gets_close
1294
- channel.sends_close
1295
- end
1296
- end
1297
-
1298
- def debug_line(msg)
1299
- /^D, .* : #{Regexp.escape(msg)}$/
1300
- end
1301
-
1302
- def debug_line_with(msg)
1303
- /^D, .* : #{Regexp.escape(msg)}/
1304
- end
1305
-
1306
- def info_line_with(msg)
1307
- /^I, .* : #{Regexp.escape(msg)}/
1308
- end
1309
-
1310
- def regexify(string)
1311
- Regexp.new(Regexp.escape(string))
1312
- end
1313
-
1314
- def warn_line_with(msg)
1315
- /^W, .* : #{Regexp.escape(msg)}/
1316
- end
1317
- end