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,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