test-kitchen 1.7.0 → 1.7.1.dev
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/.cane +8 -8
- data/.gitattributes +3 -0
- data/.github/ISSUE_TEMPLATE.md +55 -55
- data/.gitignore +28 -28
- data/.kitchen.ci.yml +23 -23
- data/.kitchen.proxy.yml +27 -27
- data/.rubocop.yml +3 -3
- data/.travis.yml +70 -70
- data/.yardopts +3 -3
- data/Berksfile +3 -3
- data/CHANGELOG.md +1090 -1083
- data/CONTRIBUTING.md +14 -14
- data/Gemfile +19 -19
- data/Gemfile.proxy_tests +4 -4
- data/Guardfile +42 -42
- data/LICENSE +15 -15
- data/MAINTAINERS.md +23 -23
- data/README.md +135 -135
- data/Rakefile +61 -61
- data/appveyor.yml +44 -44
- data/features/kitchen_action_commands.feature +164 -164
- data/features/kitchen_command.feature +16 -16
- data/features/kitchen_console_command.feature +34 -34
- data/features/kitchen_defaults.feature +38 -38
- data/features/kitchen_diagnose_command.feature +96 -96
- data/features/kitchen_driver_create_command.feature +64 -64
- data/features/kitchen_driver_discover_command.feature +25 -25
- data/features/kitchen_help_command.feature +16 -16
- data/features/kitchen_init_command.feature +274 -274
- data/features/kitchen_list_command.feature +104 -104
- data/features/kitchen_login_command.feature +62 -62
- data/features/kitchen_sink_command.feature +30 -30
- data/features/kitchen_test_command.feature +88 -88
- data/features/step_definitions/gem_steps.rb +36 -36
- data/features/step_definitions/git_steps.rb +5 -5
- data/features/step_definitions/output_steps.rb +5 -5
- data/features/support/env.rb +75 -75
- data/lib/kitchen.rb +150 -150
- data/lib/kitchen/base64_stream.rb +55 -55
- data/lib/kitchen/cli.rb +419 -419
- data/lib/kitchen/collection.rb +55 -55
- data/lib/kitchen/color.rb +65 -65
- data/lib/kitchen/command.rb +185 -185
- data/lib/kitchen/command/action.rb +45 -45
- data/lib/kitchen/command/console.rb +58 -58
- data/lib/kitchen/command/diagnose.rb +92 -92
- data/lib/kitchen/command/driver_discover.rb +105 -105
- data/lib/kitchen/command/exec.rb +41 -41
- data/lib/kitchen/command/list.rb +119 -119
- data/lib/kitchen/command/login.rb +43 -43
- data/lib/kitchen/command/sink.rb +54 -54
- data/lib/kitchen/command/test.rb +51 -51
- data/lib/kitchen/config.rb +322 -322
- data/lib/kitchen/configurable.rb +529 -529
- data/lib/kitchen/data_munger.rb +959 -959
- data/lib/kitchen/diagnostic.rb +141 -141
- data/lib/kitchen/driver.rb +56 -56
- data/lib/kitchen/driver/base.rb +134 -134
- data/lib/kitchen/driver/dummy.rb +108 -108
- data/lib/kitchen/driver/proxy.rb +72 -72
- data/lib/kitchen/driver/ssh_base.rb +357 -357
- data/lib/kitchen/errors.rb +229 -229
- data/lib/kitchen/generator/driver_create.rb +177 -177
- data/lib/kitchen/generator/init.rb +296 -296
- data/lib/kitchen/instance.rb +662 -662
- data/lib/kitchen/lazy_hash.rb +142 -142
- data/lib/kitchen/loader/yaml.rb +349 -349
- data/lib/kitchen/logger.rb +423 -423
- data/lib/kitchen/logging.rb +56 -56
- data/lib/kitchen/login_command.rb +52 -52
- data/lib/kitchen/metadata_chopper.rb +52 -52
- data/lib/kitchen/platform.rb +67 -67
- data/lib/kitchen/provisioner.rb +54 -54
- data/lib/kitchen/provisioner/base.rb +236 -236
- data/lib/kitchen/provisioner/chef/berkshelf.rb +114 -114
- data/lib/kitchen/provisioner/chef/common_sandbox.rb +322 -322
- data/lib/kitchen/provisioner/chef/librarian.rb +112 -112
- data/lib/kitchen/provisioner/chef_apply.rb +124 -124
- data/lib/kitchen/provisioner/chef_base.rb +341 -341
- data/lib/kitchen/provisioner/chef_solo.rb +88 -88
- data/lib/kitchen/provisioner/chef_zero.rb +245 -245
- data/lib/kitchen/provisioner/dummy.rb +79 -79
- data/lib/kitchen/provisioner/shell.rb +138 -138
- data/lib/kitchen/rake_tasks.rb +63 -63
- data/lib/kitchen/shell_out.rb +93 -93
- data/lib/kitchen/ssh.rb +276 -276
- data/lib/kitchen/state_file.rb +120 -120
- data/lib/kitchen/suite.rb +51 -51
- data/lib/kitchen/thor_tasks.rb +66 -66
- data/lib/kitchen/transport.rb +54 -54
- data/lib/kitchen/transport/base.rb +176 -176
- data/lib/kitchen/transport/dummy.rb +79 -79
- data/lib/kitchen/transport/ssh.rb +364 -364
- data/lib/kitchen/transport/winrm.rb +486 -486
- data/lib/kitchen/util.rb +147 -147
- data/lib/kitchen/verifier.rb +55 -55
- data/lib/kitchen/verifier/base.rb +235 -235
- data/lib/kitchen/verifier/busser.rb +277 -277
- data/lib/kitchen/verifier/dummy.rb +79 -79
- data/lib/kitchen/verifier/shell.rb +101 -101
- data/lib/kitchen/version.rb +21 -21
- data/lib/vendor/hash_recursive_merge.rb +82 -82
- data/spec/kitchen/base64_stream_spec.rb +77 -77
- data/spec/kitchen/cli_spec.rb +56 -56
- data/spec/kitchen/collection_spec.rb +80 -80
- data/spec/kitchen/color_spec.rb +54 -54
- data/spec/kitchen/config_spec.rb +408 -408
- data/spec/kitchen/configurable_spec.rb +1095 -1095
- data/spec/kitchen/data_munger_spec.rb +2694 -2694
- data/spec/kitchen/diagnostic_spec.rb +129 -129
- data/spec/kitchen/driver/base_spec.rb +121 -121
- data/spec/kitchen/driver/dummy_spec.rb +199 -199
- data/spec/kitchen/driver/proxy_spec.rb +138 -138
- data/spec/kitchen/driver/ssh_base_spec.rb +1115 -1115
- data/spec/kitchen/driver_spec.rb +112 -112
- data/spec/kitchen/errors_spec.rb +309 -309
- data/spec/kitchen/instance_spec.rb +1419 -1419
- data/spec/kitchen/lazy_hash_spec.rb +117 -117
- data/spec/kitchen/loader/yaml_spec.rb +774 -774
- data/spec/kitchen/logger_spec.rb +429 -429
- data/spec/kitchen/logging_spec.rb +59 -59
- data/spec/kitchen/login_command_spec.rb +68 -68
- data/spec/kitchen/metadata_chopper_spec.rb +82 -82
- data/spec/kitchen/platform_spec.rb +89 -89
- data/spec/kitchen/provisioner/base_spec.rb +386 -386
- data/spec/kitchen/provisioner/chef_apply_spec.rb +136 -136
- data/spec/kitchen/provisioner/chef_base_spec.rb +1161 -1161
- data/spec/kitchen/provisioner/chef_solo_spec.rb +557 -557
- data/spec/kitchen/provisioner/chef_zero_spec.rb +1001 -1001
- data/spec/kitchen/provisioner/dummy_spec.rb +99 -99
- data/spec/kitchen/provisioner/shell_spec.rb +566 -566
- data/spec/kitchen/provisioner_spec.rb +107 -107
- data/spec/kitchen/shell_out_spec.rb +150 -150
- data/spec/kitchen/ssh_spec.rb +693 -693
- data/spec/kitchen/state_file_spec.rb +129 -129
- data/spec/kitchen/suite_spec.rb +62 -62
- data/spec/kitchen/transport/base_spec.rb +89 -89
- data/spec/kitchen/transport/ssh_spec.rb +1255 -1255
- data/spec/kitchen/transport/winrm_spec.rb +1143 -1143
- data/spec/kitchen/transport_spec.rb +112 -112
- data/spec/kitchen/util_spec.rb +165 -165
- data/spec/kitchen/verifier/base_spec.rb +362 -362
- data/spec/kitchen/verifier/busser_spec.rb +610 -610
- data/spec/kitchen/verifier/dummy_spec.rb +99 -99
- data/spec/kitchen/verifier/shell_spec.rb +160 -160
- data/spec/kitchen/verifier_spec.rb +120 -120
- data/spec/kitchen_spec.rb +114 -114
- data/spec/spec_helper.rb +85 -85
- data/spec/support/powershell_max_size_spec.rb +40 -40
- data/support/busser_install_command.ps1 +14 -14
- data/support/busser_install_command.sh +14 -14
- data/support/chef-client-zero.rb +77 -77
- data/support/chef_base_init_command.ps1 +18 -18
- data/support/chef_base_init_command.sh +2 -2
- data/support/chef_base_install_command.ps1 +85 -85
- data/support/chef_base_install_command.sh +229 -229
- data/support/chef_zero_prepare_command_legacy.ps1 +9 -9
- data/support/chef_zero_prepare_command_legacy.sh +10 -10
- data/support/download_helpers.sh +109 -109
- data/support/dummy-validation.pem +27 -27
- data/templates/driver/CHANGELOG.md.erb +3 -3
- data/templates/driver/Gemfile.erb +3 -3
- data/templates/driver/README.md.erb +64 -64
- data/templates/driver/Rakefile.erb +21 -21
- data/templates/driver/driver.rb.erb +23 -23
- data/templates/driver/gemspec.erb +29 -29
- data/templates/driver/gitignore.erb +17 -17
- data/templates/driver/license_apachev2.erb +15 -15
- data/templates/driver/license_lgplv3.erb +16 -16
- data/templates/driver/license_mit.erb +22 -22
- data/templates/driver/license_reserved.erb +5 -5
- data/templates/driver/tailor.erb +4 -4
- data/templates/driver/travis.yml.erb +11 -11
- data/templates/driver/version.rb.erb +12 -12
- data/templates/init/chefignore.erb +1 -1
- data/templates/init/kitchen.yml.erb +18 -18
- data/test-kitchen.gemspec +62 -62
- data/test/integration/default/default_spec.rb +3 -3
- data/testing_windows.md +37 -37
- metadata +5 -4
data/lib/kitchen/util.rb
CHANGED
|
@@ -1,147 +1,147 @@
|
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
|
2
|
-
#
|
|
3
|
-
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
|
4
|
-
#
|
|
5
|
-
# Copyright (C) 2012, 2013, 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
|
-
module Kitchen
|
|
20
|
-
|
|
21
|
-
# Stateless utility methods used in different contexts. Essentially a mini
|
|
22
|
-
# PassiveSupport library.
|
|
23
|
-
#
|
|
24
|
-
# @author Fletcher Nichol <fnichol@nichol.ca>
|
|
25
|
-
module Util
|
|
26
|
-
|
|
27
|
-
# Returns the standard library Logger level constants for a given symbol
|
|
28
|
-
# representation.
|
|
29
|
-
#
|
|
30
|
-
# @param symbol [Symbol] symbol representation of a logger level (:debug,
|
|
31
|
-
# :info, :warn, :error, :fatal)
|
|
32
|
-
# @return [Integer] Logger::Severity constant value or nil if input is not
|
|
33
|
-
# valid
|
|
34
|
-
def self.to_logger_level(symbol)
|
|
35
|
-
return nil unless [:debug, :info, :warn, :error, :fatal].include?(symbol)
|
|
36
|
-
|
|
37
|
-
Logger.const_get(symbol.to_s.upcase)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# Returns the symbol represenation of a logging levels for a given
|
|
41
|
-
# standard library Logger::Severity constant.
|
|
42
|
-
#
|
|
43
|
-
# @param const [Integer] Logger::Severity constant value for a logging
|
|
44
|
-
# level (Logger::DEBUG, Logger::INFO, Logger::WARN, Logger::ERROR,
|
|
45
|
-
# Logger::FATAL)
|
|
46
|
-
# @return [Symbol] symbol representation of the logging level
|
|
47
|
-
def self.from_logger_level(const)
|
|
48
|
-
case const
|
|
49
|
-
when Logger::DEBUG then :debug
|
|
50
|
-
when Logger::INFO then :info
|
|
51
|
-
when Logger::WARN then :warn
|
|
52
|
-
when Logger::ERROR then :error
|
|
53
|
-
else :fatal
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# Returns a new Hash with all key values coerced to symbols. All keys
|
|
58
|
-
# within a Hash are coerced by calling #to_sym and hashes within arrays
|
|
59
|
-
# and other hashes are traversed.
|
|
60
|
-
#
|
|
61
|
-
# @param obj [Object] the hash to be processed. While intended for
|
|
62
|
-
# hashes, this method safely processes arbitrary objects
|
|
63
|
-
# @return [Object] a converted hash with all keys as symbols
|
|
64
|
-
def self.symbolized_hash(obj)
|
|
65
|
-
if obj.is_a?(Hash)
|
|
66
|
-
obj.inject({}) { |h, (k, v)| h[k.to_sym] = symbolized_hash(v); h }
|
|
67
|
-
elsif obj.is_a?(Array)
|
|
68
|
-
obj.inject([]) { |a, e| a << symbolized_hash(e); a }
|
|
69
|
-
else
|
|
70
|
-
obj
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# Returns a new Hash with all key values coerced to strings. All keys
|
|
75
|
-
# within a Hash are coerced by calling #to_s and hashes with arrays
|
|
76
|
-
# and other hashes are traversed.
|
|
77
|
-
#
|
|
78
|
-
# @param obj [Object] the hash to be processed. While intended for
|
|
79
|
-
# hashes, this method safely processes arbitrary objects
|
|
80
|
-
# @return [Object] a converted hash with all keys as strings
|
|
81
|
-
def self.stringified_hash(obj)
|
|
82
|
-
if obj.is_a?(Hash)
|
|
83
|
-
obj.inject({}) { |h, (k, v)| h[k.to_s] = stringified_hash(v); h }
|
|
84
|
-
elsif obj.is_a?(Array)
|
|
85
|
-
obj.inject([]) { |a, e| a << stringified_hash(e); a }
|
|
86
|
-
else
|
|
87
|
-
obj
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# Returns a formatted string representing a duration in seconds.
|
|
92
|
-
#
|
|
93
|
-
# @param total [Integer] the total number of seconds
|
|
94
|
-
# @return [String] a formatted string of the form (XmYY.00s)
|
|
95
|
-
def self.duration(total)
|
|
96
|
-
total = 0 if total.nil?
|
|
97
|
-
minutes = (total / 60).to_i
|
|
98
|
-
seconds = (total - (minutes * 60))
|
|
99
|
-
format("(%dm%.2fs)", minutes, seconds)
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
# Generates a command (or series of commands) wrapped so that it can be
|
|
103
|
-
# invoked on a remote instance or locally.
|
|
104
|
-
#
|
|
105
|
-
# This method uses the Bourne shell (/bin/sh) to maximize the chance of
|
|
106
|
-
# cross platform portability on Unixlike systems.
|
|
107
|
-
#
|
|
108
|
-
# @param [String] the command
|
|
109
|
-
# @return [String] a wrapped command string
|
|
110
|
-
def self.wrap_command(cmd)
|
|
111
|
-
cmd = "false" if cmd.nil?
|
|
112
|
-
cmd = "true" if cmd.to_s.empty?
|
|
113
|
-
cmd = cmd.sub(/\n\Z/, "") if cmd =~ /\n\Z/
|
|
114
|
-
|
|
115
|
-
"sh -c '\n#{cmd}\n'"
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
# Modifes the given string to strip leading whitespace on each line, the
|
|
119
|
-
# amount which is calculated by using the first line of text.
|
|
120
|
-
#
|
|
121
|
-
# @example
|
|
122
|
-
#
|
|
123
|
-
# string = <<-STRING
|
|
124
|
-
# a
|
|
125
|
-
# b
|
|
126
|
-
# c
|
|
127
|
-
# STRING
|
|
128
|
-
# Util.outdent!(string) # => "a\n b\nc\n"
|
|
129
|
-
#
|
|
130
|
-
# @param string [String] the string that will be modified
|
|
131
|
-
# @return [String] the modified string
|
|
132
|
-
def self.outdent!(string)
|
|
133
|
-
string.gsub!(/^ {#{string.index(/[^ ]/)}}/, "")
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
# Returns a set of Bourne Shell (AKA /bin/sh) compatible helper
|
|
137
|
-
# functions. This function is usually called inline in a string that
|
|
138
|
-
# will be executed remotely on a test instance.
|
|
139
|
-
#
|
|
140
|
-
# @return [String] a string representation of useful helper functions
|
|
141
|
-
def self.shell_helpers
|
|
142
|
-
IO.read(File.join(
|
|
143
|
-
File.dirname(__FILE__), %w[.. .. support download_helpers.sh]
|
|
144
|
-
))
|
|
145
|
-
end
|
|
146
|
-
end
|
|
147
|
-
end
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
|
4
|
+
#
|
|
5
|
+
# Copyright (C) 2012, 2013, 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
|
+
module Kitchen
|
|
20
|
+
|
|
21
|
+
# Stateless utility methods used in different contexts. Essentially a mini
|
|
22
|
+
# PassiveSupport library.
|
|
23
|
+
#
|
|
24
|
+
# @author Fletcher Nichol <fnichol@nichol.ca>
|
|
25
|
+
module Util
|
|
26
|
+
|
|
27
|
+
# Returns the standard library Logger level constants for a given symbol
|
|
28
|
+
# representation.
|
|
29
|
+
#
|
|
30
|
+
# @param symbol [Symbol] symbol representation of a logger level (:debug,
|
|
31
|
+
# :info, :warn, :error, :fatal)
|
|
32
|
+
# @return [Integer] Logger::Severity constant value or nil if input is not
|
|
33
|
+
# valid
|
|
34
|
+
def self.to_logger_level(symbol)
|
|
35
|
+
return nil unless [:debug, :info, :warn, :error, :fatal].include?(symbol)
|
|
36
|
+
|
|
37
|
+
Logger.const_get(symbol.to_s.upcase)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Returns the symbol represenation of a logging levels for a given
|
|
41
|
+
# standard library Logger::Severity constant.
|
|
42
|
+
#
|
|
43
|
+
# @param const [Integer] Logger::Severity constant value for a logging
|
|
44
|
+
# level (Logger::DEBUG, Logger::INFO, Logger::WARN, Logger::ERROR,
|
|
45
|
+
# Logger::FATAL)
|
|
46
|
+
# @return [Symbol] symbol representation of the logging level
|
|
47
|
+
def self.from_logger_level(const)
|
|
48
|
+
case const
|
|
49
|
+
when Logger::DEBUG then :debug
|
|
50
|
+
when Logger::INFO then :info
|
|
51
|
+
when Logger::WARN then :warn
|
|
52
|
+
when Logger::ERROR then :error
|
|
53
|
+
else :fatal
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Returns a new Hash with all key values coerced to symbols. All keys
|
|
58
|
+
# within a Hash are coerced by calling #to_sym and hashes within arrays
|
|
59
|
+
# and other hashes are traversed.
|
|
60
|
+
#
|
|
61
|
+
# @param obj [Object] the hash to be processed. While intended for
|
|
62
|
+
# hashes, this method safely processes arbitrary objects
|
|
63
|
+
# @return [Object] a converted hash with all keys as symbols
|
|
64
|
+
def self.symbolized_hash(obj)
|
|
65
|
+
if obj.is_a?(Hash)
|
|
66
|
+
obj.inject({}) { |h, (k, v)| h[k.to_sym] = symbolized_hash(v); h }
|
|
67
|
+
elsif obj.is_a?(Array)
|
|
68
|
+
obj.inject([]) { |a, e| a << symbolized_hash(e); a }
|
|
69
|
+
else
|
|
70
|
+
obj
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Returns a new Hash with all key values coerced to strings. All keys
|
|
75
|
+
# within a Hash are coerced by calling #to_s and hashes with arrays
|
|
76
|
+
# and other hashes are traversed.
|
|
77
|
+
#
|
|
78
|
+
# @param obj [Object] the hash to be processed. While intended for
|
|
79
|
+
# hashes, this method safely processes arbitrary objects
|
|
80
|
+
# @return [Object] a converted hash with all keys as strings
|
|
81
|
+
def self.stringified_hash(obj)
|
|
82
|
+
if obj.is_a?(Hash)
|
|
83
|
+
obj.inject({}) { |h, (k, v)| h[k.to_s] = stringified_hash(v); h }
|
|
84
|
+
elsif obj.is_a?(Array)
|
|
85
|
+
obj.inject([]) { |a, e| a << stringified_hash(e); a }
|
|
86
|
+
else
|
|
87
|
+
obj
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Returns a formatted string representing a duration in seconds.
|
|
92
|
+
#
|
|
93
|
+
# @param total [Integer] the total number of seconds
|
|
94
|
+
# @return [String] a formatted string of the form (XmYY.00s)
|
|
95
|
+
def self.duration(total)
|
|
96
|
+
total = 0 if total.nil?
|
|
97
|
+
minutes = (total / 60).to_i
|
|
98
|
+
seconds = (total - (minutes * 60))
|
|
99
|
+
format("(%dm%.2fs)", minutes, seconds)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Generates a command (or series of commands) wrapped so that it can be
|
|
103
|
+
# invoked on a remote instance or locally.
|
|
104
|
+
#
|
|
105
|
+
# This method uses the Bourne shell (/bin/sh) to maximize the chance of
|
|
106
|
+
# cross platform portability on Unixlike systems.
|
|
107
|
+
#
|
|
108
|
+
# @param [String] the command
|
|
109
|
+
# @return [String] a wrapped command string
|
|
110
|
+
def self.wrap_command(cmd)
|
|
111
|
+
cmd = "false" if cmd.nil?
|
|
112
|
+
cmd = "true" if cmd.to_s.empty?
|
|
113
|
+
cmd = cmd.sub(/\n\Z/, "") if cmd =~ /\n\Z/
|
|
114
|
+
|
|
115
|
+
"sh -c '\n#{cmd}\n'"
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Modifes the given string to strip leading whitespace on each line, the
|
|
119
|
+
# amount which is calculated by using the first line of text.
|
|
120
|
+
#
|
|
121
|
+
# @example
|
|
122
|
+
#
|
|
123
|
+
# string = <<-STRING
|
|
124
|
+
# a
|
|
125
|
+
# b
|
|
126
|
+
# c
|
|
127
|
+
# STRING
|
|
128
|
+
# Util.outdent!(string) # => "a\n b\nc\n"
|
|
129
|
+
#
|
|
130
|
+
# @param string [String] the string that will be modified
|
|
131
|
+
# @return [String] the modified string
|
|
132
|
+
def self.outdent!(string)
|
|
133
|
+
string.gsub!(/^ {#{string.index(/[^ ]/)}}/, "")
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Returns a set of Bourne Shell (AKA /bin/sh) compatible helper
|
|
137
|
+
# functions. This function is usually called inline in a string that
|
|
138
|
+
# will be executed remotely on a test instance.
|
|
139
|
+
#
|
|
140
|
+
# @return [String] a string representation of useful helper functions
|
|
141
|
+
def self.shell_helpers
|
|
142
|
+
IO.read(File.join(
|
|
143
|
+
File.dirname(__FILE__), %w[.. .. support download_helpers.sh]
|
|
144
|
+
))
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
data/lib/kitchen/verifier.rb
CHANGED
|
@@ -1,55 +1,55 @@
|
|
|
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 "thor/util"
|
|
20
|
-
|
|
21
|
-
require "kitchen/errors"
|
|
22
|
-
|
|
23
|
-
module Kitchen
|
|
24
|
-
|
|
25
|
-
# A verifier is responsible for running tests post-converge to confirm that
|
|
26
|
-
# the instance is in a known/consistent state.
|
|
27
|
-
#
|
|
28
|
-
# @author Fletcher Nichol <fnichol@nichol.ca>
|
|
29
|
-
module Verifier
|
|
30
|
-
|
|
31
|
-
# Default verifier to use
|
|
32
|
-
DEFAULT_PLUGIN = "busser".freeze
|
|
33
|
-
|
|
34
|
-
# Returns an instance of a verifier given a plugin type string.
|
|
35
|
-
#
|
|
36
|
-
# @param plugin [String] a verifier plugin type, to be constantized
|
|
37
|
-
# @param config [Hash] a configuration hash to initialize the verifier
|
|
38
|
-
# @return [Verifier::Base] a verifier instance
|
|
39
|
-
# @raise [ClientError] if a verifier instance could not be created
|
|
40
|
-
def self.for_plugin(plugin, config)
|
|
41
|
-
first_load = require("kitchen/verifier/#{plugin}")
|
|
42
|
-
|
|
43
|
-
str_const = Thor::Util.camel_case(plugin)
|
|
44
|
-
klass = const_get(str_const)
|
|
45
|
-
object = klass.new(config)
|
|
46
|
-
object.verify_dependencies if first_load
|
|
47
|
-
object
|
|
48
|
-
rescue LoadError, NameError
|
|
49
|
-
raise ClientError,
|
|
50
|
-
"Could not load the '#{plugin}' verifier from the load path." \
|
|
51
|
-
" Please ensure that your transport is installed as a gem or" \
|
|
52
|
-
" included in your Gemfile if using Bundler."
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
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 "thor/util"
|
|
20
|
+
|
|
21
|
+
require "kitchen/errors"
|
|
22
|
+
|
|
23
|
+
module Kitchen
|
|
24
|
+
|
|
25
|
+
# A verifier is responsible for running tests post-converge to confirm that
|
|
26
|
+
# the instance is in a known/consistent state.
|
|
27
|
+
#
|
|
28
|
+
# @author Fletcher Nichol <fnichol@nichol.ca>
|
|
29
|
+
module Verifier
|
|
30
|
+
|
|
31
|
+
# Default verifier to use
|
|
32
|
+
DEFAULT_PLUGIN = "busser".freeze
|
|
33
|
+
|
|
34
|
+
# Returns an instance of a verifier given a plugin type string.
|
|
35
|
+
#
|
|
36
|
+
# @param plugin [String] a verifier plugin type, to be constantized
|
|
37
|
+
# @param config [Hash] a configuration hash to initialize the verifier
|
|
38
|
+
# @return [Verifier::Base] a verifier instance
|
|
39
|
+
# @raise [ClientError] if a verifier instance could not be created
|
|
40
|
+
def self.for_plugin(plugin, config)
|
|
41
|
+
first_load = require("kitchen/verifier/#{plugin}")
|
|
42
|
+
|
|
43
|
+
str_const = Thor::Util.camel_case(plugin)
|
|
44
|
+
klass = const_get(str_const)
|
|
45
|
+
object = klass.new(config)
|
|
46
|
+
object.verify_dependencies if first_load
|
|
47
|
+
object
|
|
48
|
+
rescue LoadError, NameError
|
|
49
|
+
raise ClientError,
|
|
50
|
+
"Could not load the '#{plugin}' verifier from the load path." \
|
|
51
|
+
" Please ensure that your transport is installed as a gem or" \
|
|
52
|
+
" included in your Gemfile if using Bundler."
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -1,235 +1,235 @@
|
|
|
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 "kitchen/errors"
|
|
20
|
-
require "kitchen/configurable"
|
|
21
|
-
require "kitchen/logging"
|
|
22
|
-
|
|
23
|
-
module Kitchen
|
|
24
|
-
|
|
25
|
-
module Verifier
|
|
26
|
-
|
|
27
|
-
# Base class for a verifier.
|
|
28
|
-
#
|
|
29
|
-
# @author Fletcher Nichol <fnichol@nichol.ca>
|
|
30
|
-
class Base
|
|
31
|
-
|
|
32
|
-
include Configurable
|
|
33
|
-
include Logging
|
|
34
|
-
|
|
35
|
-
default_config :http_proxy, nil
|
|
36
|
-
default_config :https_proxy, nil
|
|
37
|
-
default_config :ftp_proxy, nil
|
|
38
|
-
|
|
39
|
-
default_config :root_path do |verifier|
|
|
40
|
-
verifier.windows_os? ? "$env:TEMP\\verifier" : "/tmp/verifier"
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
default_config :sudo do |verifier|
|
|
44
|
-
verifier.windows_os? ? nil : true
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
default_config :chef_omnibus_root, "/opt/chef"
|
|
48
|
-
|
|
49
|
-
default_config :sudo_command do |verifier|
|
|
50
|
-
verifier.windows_os? ? nil : "sudo -E"
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
default_config :command_prefix, nil
|
|
54
|
-
|
|
55
|
-
default_config(:suite_name) { |busser| busser.instance.suite.name }
|
|
56
|
-
|
|
57
|
-
# Creates a new Verifier object using the provided configuration data
|
|
58
|
-
# which will be merged with any default configuration.
|
|
59
|
-
#
|
|
60
|
-
# @param config [Hash] provided verifier configuration
|
|
61
|
-
def initialize(config = {})
|
|
62
|
-
init_config(config)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# Runs the verifier on the instance.
|
|
66
|
-
#
|
|
67
|
-
# @param state [Hash] mutable instance state
|
|
68
|
-
# @raise [ActionFailed] if the action could not be completed
|
|
69
|
-
def call(state)
|
|
70
|
-
create_sandbox
|
|
71
|
-
sandbox_dirs = Dir.glob(File.join(sandbox_path, "*"))
|
|
72
|
-
|
|
73
|
-
instance.transport.connection(state) do |conn|
|
|
74
|
-
conn.execute(install_command)
|
|
75
|
-
conn.execute(init_command)
|
|
76
|
-
info("Transferring files to #{instance.to_str}")
|
|
77
|
-
conn.upload(sandbox_dirs, config[:root_path])
|
|
78
|
-
debug("Transfer complete")
|
|
79
|
-
conn.execute(prepare_command)
|
|
80
|
-
conn.execute(run_command)
|
|
81
|
-
end
|
|
82
|
-
rescue Kitchen::Transport::TransportFailed => ex
|
|
83
|
-
raise ActionFailed, ex.message
|
|
84
|
-
ensure
|
|
85
|
-
cleanup_sandbox
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
# Deletes the sandbox path. Without calling this method, the sandbox path
|
|
89
|
-
# will persist after the process terminates. In other words, cleanup is
|
|
90
|
-
# explicit. This method is safe to call multiple times.
|
|
91
|
-
def cleanup_sandbox
|
|
92
|
-
return if sandbox_path.nil?
|
|
93
|
-
|
|
94
|
-
debug("Cleaning up local sandbox in #{sandbox_path}")
|
|
95
|
-
FileUtils.rmtree(sandbox_path)
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
# Creates a temporary directory on the local workstation into which
|
|
99
|
-
# verifier related files and directories can be copied or created. The
|
|
100
|
-
# contents of this directory will be copied over to the instance before
|
|
101
|
-
# invoking the verifier's run command. After this method completes, it
|
|
102
|
-
# is expected that the contents of the sandbox is complete and ready for
|
|
103
|
-
# copy to the remote instance.
|
|
104
|
-
#
|
|
105
|
-
# **Note:** any subclasses would be well advised to call super first when
|
|
106
|
-
# overriding this method, for example:
|
|
107
|
-
#
|
|
108
|
-
# @example overriding `#create_sandbox`
|
|
109
|
-
#
|
|
110
|
-
# class MyVerifier < Kitchen::Verifier::Base
|
|
111
|
-
# def create_sandbox
|
|
112
|
-
# super
|
|
113
|
-
# # any further file copies, preparations, etc.
|
|
114
|
-
# end
|
|
115
|
-
# end
|
|
116
|
-
def create_sandbox
|
|
117
|
-
@sandbox_path = Dir.mktmpdir("#{instance.name}-sandbox-")
|
|
118
|
-
File.chmod(0755, sandbox_path)
|
|
119
|
-
info("Preparing files for transfer")
|
|
120
|
-
debug("Creating local sandbox in #{sandbox_path}")
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
# Generates a command string which will install and configure the
|
|
124
|
-
# verifier software on an instance. If no work is required, then `nil`
|
|
125
|
-
# will be returned.
|
|
126
|
-
#
|
|
127
|
-
# @return [String] a command string
|
|
128
|
-
def install_command
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
# Generates a command string which will perform any data initialization
|
|
132
|
-
# or configuration required after the verifier software is installed
|
|
133
|
-
# but before the sandbox has been transferred to the instance. If no work
|
|
134
|
-
# is required, then `nil` will be returned.
|
|
135
|
-
#
|
|
136
|
-
# @return [String] a command string
|
|
137
|
-
def init_command
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
# Generates a command string which will perform any commands or
|
|
141
|
-
# configuration required just before the main verifier run command but
|
|
142
|
-
# after the sandbox has been transferred to the instance. If no work is
|
|
143
|
-
# required, then `nil` will be returned.
|
|
144
|
-
#
|
|
145
|
-
# @return [String] a command string
|
|
146
|
-
def prepare_command
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
# Generates a command string which will invoke the main verifier
|
|
150
|
-
# command on the prepared instance. If no work is required, then `nil`
|
|
151
|
-
# will be returned.
|
|
152
|
-
#
|
|
153
|
-
# @return [String] a command string
|
|
154
|
-
def run_command
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
# Returns the absolute path to the sandbox directory or raises an
|
|
158
|
-
# exception if `#create_sandbox` has not yet been called.
|
|
159
|
-
#
|
|
160
|
-
# @return [String] the absolute path to the sandbox directory
|
|
161
|
-
# @raise [ClientError] if the sandbox directory has no yet been created
|
|
162
|
-
# by calling `#create_sandbox`
|
|
163
|
-
def sandbox_path
|
|
164
|
-
@sandbox_path || (raise ClientError, "Sandbox directory has not yet " \
|
|
165
|
-
"been created. Please run #{self.class}#create_sandox before " \
|
|
166
|
-
"trying to access the path.")
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
# Sets the API version for this verifier. If the verifier does not set
|
|
170
|
-
# this value, then `nil` will be used and reported.
|
|
171
|
-
#
|
|
172
|
-
# Sets the API version for this verifier
|
|
173
|
-
#
|
|
174
|
-
# @example setting an API version
|
|
175
|
-
#
|
|
176
|
-
# module Kitchen
|
|
177
|
-
# module Verifier
|
|
178
|
-
# class NewVerifier < Kitchen::Verifier::Base
|
|
179
|
-
#
|
|
180
|
-
# kitchen_verifier_api_version 2
|
|
181
|
-
#
|
|
182
|
-
# end
|
|
183
|
-
# end
|
|
184
|
-
# end
|
|
185
|
-
#
|
|
186
|
-
# @param version [Integer,String] a version number
|
|
187
|
-
#
|
|
188
|
-
def self.kitchen_verifier_api_version(version)
|
|
189
|
-
@api_version = version
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
private
|
|
193
|
-
|
|
194
|
-
# Builds a complete command given a variables String preamble and a file
|
|
195
|
-
# containing shell code.
|
|
196
|
-
#
|
|
197
|
-
# @param vars [String] shell variables, as a String
|
|
198
|
-
# @param file [String] file basename (without extension) containing
|
|
199
|
-
# shell code
|
|
200
|
-
# @return [String] command
|
|
201
|
-
# @api private
|
|
202
|
-
def shell_code_from_file(vars, file)
|
|
203
|
-
src_file = File.join(
|
|
204
|
-
File.dirname(__FILE__),
|
|
205
|
-
%w[.. .. .. support],
|
|
206
|
-
file + (powershell_shell? ? ".ps1" : ".sh")
|
|
207
|
-
)
|
|
208
|
-
|
|
209
|
-
wrap_shell_code([vars, "", IO.read(src_file)].join("\n"))
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
# Conditionally prefixes a command with a sudo command.
|
|
213
|
-
#
|
|
214
|
-
# @param command [String] command to be prefixed
|
|
215
|
-
# @return [String] the command, conditionaly prefixed with sudo
|
|
216
|
-
# @api private
|
|
217
|
-
def sudo(script)
|
|
218
|
-
config[:sudo] ? "#{config[:sudo_command]} #{script}" : script
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
# Conditionally prefixes a command with a command prefix.
|
|
222
|
-
# This should generally be done after a command has been
|
|
223
|
-
# conditionally prefixed by #sudo as certain platforms, such as
|
|
224
|
-
# Cisco Nexus, require all commands to be run with a prefix to
|
|
225
|
-
# obtain outbound network access.
|
|
226
|
-
#
|
|
227
|
-
# @param command [String] command to be prefixed
|
|
228
|
-
# @return [String] the command, conditionally prefixed with the configured prefix
|
|
229
|
-
# @api private
|
|
230
|
-
def prefix_command(script)
|
|
231
|
-
config[:command_prefix] ? "#{config[:command_prefix]} #{script}" : script
|
|
232
|
-
end
|
|
233
|
-
end
|
|
234
|
-
end
|
|
235
|
-
end
|
|
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 "kitchen/errors"
|
|
20
|
+
require "kitchen/configurable"
|
|
21
|
+
require "kitchen/logging"
|
|
22
|
+
|
|
23
|
+
module Kitchen
|
|
24
|
+
|
|
25
|
+
module Verifier
|
|
26
|
+
|
|
27
|
+
# Base class for a verifier.
|
|
28
|
+
#
|
|
29
|
+
# @author Fletcher Nichol <fnichol@nichol.ca>
|
|
30
|
+
class Base
|
|
31
|
+
|
|
32
|
+
include Configurable
|
|
33
|
+
include Logging
|
|
34
|
+
|
|
35
|
+
default_config :http_proxy, nil
|
|
36
|
+
default_config :https_proxy, nil
|
|
37
|
+
default_config :ftp_proxy, nil
|
|
38
|
+
|
|
39
|
+
default_config :root_path do |verifier|
|
|
40
|
+
verifier.windows_os? ? "$env:TEMP\\verifier" : "/tmp/verifier"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
default_config :sudo do |verifier|
|
|
44
|
+
verifier.windows_os? ? nil : true
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
default_config :chef_omnibus_root, "/opt/chef"
|
|
48
|
+
|
|
49
|
+
default_config :sudo_command do |verifier|
|
|
50
|
+
verifier.windows_os? ? nil : "sudo -E"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
default_config :command_prefix, nil
|
|
54
|
+
|
|
55
|
+
default_config(:suite_name) { |busser| busser.instance.suite.name }
|
|
56
|
+
|
|
57
|
+
# Creates a new Verifier object using the provided configuration data
|
|
58
|
+
# which will be merged with any default configuration.
|
|
59
|
+
#
|
|
60
|
+
# @param config [Hash] provided verifier configuration
|
|
61
|
+
def initialize(config = {})
|
|
62
|
+
init_config(config)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Runs the verifier on the instance.
|
|
66
|
+
#
|
|
67
|
+
# @param state [Hash] mutable instance state
|
|
68
|
+
# @raise [ActionFailed] if the action could not be completed
|
|
69
|
+
def call(state)
|
|
70
|
+
create_sandbox
|
|
71
|
+
sandbox_dirs = Dir.glob(File.join(sandbox_path, "*"))
|
|
72
|
+
|
|
73
|
+
instance.transport.connection(state) do |conn|
|
|
74
|
+
conn.execute(install_command)
|
|
75
|
+
conn.execute(init_command)
|
|
76
|
+
info("Transferring files to #{instance.to_str}")
|
|
77
|
+
conn.upload(sandbox_dirs, config[:root_path])
|
|
78
|
+
debug("Transfer complete")
|
|
79
|
+
conn.execute(prepare_command)
|
|
80
|
+
conn.execute(run_command)
|
|
81
|
+
end
|
|
82
|
+
rescue Kitchen::Transport::TransportFailed => ex
|
|
83
|
+
raise ActionFailed, ex.message
|
|
84
|
+
ensure
|
|
85
|
+
cleanup_sandbox
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Deletes the sandbox path. Without calling this method, the sandbox path
|
|
89
|
+
# will persist after the process terminates. In other words, cleanup is
|
|
90
|
+
# explicit. This method is safe to call multiple times.
|
|
91
|
+
def cleanup_sandbox
|
|
92
|
+
return if sandbox_path.nil?
|
|
93
|
+
|
|
94
|
+
debug("Cleaning up local sandbox in #{sandbox_path}")
|
|
95
|
+
FileUtils.rmtree(sandbox_path)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Creates a temporary directory on the local workstation into which
|
|
99
|
+
# verifier related files and directories can be copied or created. The
|
|
100
|
+
# contents of this directory will be copied over to the instance before
|
|
101
|
+
# invoking the verifier's run command. After this method completes, it
|
|
102
|
+
# is expected that the contents of the sandbox is complete and ready for
|
|
103
|
+
# copy to the remote instance.
|
|
104
|
+
#
|
|
105
|
+
# **Note:** any subclasses would be well advised to call super first when
|
|
106
|
+
# overriding this method, for example:
|
|
107
|
+
#
|
|
108
|
+
# @example overriding `#create_sandbox`
|
|
109
|
+
#
|
|
110
|
+
# class MyVerifier < Kitchen::Verifier::Base
|
|
111
|
+
# def create_sandbox
|
|
112
|
+
# super
|
|
113
|
+
# # any further file copies, preparations, etc.
|
|
114
|
+
# end
|
|
115
|
+
# end
|
|
116
|
+
def create_sandbox
|
|
117
|
+
@sandbox_path = Dir.mktmpdir("#{instance.name}-sandbox-")
|
|
118
|
+
File.chmod(0755, sandbox_path)
|
|
119
|
+
info("Preparing files for transfer")
|
|
120
|
+
debug("Creating local sandbox in #{sandbox_path}")
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Generates a command string which will install and configure the
|
|
124
|
+
# verifier software on an instance. If no work is required, then `nil`
|
|
125
|
+
# will be returned.
|
|
126
|
+
#
|
|
127
|
+
# @return [String] a command string
|
|
128
|
+
def install_command
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Generates a command string which will perform any data initialization
|
|
132
|
+
# or configuration required after the verifier software is installed
|
|
133
|
+
# but before the sandbox has been transferred to the instance. If no work
|
|
134
|
+
# is required, then `nil` will be returned.
|
|
135
|
+
#
|
|
136
|
+
# @return [String] a command string
|
|
137
|
+
def init_command
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Generates a command string which will perform any commands or
|
|
141
|
+
# configuration required just before the main verifier run command but
|
|
142
|
+
# after the sandbox has been transferred to the instance. If no work is
|
|
143
|
+
# required, then `nil` will be returned.
|
|
144
|
+
#
|
|
145
|
+
# @return [String] a command string
|
|
146
|
+
def prepare_command
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Generates a command string which will invoke the main verifier
|
|
150
|
+
# command on the prepared instance. If no work is required, then `nil`
|
|
151
|
+
# will be returned.
|
|
152
|
+
#
|
|
153
|
+
# @return [String] a command string
|
|
154
|
+
def run_command
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Returns the absolute path to the sandbox directory or raises an
|
|
158
|
+
# exception if `#create_sandbox` has not yet been called.
|
|
159
|
+
#
|
|
160
|
+
# @return [String] the absolute path to the sandbox directory
|
|
161
|
+
# @raise [ClientError] if the sandbox directory has no yet been created
|
|
162
|
+
# by calling `#create_sandbox`
|
|
163
|
+
def sandbox_path
|
|
164
|
+
@sandbox_path || (raise ClientError, "Sandbox directory has not yet " \
|
|
165
|
+
"been created. Please run #{self.class}#create_sandox before " \
|
|
166
|
+
"trying to access the path.")
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Sets the API version for this verifier. If the verifier does not set
|
|
170
|
+
# this value, then `nil` will be used and reported.
|
|
171
|
+
#
|
|
172
|
+
# Sets the API version for this verifier
|
|
173
|
+
#
|
|
174
|
+
# @example setting an API version
|
|
175
|
+
#
|
|
176
|
+
# module Kitchen
|
|
177
|
+
# module Verifier
|
|
178
|
+
# class NewVerifier < Kitchen::Verifier::Base
|
|
179
|
+
#
|
|
180
|
+
# kitchen_verifier_api_version 2
|
|
181
|
+
#
|
|
182
|
+
# end
|
|
183
|
+
# end
|
|
184
|
+
# end
|
|
185
|
+
#
|
|
186
|
+
# @param version [Integer,String] a version number
|
|
187
|
+
#
|
|
188
|
+
def self.kitchen_verifier_api_version(version)
|
|
189
|
+
@api_version = version
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
private
|
|
193
|
+
|
|
194
|
+
# Builds a complete command given a variables String preamble and a file
|
|
195
|
+
# containing shell code.
|
|
196
|
+
#
|
|
197
|
+
# @param vars [String] shell variables, as a String
|
|
198
|
+
# @param file [String] file basename (without extension) containing
|
|
199
|
+
# shell code
|
|
200
|
+
# @return [String] command
|
|
201
|
+
# @api private
|
|
202
|
+
def shell_code_from_file(vars, file)
|
|
203
|
+
src_file = File.join(
|
|
204
|
+
File.dirname(__FILE__),
|
|
205
|
+
%w[.. .. .. support],
|
|
206
|
+
file + (powershell_shell? ? ".ps1" : ".sh")
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
wrap_shell_code([vars, "", IO.read(src_file)].join("\n"))
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# Conditionally prefixes a command with a sudo command.
|
|
213
|
+
#
|
|
214
|
+
# @param command [String] command to be prefixed
|
|
215
|
+
# @return [String] the command, conditionaly prefixed with sudo
|
|
216
|
+
# @api private
|
|
217
|
+
def sudo(script)
|
|
218
|
+
config[:sudo] ? "#{config[:sudo_command]} #{script}" : script
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# Conditionally prefixes a command with a command prefix.
|
|
222
|
+
# This should generally be done after a command has been
|
|
223
|
+
# conditionally prefixed by #sudo as certain platforms, such as
|
|
224
|
+
# Cisco Nexus, require all commands to be run with a prefix to
|
|
225
|
+
# obtain outbound network access.
|
|
226
|
+
#
|
|
227
|
+
# @param command [String] command to be prefixed
|
|
228
|
+
# @return [String] the command, conditionally prefixed with the configured prefix
|
|
229
|
+
# @api private
|
|
230
|
+
def prefix_command(script)
|
|
231
|
+
config[:command_prefix] ? "#{config[:command_prefix]} #{script}" : script
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
end
|