test-kitchen 1.23.3 → 1.23.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/kitchen/version.rb +1 -1
- data/support/chef-client-zero.rb +1 -1
- metadata +5 -324
- data/.gitattributes +0 -3
- data/.github/ISSUE_TEMPLATE.md +0 -56
- data/.github/lock.yml +0 -1
- data/.gitignore +0 -38
- data/.gitmodules +0 -0
- data/.kitchen.appveyor.yml +0 -25
- data/.kitchen.dokken.yml +0 -31
- data/.kitchen.proxy.yml +0 -27
- data/.rubocop.yml +0 -5
- data/.travis.yml +0 -57
- data/.yardopts +0 -3
- data/Berksfile +0 -3
- data/CHANGELOG.md +0 -1510
- data/CONTRIBUTING.md +0 -14
- data/ECOSYSTEM.md +0 -93
- data/Gemfile +0 -40
- data/Gemfile.proxy_tests +0 -4
- data/Guardfile +0 -42
- data/MAINTAINERS.md +0 -29
- data/README.md +0 -138
- data/RELEASE_NOTES.md +0 -167
- data/Rakefile +0 -77
- data/appveyor.yml +0 -47
- data/docs/CONTRIBUTING.md +0 -8
- data/docs/LICENSE +0 -22
- data/docs/README.md +0 -78
- data/docs/archetypes/default.md +0 -6
- data/docs/config.toml +0 -36
- data/docs/content/docs/_index.md +0 -5
- data/docs/content/docs/drivers/_index.md +0 -27
- data/docs/content/docs/drivers/azurerm.md +0 -44
- data/docs/content/docs/drivers/vagrant.md +0 -39
- data/docs/content/docs/getting-started/00-introduction.md +0 -14
- data/docs/content/docs/getting-started/01-installing.md +0 -64
- data/docs/content/docs/getting-started/02-getting-help.md +0 -59
- data/docs/content/docs/getting-started/03-creating-cookbook.md +0 -46
- data/docs/content/docs/getting-started/04-kitchen-yml.md +0 -56
- data/docs/content/docs/getting-started/05-instances.md +0 -79
- data/docs/content/docs/getting-started/06-writing-recipe.md +0 -21
- data/docs/content/docs/getting-started/07-running-converge.md +0 -134
- data/docs/content/docs/getting-started/08-manually-verifying.md +0 -55
- data/docs/content/docs/getting-started/09-writing-test.md +0 -49
- data/docs/content/docs/getting-started/10-running-verify.md +0 -120
- data/docs/content/docs/getting-started/11-running-test.md +0 -168
- data/docs/content/docs/getting-started/12-adding-platform.md +0 -206
- data/docs/content/docs/getting-started/13-adding-feature.md +0 -30
- data/docs/content/docs/getting-started/14-adding-suite.md +0 -60
- data/docs/content/docs/getting-started/15-adding-test.md +0 -66
- data/docs/content/docs/getting-started/16-adding-recipe.md +0 -53
- data/docs/content/docs/getting-started/17-excluding-platforms.md +0 -101
- data/docs/content/docs/getting-started/18-next-steps.md +0 -23
- data/docs/content/docs/getting-started/_index.md +0 -5
- data/docs/content/docs/provisioners/_index.md +0 -36
- data/docs/content/docs/provisioners/chef.md +0 -69
- data/docs/content/docs/provisioners/shell.md +0 -31
- data/docs/content/docs/reference/_index.md +0 -5
- data/docs/content/docs/reference/configuration.md +0 -53
- data/docs/content/docs/reference/examples.md +0 -97
- data/docs/content/docs/reference/faq.md +0 -58
- data/docs/content/docs/reference/fixtures.md +0 -32
- data/docs/content/docs/reference/glossary.md +0 -34
- data/docs/content/docs/reference/lifecycle-hooks.md +0 -68
- data/docs/content/docs/reference/reboots.md +0 -24
- data/docs/content/docs/verifiers/_index.md +0 -14
- data/docs/content/docs/verifiers/inspec.md +0 -44
- data/docs/content/docs/verifiers/serverspec.md +0 -20
- data/docs/static/images/chef-logo.png +0 -0
- data/docs/static/images/chef-logo.svg +0 -1
- data/docs/static/images/github-banner.png +0 -0
- data/docs/static/images/github-banner.svg +0 -71
- data/docs/static/images/kitchen-logo.png +0 -0
- data/docs/static/images/logo-block.svg +0 -222
- data/docs/static/images/logo.png +0 -0
- data/docs/static/images/logos-group.png +0 -0
- data/docs/static/images/terminal-1.png +0 -0
- data/docs/static/images/terminal-1.svg +0 -589
- data/docs/static/images/terminal-2.png +0 -0
- data/docs/static/images/terminal-2.svg +0 -235
- data/docs/static/images/terminal-3.png +0 -0
- data/docs/static/images/terminal-3.svg +0 -439
- data/docs/static/index.html +0 -59
- data/docs/static/javascripts/all.js +0 -348
- data/docs/static/javascripts/vendor/foundation.min.js +0 -4
- data/docs/static/javascripts/vendor/jquery.min.js +0 -5
- data/docs/static/javascripts/vendor/what-input.js +0 -336
- data/docs/static/stylesheets/site.css +0 -4667
- data/docs/themes/kitchen/layouts/_default/baseof.html +0 -53
- data/docs/themes/kitchen/layouts/_default/list.html +0 -4
- data/docs/themes/kitchen/layouts/_default/redirect.html +0 -10
- data/docs/themes/kitchen/layouts/_default/single.html +0 -6
- data/docs/themes/kitchen/layouts/partials/core/head.html +0 -6
- data/docs/themes/kitchen/layouts/partials/kitchen/footer.html +0 -18
- data/docs/themes/kitchen/layouts/partials/kitchen/head.html +0 -4
- data/docs/themes/kitchen/layouts/partials/kitchen/header.html +0 -26
- data/docs/themes/kitchen/layouts/partials/search-docs.html +0 -3
- data/docs/themes/kitchen/layouts/partials/sidebar.html +0 -33
- data/docs/themes/kitchen/layouts/shortcodes/button.html +0 -1
- data/docs/themes/kitchen/layouts/shortcodes/codeblock.html +0 -8
- data/docs/themes/kitchen/layouts/shortcodes/cta.html +0 -5
- data/docs/themes/kitchen/layouts/shortcodes/danger.html +0 -1
- data/docs/themes/kitchen/layouts/shortcodes/example_fqdn.html +0 -1
- data/docs/themes/kitchen/layouts/shortcodes/info.html +0 -1
- data/docs/themes/kitchen/layouts/shortcodes/ol-styled.html +0 -3
- data/docs/themes/kitchen/layouts/shortcodes/success.html +0 -1
- data/docs/themes/kitchen/layouts/shortcodes/tip.html +0 -1
- data/docs/themes/kitchen/layouts/shortcodes/warning.html +0 -1
- data/docs/themes/kitchen/static/css/kitchen.css +0 -10
- data/docs/themes/kitchen/static/css/kitchen.css.map +0 -7
- data/docs/themes/kitchen/static/fonts/Muli-Bold.ttf +0 -0
- data/docs/themes/kitchen/static/fonts/Muli-Regular.ttf +0 -0
- data/docs/themes/kitchen/static/fonts/Muli-SemiBold.ttf +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-brands-400.eot +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-brands-400.svg +0 -1104
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-brands-400.ttf +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-brands-400.woff +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-brands-400.woff2 +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-regular-400.eot +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-regular-400.svg +0 -372
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-regular-400.ttf +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-regular-400.woff +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-regular-400.woff2 +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-solid-900.eot +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-solid-900.svg +0 -1896
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-solid-900.ttf +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-solid-900.woff +0 -0
- data/docs/themes/kitchen/static/fonts/fontawesome/fa-solid-900.woff2 +0 -0
- data/docs/themes/kitchen/static/images/chef-logo-light.svg +0 -36
- data/docs/themes/kitchen/static/images/chef-logo-white.svg +0 -38
- data/docs/themes/kitchen/static/images/chef-logo.svg +0 -37
- data/docs/themes/kitchen/static/images/favicon.ico +0 -0
- data/docs/themes/kitchen/static/js/scripts-all.js +0 -7
- data/docs/themes/kitchen/static/js/source/chef-hugo.js +0 -116
- data/docs/themes/kitchen/static/js/source/omnitruck.js +0 -82
- data/docs/themes/kitchen/static/js/source/segment.js +0 -52
- data/docs/themes/kitchen/static/sass/_buttons.scss +0 -161
- data/docs/themes/kitchen/static/sass/_core.scss +0 -24
- data/docs/themes/kitchen/static/sass/_forms.scss +0 -14
- data/docs/themes/kitchen/static/sass/_mixins.scss +0 -133
- data/docs/themes/kitchen/static/sass/_typography.scss +0 -34
- data/docs/themes/kitchen/static/sass/_variables.scss +0 -82
- data/docs/themes/kitchen/static/sass/kitchen.scss +0 -7
- data/docs/themes/kitchen/static/sass/kitchen/_footer.scss +0 -50
- data/docs/themes/kitchen/static/sass/kitchen/_header.scss +0 -187
- data/docs/themes/kitchen/static/sass/kitchen/_homepage.scss +0 -27
- data/docs/themes/kitchen/static/sass/kitchen/_utility-bar.scss +0 -173
- data/docs/themes/kitchen/static/sass/partials/_alerts.scss +0 -32
- data/docs/themes/kitchen/static/sass/partials/_bg.scss +0 -19
- data/docs/themes/kitchen/static/sass/partials/_blurbs.scss +0 -25
- data/docs/themes/kitchen/static/sass/partials/_callout.scss +0 -15
- data/docs/themes/kitchen/static/sass/partials/_cards.scss +0 -54
- data/docs/themes/kitchen/static/sass/partials/_dropdown.scss +0 -77
- data/docs/themes/kitchen/static/sass/partials/_grid.scss +0 -87
- data/docs/themes/kitchen/static/sass/partials/_padding.scss +0 -73
- data/docs/themes/kitchen/static/sass/partials/_sidebar.scss +0 -71
- data/docs/themes/kitchen/static/sass/partials/_tabs.scss +0 -125
- data/docs/themes/kitchen/static/sass/typography/_chroma.scss +0 -366
- data/docs/themes/kitchen/static/sass/typography/_code.scss +0 -72
- data/docs/themes/kitchen/static/sass/typography/_headers.scss +0 -90
- data/docs/themes/kitchen/static/sass/typography/_links.scss +0 -127
- data/docs/themes/kitchen/static/sass/typography/_lists.scss +0 -155
- data/docs/themes/kitchen/static/sass/typography/_prose.scss +0 -29
- data/docs/themes/kitchen/static/sass/typography/_text.scss +0 -221
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_animated.scss +0 -20
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_bordered-pulled.scss +0 -20
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_core.scss +0 -16
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_fixed-width.scss +0 -6
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_icons.scss +0 -992
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_larger.scss +0 -23
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_list.scss +0 -18
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_mixins.scss +0 -57
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_rotated-flipped.scss +0 -23
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_screen-reader.scss +0 -5
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_stacked.scss +0 -31
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/_variables.scss +0 -1005
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/fa-brands.scss +0 -21
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/fa-regular.scss +0 -22
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/fa-solid.scss +0 -23
- data/docs/themes/kitchen/static/sass/vendor/fontawesome/fontawesome.scss +0 -16
- data/docs/themes/kitchen/theme.toml +0 -8
- data/features/kitchen_action_commands.feature +0 -164
- data/features/kitchen_command.feature +0 -16
- data/features/kitchen_console_command.feature +0 -35
- data/features/kitchen_defaults.feature +0 -38
- data/features/kitchen_diagnose_command.feature +0 -96
- data/features/kitchen_help_command.feature +0 -16
- data/features/kitchen_init_command.feature +0 -254
- data/features/kitchen_list_command.feature +0 -140
- data/features/kitchen_login_command.feature +0 -62
- data/features/kitchen_sink_command.feature +0 -30
- data/features/kitchen_test_command.feature +0 -88
- data/features/step_definitions/gem_steps.rb +0 -24
- data/features/step_definitions/git_steps.rb +0 -5
- data/features/step_definitions/output_steps.rb +0 -5
- data/features/support/env.rb +0 -74
- data/spec/kitchen/base64_stream_spec.rb +0 -74
- data/spec/kitchen/cli_spec.rb +0 -54
- data/spec/kitchen/collection_spec.rb +0 -76
- data/spec/kitchen/color_spec.rb +0 -51
- data/spec/kitchen/config_spec.rb +0 -434
- data/spec/kitchen/configurable_spec.rb +0 -1113
- data/spec/kitchen/data_munger_spec.rb +0 -2800
- data/spec/kitchen/diagnostic_spec.rb +0 -128
- data/spec/kitchen/driver/base_spec.rb +0 -132
- data/spec/kitchen/driver/dummy_spec.rb +0 -193
- data/spec/kitchen/driver/exec_spec.rb +0 -75
- data/spec/kitchen/driver/proxy_spec.rb +0 -127
- data/spec/kitchen/driver/ssh_base_spec.rb +0 -1136
- data/spec/kitchen/driver_spec.rb +0 -106
- data/spec/kitchen/errors_spec.rb +0 -317
- data/spec/kitchen/instance_spec.rb +0 -1372
- data/spec/kitchen/lazy_hash_spec.rb +0 -113
- data/spec/kitchen/lifecycle_hooks_spec.rb +0 -171
- data/spec/kitchen/loader/yaml_spec.rb +0 -787
- data/spec/kitchen/logger_spec.rb +0 -425
- data/spec/kitchen/logging_spec.rb +0 -56
- data/spec/kitchen/login_command_spec.rb +0 -67
- data/spec/kitchen/metadata_chopper_spec.rb +0 -79
- data/spec/kitchen/platform_spec.rb +0 -88
- data/spec/kitchen/provisioner/base_spec.rb +0 -393
- data/spec/kitchen/provisioner/chef/policyfile_spec.rb +0 -140
- data/spec/kitchen/provisioner/chef_apply_spec.rb +0 -131
- data/spec/kitchen/provisioner/chef_base_spec.rb +0 -1565
- data/spec/kitchen/provisioner/chef_solo_spec.rb +0 -602
- data/spec/kitchen/provisioner/chef_zero_spec.rb +0 -1013
- data/spec/kitchen/provisioner/dummy_spec.rb +0 -96
- data/spec/kitchen/provisioner/shell_spec.rb +0 -623
- data/spec/kitchen/provisioner_spec.rb +0 -101
- data/spec/kitchen/shell_out_spec.rb +0 -146
- data/spec/kitchen/ssh_spec.rb +0 -584
- data/spec/kitchen/state_file_spec.rb +0 -122
- data/spec/kitchen/suite_spec.rb +0 -61
- data/spec/kitchen/transport/base_spec.rb +0 -140
- data/spec/kitchen/transport/exec_spec.rb +0 -79
- data/spec/kitchen/transport/ssh_spec.rb +0 -1317
- data/spec/kitchen/transport/winrm_spec.rb +0 -1320
- data/spec/kitchen/transport_spec.rb +0 -106
- data/spec/kitchen/util_spec.rb +0 -250
- data/spec/kitchen/verifier/base_spec.rb +0 -346
- data/spec/kitchen/verifier/busser_spec.rb +0 -580
- data/spec/kitchen/verifier/dummy_spec.rb +0 -96
- data/spec/kitchen/verifier/shell_spec.rb +0 -157
- data/spec/kitchen/verifier_spec.rb +0 -114
- data/spec/kitchen_spec.rb +0 -112
- data/spec/spec_helper.rb +0 -110
- data/spec/support/powershell_max_size_spec.rb +0 -39
- data/test-kitchen.gemspec +0 -49
- data/test/cookbooks/test_cookbook/metadata.rb +0 -6
- data/test/cookbooks/test_cookbook/recipes/default.rb +0 -1
- data/test/integration/default/default_spec.rb +0 -3
- data/testing_windows.md +0 -38
|
@@ -1,101 +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/configurable"
|
|
22
|
-
require "kitchen/errors"
|
|
23
|
-
require "kitchen/logging"
|
|
24
|
-
require "kitchen/provisioner"
|
|
25
|
-
require "kitchen/provisioner/base"
|
|
26
|
-
|
|
27
|
-
module Kitchen
|
|
28
|
-
module Provisioner
|
|
29
|
-
class Coolbeans < Kitchen::Provisioner::Base
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
class ItDepends < Kitchen::Provisioner::Base
|
|
33
|
-
attr_reader :verify_call_count
|
|
34
|
-
|
|
35
|
-
def initialize(config = {})
|
|
36
|
-
@verify_call_count = 0
|
|
37
|
-
super
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def verify_dependencies
|
|
41
|
-
@verify_call_count += 1
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
class UnstableDepends < Kitchen::Provisioner::Base
|
|
46
|
-
def verify_dependencies
|
|
47
|
-
raise UserError, "Oh noes, you don't have software!"
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
describe Kitchen::Provisioner do
|
|
54
|
-
describe ".for_plugin" do
|
|
55
|
-
before do
|
|
56
|
-
Kitchen::Provisioner.stubs(:require).returns(true)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
it "returns a provisioner object of the correct class" do
|
|
60
|
-
provisioner = Kitchen::Provisioner.for_plugin("coolbeans", {})
|
|
61
|
-
|
|
62
|
-
provisioner.must_be_kind_of Kitchen::Provisioner::Coolbeans
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
it "returns a provisioner initialized with its config" do
|
|
66
|
-
provisioner = Kitchen::Provisioner.for_plugin("coolbeans", foo: "bar")
|
|
67
|
-
|
|
68
|
-
provisioner[:foo].must_equal "bar"
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
it "calls #verify_dependencies on the provisioner object" do
|
|
72
|
-
provisioner = Kitchen::Provisioner.for_plugin("it_depends", {})
|
|
73
|
-
|
|
74
|
-
provisioner.verify_call_count.must_equal 1
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
it "calls #verify_dependencies once per provisioner require" do
|
|
78
|
-
Kitchen::Provisioner.stubs(:require).returns(true, false)
|
|
79
|
-
provisioner1 = Kitchen::Provisioner.for_plugin("it_depends", {})
|
|
80
|
-
provisioner1.verify_call_count.must_equal 1
|
|
81
|
-
provisioner2 = Kitchen::Provisioner.for_plugin("it_depends", {})
|
|
82
|
-
|
|
83
|
-
provisioner2.verify_call_count.must_equal 0
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
it "raises ClientError if the provisioner could not be required" do
|
|
87
|
-
Kitchen::Provisioner.stubs(:require).raises(LoadError)
|
|
88
|
-
|
|
89
|
-
proc { Kitchen::Provisioner.for_plugin("coolbeans", {}) }
|
|
90
|
-
.must_raise Kitchen::ClientError
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
it "raises ClientError if the provisioner's class constant was not found" do
|
|
94
|
-
# pretend require worked
|
|
95
|
-
Kitchen::Provisioner.stubs(:require).returns(true)
|
|
96
|
-
|
|
97
|
-
proc { Kitchen::Provisioner.for_plugin("nope", {}) }
|
|
98
|
-
.must_raise Kitchen::ClientError
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
end
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
|
2
|
-
#
|
|
3
|
-
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
|
4
|
-
#
|
|
5
|
-
# Copyright (C) 2014, 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/shell_out"
|
|
23
|
-
require "kitchen/util"
|
|
24
|
-
|
|
25
|
-
module Kitchen
|
|
26
|
-
class Shelly
|
|
27
|
-
include Kitchen::ShellOut
|
|
28
|
-
|
|
29
|
-
attr_reader :logs
|
|
30
|
-
|
|
31
|
-
def debug(msg)
|
|
32
|
-
@logs ||= []
|
|
33
|
-
@logs << msg
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def logger
|
|
37
|
-
"alogger"
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
describe Kitchen::ShellOut do
|
|
43
|
-
let(:command) do
|
|
44
|
-
stub(
|
|
45
|
-
run_command: true,
|
|
46
|
-
error!: true,
|
|
47
|
-
stdout: "",
|
|
48
|
-
execution_time: 123
|
|
49
|
-
)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
let(:subject) { Kitchen::Shelly.new }
|
|
53
|
-
|
|
54
|
-
describe "#run_command" do
|
|
55
|
-
let(:opts) do
|
|
56
|
-
{ live_stream: "alogger", timeout: 60_000 }
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
before do
|
|
60
|
-
Mixlib::ShellOut.stubs(:new).returns(command)
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
it "builds a Mixlib::ShellOut object with default options" do
|
|
64
|
-
Mixlib::ShellOut.unstub(:new)
|
|
65
|
-
Mixlib::ShellOut.expects(:new).with("yoyo", opts).returns(command)
|
|
66
|
-
|
|
67
|
-
subject.run_command("yoyo")
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
[:timeout, :cwd, :environment].each do |attr|
|
|
71
|
-
it "builds a Mixlib::ShellOut object with a custom #{attr}" do
|
|
72
|
-
opts[attr] = "custom"
|
|
73
|
-
|
|
74
|
-
Mixlib::ShellOut.unstub(:new)
|
|
75
|
-
Mixlib::ShellOut.expects(:new).with("yoyo", opts).returns(command)
|
|
76
|
-
|
|
77
|
-
subject.run_command("yoyo", attr => "custom")
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
it "returns the command's standard out" do
|
|
82
|
-
command.stubs(:stdout).returns("sweetness")
|
|
83
|
-
|
|
84
|
-
subject.run_command("icecream").must_equal "sweetness"
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
it "raises a ShellCommandFailed if the command does not cleanly exit" do
|
|
88
|
-
command.stubs(:error!)
|
|
89
|
-
.raises(Mixlib::ShellOut::ShellCommandFailed, "boom bad")
|
|
90
|
-
|
|
91
|
-
err = proc { subject.run_command("boom") }
|
|
92
|
-
.must_raise Kitchen::ShellOut::ShellCommandFailed
|
|
93
|
-
err.message.must_equal "boom bad"
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
it "raises a Kitchen::Errror tagged exception for unknown exceptions" do
|
|
97
|
-
command.stubs(:error!).raises(IOError, "boom bad")
|
|
98
|
-
|
|
99
|
-
err = proc { subject.run_command("boom") }.must_raise IOError
|
|
100
|
-
err.must_be_kind_of Kitchen::Error
|
|
101
|
-
err.message.must_equal "boom bad"
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
it "prepends with sudo if :use_sudo is truthy" do
|
|
105
|
-
Mixlib::ShellOut.unstub(:new)
|
|
106
|
-
Mixlib::ShellOut.expects(:new).with("sudo -E yo", opts).returns(command)
|
|
107
|
-
|
|
108
|
-
subject.run_command("yo", use_sudo: true)
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
it "prepends with custom :sudo_command if :use_sudo is truthy" do
|
|
112
|
-
Mixlib::ShellOut.unstub(:new)
|
|
113
|
-
Mixlib::ShellOut.expects(:new).with("wat yo", opts).returns(command)
|
|
114
|
-
|
|
115
|
-
subject.run_command("yo", use_sudo: true, sudo_command: "wat")
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
it "logs a debug BEGIN message" do
|
|
119
|
-
subject.run_command("echo whoopa\ndoopa\ndo")
|
|
120
|
-
|
|
121
|
-
subject.logs.first
|
|
122
|
-
.must_equal "[local command] BEGIN (echo whoopa\ndoopa\ndo)"
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
it "logs a debug BEGIN message with custom log subject" do
|
|
126
|
-
subject.run_command("tenac", log_subject: "thed")
|
|
127
|
-
|
|
128
|
-
subject.logs.first.must_equal "[thed command] BEGIN (tenac)"
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
it "truncates the debug BEGIN command if it spans multiple lines" do
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
it "logs a debug END message" do
|
|
135
|
-
subject.run_command("echo whoopa doopa")
|
|
136
|
-
|
|
137
|
-
subject.logs.last.must_equal "[local command] END (2m3.00s)"
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
it "logs a debug END message with custom log subject" do
|
|
141
|
-
subject.run_command("tenac", log_subject: "thed")
|
|
142
|
-
|
|
143
|
-
subject.logs.last.must_equal "[thed command] END (2m3.00s)"
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
end
|
data/spec/kitchen/ssh_spec.rb
DELETED
|
@@ -1,584 +0,0 @@
|
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
|
2
|
-
#
|
|
3
|
-
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
|
4
|
-
#
|
|
5
|
-
# Copyright (C) 2014, 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/ssh"
|
|
22
|
-
require "tmpdir"
|
|
23
|
-
require "net/ssh/test"
|
|
24
|
-
|
|
25
|
-
describe Kitchen::SSH do
|
|
26
|
-
include Net::SSH::Test
|
|
27
|
-
|
|
28
|
-
let(:logged_output) { StringIO.new }
|
|
29
|
-
let(:logger) { Logger.new(logged_output) }
|
|
30
|
-
let(:opts) { Hash.new }
|
|
31
|
-
let(:ssh) { Kitchen::SSH.new("foo", "me", opts) }
|
|
32
|
-
let(:conn) { Net::SSH::Test::Extensions::IO.with_test_extension { connection } }
|
|
33
|
-
|
|
34
|
-
before do
|
|
35
|
-
logger.level = Logger::DEBUG
|
|
36
|
-
opts[:logger] = logger
|
|
37
|
-
Net::SSH.stubs(:start).returns(conn)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
describe "establishing a connection" do
|
|
41
|
-
[
|
|
42
|
-
Errno::EACCES, Errno::EADDRINUSE, Errno::ECONNREFUSED,
|
|
43
|
-
Errno::ECONNRESET, Errno::ENETUNREACH, Errno::EHOSTUNREACH,
|
|
44
|
-
Net::SSH::Disconnect, Net::SSH::AuthenticationFailed, Net::SSH::ConnectionTimeout
|
|
45
|
-
].each do |klass|
|
|
46
|
-
describe "raising #{klass}" do
|
|
47
|
-
before do
|
|
48
|
-
Net::SSH.stubs(:start).raises(klass)
|
|
49
|
-
opts[:ssh_retries] = 3
|
|
50
|
-
ssh.stubs(:sleep)
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
it "reraises the #{klass} exception" do
|
|
54
|
-
proc { ssh.exec("nope") }.must_raise klass
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
it "attempts to connect ':ssh_retries' times" do
|
|
58
|
-
begin
|
|
59
|
-
ssh.exec("nope")
|
|
60
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
logged_output.string.lines.count do |l|
|
|
64
|
-
l =~ debug_line("[SSH] opening connection to me@foo:22<{:ssh_retries=>3}>")
|
|
65
|
-
end.must_equal opts[:ssh_retries]
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
it "sleeps for 1 second between retries" do
|
|
69
|
-
ssh.unstub(:sleep)
|
|
70
|
-
ssh.expects(:sleep).with(1).twice
|
|
71
|
-
|
|
72
|
-
begin
|
|
73
|
-
ssh.exec("nope")
|
|
74
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
it "logs the first 2 retry failures on info" do
|
|
79
|
-
begin
|
|
80
|
-
ssh.exec("nope")
|
|
81
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
logged_output.string.lines.count do |l|
|
|
85
|
-
l =~ info_line_with("[SSH] connection failed, retrying ")
|
|
86
|
-
end.must_equal 2
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
it "logs the last retry failures on warn" do
|
|
90
|
-
begin
|
|
91
|
-
ssh.exec("nope")
|
|
92
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
logged_output.string.lines.count do |l|
|
|
96
|
-
l =~ warn_line_with("[SSH] connection failed, terminating ")
|
|
97
|
-
end.must_equal 1
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
describe "#exec" do
|
|
104
|
-
describe "for a successful command" do
|
|
105
|
-
before do
|
|
106
|
-
story do |script|
|
|
107
|
-
channel = script.opens_channel
|
|
108
|
-
channel.sends_request_pty
|
|
109
|
-
channel.sends_exec("doit")
|
|
110
|
-
channel.gets_data("ok\n")
|
|
111
|
-
channel.gets_extended_data("some stderr stuffs\n")
|
|
112
|
-
channel.gets_exit_status(0)
|
|
113
|
-
channel.gets_close
|
|
114
|
-
channel.sends_close
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
it "logger displays command on debug" do
|
|
119
|
-
assert_scripted { ssh.exec("doit") }
|
|
120
|
-
|
|
121
|
-
logged_output.string.must_match debug_line(
|
|
122
|
-
"[SSH] me@foo:22<{}> (doit)"
|
|
123
|
-
)
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
it "logger displays establishing connection on debug" do
|
|
127
|
-
assert_scripted { ssh.exec("doit") }
|
|
128
|
-
|
|
129
|
-
logged_output.string.must_match debug_line(
|
|
130
|
-
"[SSH] opening connection to me@foo:22<{}>"
|
|
131
|
-
)
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
it "logger captures stdout" do
|
|
135
|
-
assert_scripted { ssh.exec("doit") }
|
|
136
|
-
|
|
137
|
-
logged_output.string.must_match(/^ok$/)
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
it "logger captures stderr" do
|
|
141
|
-
assert_scripted { ssh.exec("doit") }
|
|
142
|
-
|
|
143
|
-
logged_output.string.must_match(/^some stderr stuffs$/)
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
describe "for a failed command" do
|
|
148
|
-
before do
|
|
149
|
-
story do |script|
|
|
150
|
-
channel = script.opens_channel
|
|
151
|
-
channel.sends_request_pty
|
|
152
|
-
channel.sends_exec("doit")
|
|
153
|
-
channel.gets_data("nope\n")
|
|
154
|
-
channel.gets_extended_data("youdead\n")
|
|
155
|
-
channel.gets_exit_status(42)
|
|
156
|
-
channel.gets_close
|
|
157
|
-
channel.sends_close
|
|
158
|
-
end
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
it "logger displays command on debug" do
|
|
162
|
-
begin
|
|
163
|
-
assert_scripted { ssh.exec("doit") }
|
|
164
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
logged_output.string.must_match debug_line(
|
|
168
|
-
"[SSH] me@foo:22<{}> (doit)"
|
|
169
|
-
)
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
it "logger displays establishing connection on debug" do
|
|
173
|
-
begin
|
|
174
|
-
assert_scripted { ssh.exec("doit") }
|
|
175
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
logged_output.string.must_match debug_line(
|
|
179
|
-
"[SSH] opening connection to me@foo:22<{}>"
|
|
180
|
-
)
|
|
181
|
-
end
|
|
182
|
-
|
|
183
|
-
it "logger captures stdout" do
|
|
184
|
-
begin
|
|
185
|
-
assert_scripted { ssh.exec("doit") }
|
|
186
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
logged_output.string.must_match(/^nope$/)
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
it "logger captures stderr" do
|
|
193
|
-
begin
|
|
194
|
-
assert_scripted { ssh.exec("doit") }
|
|
195
|
-
rescue # rubocop:disable Lint/HandleExceptions
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
logged_output.string.must_match(/^youdead$/)
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
it "raises an SSHFailed exception" do
|
|
202
|
-
err = proc { assert_scripted { ssh.exec("doit") } }.must_raise Kitchen::SSHFailed
|
|
203
|
-
err.message.must_equal "SSH exited (42) for command: [doit]"
|
|
204
|
-
end
|
|
205
|
-
end
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
describe "#upload!" do
|
|
209
|
-
let(:content) { "a" * 1234 }
|
|
210
|
-
|
|
211
|
-
let(:src) do
|
|
212
|
-
file = Tempfile.new("file")
|
|
213
|
-
file.write("a" * 1234)
|
|
214
|
-
file.close
|
|
215
|
-
FileUtils.chmod(0755, file.path)
|
|
216
|
-
file
|
|
217
|
-
end
|
|
218
|
-
|
|
219
|
-
before do
|
|
220
|
-
expect_scp_session("-t /tmp/remote") do |channel|
|
|
221
|
-
file_mode = running_tests_on_windows? ? 0644 : 0755
|
|
222
|
-
channel.gets_data("\0")
|
|
223
|
-
channel.sends_data("C#{padded_octal_string(file_mode)} 1234 #{File.basename(src.path)}\n")
|
|
224
|
-
channel.gets_data("\0")
|
|
225
|
-
channel.sends_data("a" * 1234)
|
|
226
|
-
channel.sends_data("\0")
|
|
227
|
-
channel.gets_data("\0")
|
|
228
|
-
end
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
after do
|
|
232
|
-
src.unlink
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
it "uploads a file to remote over scp" do
|
|
236
|
-
assert_scripted do
|
|
237
|
-
ssh.upload!(src.path, "/tmp/remote")
|
|
238
|
-
end
|
|
239
|
-
end
|
|
240
|
-
|
|
241
|
-
it "logs upload progress to debug" do
|
|
242
|
-
assert_scripted do
|
|
243
|
-
ssh.upload!(src.path, "/tmp/remote")
|
|
244
|
-
end
|
|
245
|
-
|
|
246
|
-
logged_output.string.must_match debug_line(
|
|
247
|
-
"[SSH] opening connection to me@foo:22<{}>"
|
|
248
|
-
)
|
|
249
|
-
logged_output.string.must_match debug_line(
|
|
250
|
-
"Uploaded #{src.path} (1234 bytes)"
|
|
251
|
-
)
|
|
252
|
-
end
|
|
253
|
-
end
|
|
254
|
-
|
|
255
|
-
describe "#upload_path!" do
|
|
256
|
-
before do
|
|
257
|
-
@dir = Dir.mktmpdir("local")
|
|
258
|
-
|
|
259
|
-
# Since File.chmod is a NOOP on Windows
|
|
260
|
-
@tmp_dir_mode = running_tests_on_windows? ? 0755 : 0700
|
|
261
|
-
@alpha_file_mode = running_tests_on_windows? ? 0644 : 0644
|
|
262
|
-
@beta_file_mode = running_tests_on_windows? ? 0444 : 0555
|
|
263
|
-
|
|
264
|
-
FileUtils.chmod(0700, @dir)
|
|
265
|
-
File.open("#{@dir}/alpha", "wb") { |f| f.write("alpha-contents\n") }
|
|
266
|
-
FileUtils.chmod(0644, "#{@dir}/alpha")
|
|
267
|
-
FileUtils.mkdir_p("#{@dir}/subdir")
|
|
268
|
-
FileUtils.chmod(0755, "#{@dir}/subdir")
|
|
269
|
-
File.open("#{@dir}/subdir/beta", "wb") { |f| f.write("beta-contents\n") }
|
|
270
|
-
FileUtils.chmod(0555, "#{@dir}/subdir/beta")
|
|
271
|
-
File.open("#{@dir}/zulu", "wb") { |f| f.write("zulu-contents\n") }
|
|
272
|
-
FileUtils.chmod(0444, "#{@dir}/zulu")
|
|
273
|
-
|
|
274
|
-
expect_scp_session("-t -r /tmp/remote") do |channel|
|
|
275
|
-
channel.gets_data("\0")
|
|
276
|
-
channel.sends_data("D#{padded_octal_string(@tmp_dir_mode)} 0 #{File.basename(@dir)}\n")
|
|
277
|
-
channel.gets_data("\0")
|
|
278
|
-
channel.sends_data("C#{padded_octal_string(@alpha_file_mode)} 15 alpha\n")
|
|
279
|
-
channel.gets_data("\0")
|
|
280
|
-
channel.sends_data("alpha-contents\n")
|
|
281
|
-
channel.sends_data("\0")
|
|
282
|
-
channel.gets_data("\0")
|
|
283
|
-
channel.sends_data("D0755 0 subdir\n")
|
|
284
|
-
channel.gets_data("\0")
|
|
285
|
-
channel.sends_data("C#{padded_octal_string(@beta_file_mode)} 14 beta\n")
|
|
286
|
-
channel.gets_data("\0")
|
|
287
|
-
channel.sends_data("beta-contents\n")
|
|
288
|
-
channel.sends_data("\0")
|
|
289
|
-
channel.gets_data("\0")
|
|
290
|
-
channel.sends_data("E\n")
|
|
291
|
-
channel.gets_data("\0")
|
|
292
|
-
channel.sends_data("C0444 14 zulu\n")
|
|
293
|
-
channel.gets_data("\0")
|
|
294
|
-
channel.sends_data("zulu-contents\n")
|
|
295
|
-
channel.sends_data("\0")
|
|
296
|
-
channel.gets_data("\0")
|
|
297
|
-
channel.sends_data("E\n")
|
|
298
|
-
channel.gets_data("\0")
|
|
299
|
-
end
|
|
300
|
-
end
|
|
301
|
-
|
|
302
|
-
after do
|
|
303
|
-
FileUtils.remove_entry_secure(@dir)
|
|
304
|
-
end
|
|
305
|
-
|
|
306
|
-
it "uploads a file to remote over scp" do
|
|
307
|
-
with_sorted_dir_entries do
|
|
308
|
-
assert_scripted { ssh.upload_path!(@dir, "/tmp/remote") }
|
|
309
|
-
end
|
|
310
|
-
end
|
|
311
|
-
|
|
312
|
-
it "logs upload progress to debug" do
|
|
313
|
-
remote_base = "#{Dir.tmpdir}/#{File.basename(@dir)}"
|
|
314
|
-
|
|
315
|
-
with_sorted_dir_entries do
|
|
316
|
-
assert_scripted { ssh.upload_path!(@dir, "/tmp/remote") }
|
|
317
|
-
end
|
|
318
|
-
|
|
319
|
-
logged_output.string.must_match debug_line(
|
|
320
|
-
"[SSH] opening connection to me@foo:22<{}>"
|
|
321
|
-
)
|
|
322
|
-
logged_output.string.must_match debug_line(
|
|
323
|
-
"Uploaded #{remote_base}/alpha (15 bytes)"
|
|
324
|
-
)
|
|
325
|
-
logged_output.string.must_match debug_line(
|
|
326
|
-
"Uploaded #{remote_base}/subdir/beta (14 bytes)"
|
|
327
|
-
)
|
|
328
|
-
logged_output.string.must_match debug_line(
|
|
329
|
-
"Uploaded #{remote_base}/zulu (14 bytes)"
|
|
330
|
-
)
|
|
331
|
-
end
|
|
332
|
-
end
|
|
333
|
-
|
|
334
|
-
describe "#shutdown" do
|
|
335
|
-
before do
|
|
336
|
-
story do |script|
|
|
337
|
-
channel = script.opens_channel
|
|
338
|
-
channel.sends_request_pty
|
|
339
|
-
channel.sends_exec("doit")
|
|
340
|
-
channel.gets_data("ok\n")
|
|
341
|
-
channel.gets_exit_status(0)
|
|
342
|
-
channel.gets_close
|
|
343
|
-
channel.sends_close
|
|
344
|
-
end
|
|
345
|
-
end
|
|
346
|
-
|
|
347
|
-
it "logger displays closing connection on debug" do
|
|
348
|
-
conn.expects(:shutdown!)
|
|
349
|
-
|
|
350
|
-
assert_scripted do
|
|
351
|
-
ssh.exec("doit")
|
|
352
|
-
ssh.shutdown
|
|
353
|
-
end
|
|
354
|
-
|
|
355
|
-
logged_output.string.must_match debug_line(
|
|
356
|
-
"[SSH] closing connection to me@foo:22<{}>"
|
|
357
|
-
)
|
|
358
|
-
end
|
|
359
|
-
|
|
360
|
-
it "only closes the connection once for multiple calls" do
|
|
361
|
-
conn.expects(:shutdown!).once
|
|
362
|
-
|
|
363
|
-
assert_scripted do
|
|
364
|
-
ssh.exec("doit")
|
|
365
|
-
ssh.shutdown
|
|
366
|
-
ssh.shutdown
|
|
367
|
-
ssh.shutdown
|
|
368
|
-
end
|
|
369
|
-
end
|
|
370
|
-
end
|
|
371
|
-
|
|
372
|
-
describe "block form" do
|
|
373
|
-
before do
|
|
374
|
-
story do |script|
|
|
375
|
-
channel = script.opens_channel
|
|
376
|
-
channel.sends_request_pty
|
|
377
|
-
channel.sends_exec("doit")
|
|
378
|
-
channel.gets_data("ok\n")
|
|
379
|
-
channel.gets_exit_status(0)
|
|
380
|
-
channel.gets_close
|
|
381
|
-
channel.sends_close
|
|
382
|
-
end
|
|
383
|
-
end
|
|
384
|
-
|
|
385
|
-
it "shuts down the connection when block closes" do
|
|
386
|
-
conn.expects(:shutdown!)
|
|
387
|
-
|
|
388
|
-
Net::SSH::Test::Extensions::IO.with_test_extension do
|
|
389
|
-
Kitchen::SSH.new("foo", "me", opts) do |ssh|
|
|
390
|
-
ssh.exec("doit")
|
|
391
|
-
end
|
|
392
|
-
end
|
|
393
|
-
end
|
|
394
|
-
end
|
|
395
|
-
|
|
396
|
-
describe "#login_command" do
|
|
397
|
-
let(:login_command) { ssh.login_command }
|
|
398
|
-
let(:args) { login_command.arguments.join(" ") }
|
|
399
|
-
|
|
400
|
-
it "returns a LoginCommand" do
|
|
401
|
-
login_command.must_be_instance_of Kitchen::LoginCommand
|
|
402
|
-
end
|
|
403
|
-
|
|
404
|
-
it "is an SSH command" do
|
|
405
|
-
login_command.command.must_equal "ssh"
|
|
406
|
-
args.must_match %r{ me@foo$}
|
|
407
|
-
end
|
|
408
|
-
|
|
409
|
-
it "sets the UserKnownHostsFile option" do
|
|
410
|
-
args.must_match regexify("-o UserKnownHostsFile=/dev/null ")
|
|
411
|
-
end
|
|
412
|
-
|
|
413
|
-
it "sets the StrictHostKeyChecking option" do
|
|
414
|
-
args.must_match regexify(" -o StrictHostKeyChecking=no ")
|
|
415
|
-
end
|
|
416
|
-
|
|
417
|
-
it "won't set IdentitiesOnly option by default" do
|
|
418
|
-
args.wont_match regexify(" -o IdentitiesOnly=")
|
|
419
|
-
end
|
|
420
|
-
|
|
421
|
-
it "sets the IdentiesOnly option if :keys option is given" do
|
|
422
|
-
opts[:keys] = ["yep"]
|
|
423
|
-
|
|
424
|
-
args.must_match regexify(" -o IdentitiesOnly=yes ")
|
|
425
|
-
end
|
|
426
|
-
|
|
427
|
-
it "sets the LogLevel option to VERBOSE if logger is set to debug" do
|
|
428
|
-
logger.level = ::Logger::DEBUG
|
|
429
|
-
opts[:logger] = logger
|
|
430
|
-
|
|
431
|
-
args.must_match regexify(" -o LogLevel=VERBOSE ")
|
|
432
|
-
end
|
|
433
|
-
|
|
434
|
-
it "sets the LogLevel option to ERROR if logger is not set to debug" do
|
|
435
|
-
logger.level = ::Logger::INFO
|
|
436
|
-
opts[:logger] = logger
|
|
437
|
-
|
|
438
|
-
args.must_match regexify(" -o LogLevel=ERROR ")
|
|
439
|
-
end
|
|
440
|
-
|
|
441
|
-
it "won't set the ForwardAgent option by default" do
|
|
442
|
-
args.wont_match regexify(" -o ForwardAgent=")
|
|
443
|
-
end
|
|
444
|
-
|
|
445
|
-
it "sets the ForwardAgent option to yes if truthy" do
|
|
446
|
-
opts[:forward_agent] = "yep"
|
|
447
|
-
|
|
448
|
-
args.must_match regexify(" -o ForwardAgent=yes")
|
|
449
|
-
end
|
|
450
|
-
|
|
451
|
-
it "sets the ForwardAgent option to no if falsey" do
|
|
452
|
-
opts[:forward_agent] = false
|
|
453
|
-
|
|
454
|
-
args.must_match regexify(" -o ForwardAgent=no")
|
|
455
|
-
end
|
|
456
|
-
|
|
457
|
-
it "won't add any SSH keys by default" do
|
|
458
|
-
args.wont_match regexify(" -i ")
|
|
459
|
-
end
|
|
460
|
-
|
|
461
|
-
it "sets SSH keys options if given" do
|
|
462
|
-
opts[:keys] = %w{one two}
|
|
463
|
-
|
|
464
|
-
args.must_match regexify(" -i one ")
|
|
465
|
-
args.must_match regexify(" -i two ")
|
|
466
|
-
end
|
|
467
|
-
|
|
468
|
-
it "sets the port option to 22 by default" do
|
|
469
|
-
args.must_match regexify(" -p 22 ")
|
|
470
|
-
end
|
|
471
|
-
|
|
472
|
-
it "sets the port option" do
|
|
473
|
-
opts[:port] = 1234
|
|
474
|
-
|
|
475
|
-
args.must_match regexify(" -p 1234 ")
|
|
476
|
-
end
|
|
477
|
-
end
|
|
478
|
-
|
|
479
|
-
describe "#test_ssh" do
|
|
480
|
-
let(:tcp_socket) { stub(select_for_read?: true, close: true) }
|
|
481
|
-
|
|
482
|
-
before { ssh.stubs(:sleep) }
|
|
483
|
-
|
|
484
|
-
it "returns a truthy value" do
|
|
485
|
-
TCPSocket.stubs(:new).returns(tcp_socket)
|
|
486
|
-
|
|
487
|
-
Net::SSH::Test::Extensions::IO.with_test_extension do
|
|
488
|
-
result = ssh.send(:test_ssh)
|
|
489
|
-
result.wont_equal nil
|
|
490
|
-
result.wont_equal false
|
|
491
|
-
end
|
|
492
|
-
end
|
|
493
|
-
|
|
494
|
-
it "closes socket when finished" do
|
|
495
|
-
TCPSocket.stubs(:new).returns(tcp_socket)
|
|
496
|
-
tcp_socket.expects(:close)
|
|
497
|
-
|
|
498
|
-
Net::SSH::Test::Extensions::IO.with_test_extension { ssh.send(:test_ssh) }
|
|
499
|
-
end
|
|
500
|
-
|
|
501
|
-
[
|
|
502
|
-
SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH,
|
|
503
|
-
Errno::ENETUNREACH, IOError
|
|
504
|
-
].each do |klass|
|
|
505
|
-
describe "when #{klass} is raised" do
|
|
506
|
-
before { TCPSocket.stubs(:new).raises(klass) }
|
|
507
|
-
|
|
508
|
-
it "returns false" do
|
|
509
|
-
ssh.send(:test_ssh).must_equal false
|
|
510
|
-
end
|
|
511
|
-
|
|
512
|
-
it "sleeps for 2 seconds" do
|
|
513
|
-
ssh.expects(:sleep).with(2)
|
|
514
|
-
|
|
515
|
-
ssh.send(:test_ssh)
|
|
516
|
-
end
|
|
517
|
-
end
|
|
518
|
-
end
|
|
519
|
-
|
|
520
|
-
[
|
|
521
|
-
Errno::EPERM, Errno::ETIMEDOUT
|
|
522
|
-
].each do |klass|
|
|
523
|
-
describe "when #{klass} is raised" do
|
|
524
|
-
it "returns false when #{klass} is raised" do
|
|
525
|
-
TCPSocket.stubs(:new).raises(klass)
|
|
526
|
-
|
|
527
|
-
ssh.send(:test_ssh).must_equal false
|
|
528
|
-
end
|
|
529
|
-
end
|
|
530
|
-
end
|
|
531
|
-
end
|
|
532
|
-
|
|
533
|
-
describe "#wait" do
|
|
534
|
-
let(:not_ready) do
|
|
535
|
-
stub(select_for_read?: false, idle!: true, close: true)
|
|
536
|
-
end
|
|
537
|
-
|
|
538
|
-
let(:ready) do
|
|
539
|
-
stub(select_for_read?: true, close: true)
|
|
540
|
-
end
|
|
541
|
-
|
|
542
|
-
it "logs to info for each retry" do
|
|
543
|
-
TCPSocket.stubs(:new).returns(not_ready, not_ready, ready)
|
|
544
|
-
Net::SSH::Test::Extensions::IO.with_test_extension { ssh.wait }
|
|
545
|
-
|
|
546
|
-
logged_output.string.lines.count do |l|
|
|
547
|
-
l =~ info_line_with("Waiting for foo:22...")
|
|
548
|
-
end.must_equal 2
|
|
549
|
-
end
|
|
550
|
-
end
|
|
551
|
-
|
|
552
|
-
def expect_scp_session(args)
|
|
553
|
-
story do |script|
|
|
554
|
-
channel = script.opens_channel
|
|
555
|
-
channel.sends_exec("scp #{args}")
|
|
556
|
-
yield channel if block_given?
|
|
557
|
-
channel.sends_eof
|
|
558
|
-
channel.gets_exit_status(0)
|
|
559
|
-
channel.gets_eof
|
|
560
|
-
channel.gets_close
|
|
561
|
-
channel.sends_close
|
|
562
|
-
end
|
|
563
|
-
end
|
|
564
|
-
|
|
565
|
-
def regexify(string)
|
|
566
|
-
Regexp.new(Regexp.escape(string))
|
|
567
|
-
end
|
|
568
|
-
|
|
569
|
-
def debug_line(msg)
|
|
570
|
-
/^D, .* : #{Regexp.escape(msg)}$/
|
|
571
|
-
end
|
|
572
|
-
|
|
573
|
-
def debug_line_with(msg)
|
|
574
|
-
/^D, .* : #{Regexp.escape(msg)}/
|
|
575
|
-
end
|
|
576
|
-
|
|
577
|
-
def info_line_with(msg)
|
|
578
|
-
/^I, .* : #{Regexp.escape(msg)}/
|
|
579
|
-
end
|
|
580
|
-
|
|
581
|
-
def warn_line_with(msg)
|
|
582
|
-
/^W, .* : #{Regexp.escape(msg)}/
|
|
583
|
-
end
|
|
584
|
-
end
|