test-kitchen 1.6.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. checksums.yaml +4 -4
  2. data/.cane +8 -7
  3. data/.github/ISSUE_TEMPLATE.md +56 -0
  4. data/.gitignore +28 -27
  5. data/.kitchen.ci.yml +23 -0
  6. data/.kitchen.proxy.yml +27 -0
  7. data/.rubocop.yml +3 -3
  8. data/.travis.yml +70 -53
  9. data/.yardopts +3 -3
  10. data/Berksfile +3 -0
  11. data/CHANGELOG.md +1083 -1051
  12. data/CONTRIBUTING.md +14 -14
  13. data/Gemfile +19 -14
  14. data/Gemfile.proxy_tests +4 -5
  15. data/Guardfile +42 -42
  16. data/LICENSE +15 -15
  17. data/MAINTAINERS.md +23 -24
  18. data/README.md +135 -135
  19. data/Rakefile +61 -76
  20. data/appveyor.yml +44 -34
  21. data/features/kitchen_action_commands.feature +164 -164
  22. data/features/kitchen_command.feature +16 -16
  23. data/features/kitchen_console_command.feature +34 -34
  24. data/features/kitchen_defaults.feature +38 -38
  25. data/features/kitchen_diagnose_command.feature +96 -96
  26. data/features/kitchen_driver_create_command.feature +64 -64
  27. data/features/kitchen_driver_discover_command.feature +25 -25
  28. data/features/kitchen_help_command.feature +16 -16
  29. data/features/kitchen_init_command.feature +274 -274
  30. data/features/kitchen_list_command.feature +104 -104
  31. data/features/kitchen_login_command.feature +62 -62
  32. data/features/kitchen_sink_command.feature +30 -30
  33. data/features/kitchen_test_command.feature +88 -88
  34. data/features/step_definitions/gem_steps.rb +36 -36
  35. data/features/step_definitions/git_steps.rb +5 -5
  36. data/features/step_definitions/output_steps.rb +5 -5
  37. data/features/support/env.rb +75 -75
  38. data/lib/kitchen.rb +150 -150
  39. data/lib/kitchen/base64_stream.rb +55 -55
  40. data/lib/kitchen/cli.rb +419 -419
  41. data/lib/kitchen/collection.rb +55 -55
  42. data/lib/kitchen/color.rb +65 -65
  43. data/lib/kitchen/command.rb +185 -185
  44. data/lib/kitchen/command/action.rb +45 -45
  45. data/lib/kitchen/command/console.rb +58 -58
  46. data/lib/kitchen/command/diagnose.rb +92 -92
  47. data/lib/kitchen/command/driver_discover.rb +105 -105
  48. data/lib/kitchen/command/exec.rb +41 -41
  49. data/lib/kitchen/command/list.rb +119 -119
  50. data/lib/kitchen/command/login.rb +43 -43
  51. data/lib/kitchen/command/sink.rb +54 -54
  52. data/lib/kitchen/command/test.rb +51 -51
  53. data/lib/kitchen/config.rb +322 -322
  54. data/lib/kitchen/configurable.rb +529 -529
  55. data/lib/kitchen/data_munger.rb +959 -960
  56. data/lib/kitchen/diagnostic.rb +141 -141
  57. data/lib/kitchen/driver.rb +56 -56
  58. data/lib/kitchen/driver/base.rb +134 -134
  59. data/lib/kitchen/driver/dummy.rb +108 -108
  60. data/lib/kitchen/driver/proxy.rb +72 -72
  61. data/lib/kitchen/driver/ssh_base.rb +357 -357
  62. data/lib/kitchen/errors.rb +229 -229
  63. data/lib/kitchen/generator/driver_create.rb +177 -177
  64. data/lib/kitchen/generator/init.rb +296 -296
  65. data/lib/kitchen/instance.rb +662 -662
  66. data/lib/kitchen/lazy_hash.rb +142 -142
  67. data/lib/kitchen/loader/yaml.rb +349 -349
  68. data/lib/kitchen/logger.rb +423 -423
  69. data/lib/kitchen/logging.rb +56 -56
  70. data/lib/kitchen/login_command.rb +52 -52
  71. data/lib/kitchen/metadata_chopper.rb +52 -52
  72. data/lib/kitchen/platform.rb +67 -67
  73. data/lib/kitchen/provisioner.rb +54 -54
  74. data/lib/kitchen/provisioner/base.rb +236 -236
  75. data/lib/kitchen/provisioner/chef/berkshelf.rb +114 -114
  76. data/lib/kitchen/provisioner/chef/common_sandbox.rb +322 -322
  77. data/lib/kitchen/provisioner/chef/librarian.rb +112 -112
  78. data/lib/kitchen/provisioner/chef_apply.rb +124 -125
  79. data/lib/kitchen/provisioner/chef_base.rb +341 -294
  80. data/lib/kitchen/provisioner/chef_solo.rb +88 -89
  81. data/lib/kitchen/provisioner/chef_zero.rb +245 -245
  82. data/lib/kitchen/provisioner/dummy.rb +79 -79
  83. data/lib/kitchen/provisioner/shell.rb +138 -138
  84. data/lib/kitchen/rake_tasks.rb +63 -63
  85. data/lib/kitchen/shell_out.rb +93 -93
  86. data/lib/kitchen/ssh.rb +276 -276
  87. data/lib/kitchen/state_file.rb +120 -120
  88. data/lib/kitchen/suite.rb +51 -51
  89. data/lib/kitchen/thor_tasks.rb +66 -66
  90. data/lib/kitchen/transport.rb +54 -54
  91. data/lib/kitchen/transport/base.rb +176 -176
  92. data/lib/kitchen/transport/dummy.rb +79 -79
  93. data/lib/kitchen/transport/ssh.rb +364 -364
  94. data/lib/kitchen/transport/winrm.rb +486 -486
  95. data/lib/kitchen/util.rb +147 -147
  96. data/lib/kitchen/verifier.rb +55 -55
  97. data/lib/kitchen/verifier/base.rb +235 -235
  98. data/lib/kitchen/verifier/busser.rb +277 -277
  99. data/lib/kitchen/verifier/dummy.rb +79 -79
  100. data/lib/kitchen/verifier/shell.rb +101 -101
  101. data/lib/kitchen/version.rb +21 -21
  102. data/lib/vendor/hash_recursive_merge.rb +82 -82
  103. data/spec/kitchen/base64_stream_spec.rb +77 -77
  104. data/spec/kitchen/cli_spec.rb +56 -56
  105. data/spec/kitchen/collection_spec.rb +80 -80
  106. data/spec/kitchen/color_spec.rb +54 -54
  107. data/spec/kitchen/config_spec.rb +408 -408
  108. data/spec/kitchen/configurable_spec.rb +1095 -1062
  109. data/spec/kitchen/data_munger_spec.rb +2694 -2383
  110. data/spec/kitchen/diagnostic_spec.rb +129 -129
  111. data/spec/kitchen/driver/base_spec.rb +121 -121
  112. data/spec/kitchen/driver/dummy_spec.rb +199 -199
  113. data/spec/kitchen/driver/proxy_spec.rb +138 -138
  114. data/spec/kitchen/driver/ssh_base_spec.rb +1115 -1115
  115. data/spec/kitchen/driver_spec.rb +112 -112
  116. data/spec/kitchen/errors_spec.rb +309 -309
  117. data/spec/kitchen/instance_spec.rb +1419 -1419
  118. data/spec/kitchen/lazy_hash_spec.rb +117 -117
  119. data/spec/kitchen/loader/yaml_spec.rb +774 -774
  120. data/spec/kitchen/logger_spec.rb +429 -429
  121. data/spec/kitchen/logging_spec.rb +59 -59
  122. data/spec/kitchen/login_command_spec.rb +68 -68
  123. data/spec/kitchen/metadata_chopper_spec.rb +82 -82
  124. data/spec/kitchen/platform_spec.rb +89 -89
  125. data/spec/kitchen/provisioner/base_spec.rb +386 -386
  126. data/spec/kitchen/provisioner/chef_apply_spec.rb +136 -136
  127. data/spec/kitchen/provisioner/chef_base_spec.rb +1161 -1067
  128. data/spec/kitchen/provisioner/chef_solo_spec.rb +557 -557
  129. data/spec/kitchen/provisioner/chef_zero_spec.rb +1001 -1001
  130. data/spec/kitchen/provisioner/dummy_spec.rb +99 -99
  131. data/spec/kitchen/provisioner/shell_spec.rb +566 -566
  132. data/spec/kitchen/provisioner_spec.rb +107 -107
  133. data/spec/kitchen/shell_out_spec.rb +150 -150
  134. data/spec/kitchen/ssh_spec.rb +693 -693
  135. data/spec/kitchen/state_file_spec.rb +129 -129
  136. data/spec/kitchen/suite_spec.rb +62 -62
  137. data/spec/kitchen/transport/base_spec.rb +89 -89
  138. data/spec/kitchen/transport/ssh_spec.rb +1255 -1255
  139. data/spec/kitchen/transport/winrm_spec.rb +1143 -1143
  140. data/spec/kitchen/transport_spec.rb +112 -112
  141. data/spec/kitchen/util_spec.rb +165 -165
  142. data/spec/kitchen/verifier/base_spec.rb +362 -362
  143. data/spec/kitchen/verifier/busser_spec.rb +610 -610
  144. data/spec/kitchen/verifier/dummy_spec.rb +99 -99
  145. data/spec/kitchen/verifier/shell_spec.rb +160 -158
  146. data/spec/kitchen/verifier_spec.rb +120 -120
  147. data/spec/kitchen_spec.rb +114 -114
  148. data/spec/spec_helper.rb +85 -85
  149. data/spec/support/powershell_max_size_spec.rb +40 -40
  150. data/support/busser_install_command.ps1 +14 -14
  151. data/support/busser_install_command.sh +14 -14
  152. data/support/chef-client-zero.rb +77 -77
  153. data/support/chef_base_init_command.ps1 +18 -18
  154. data/support/chef_base_init_command.sh +2 -2
  155. data/support/chef_base_install_command.ps1 +85 -85
  156. data/support/chef_base_install_command.sh +229 -229
  157. data/support/chef_zero_prepare_command_legacy.ps1 +9 -9
  158. data/support/chef_zero_prepare_command_legacy.sh +10 -10
  159. data/support/download_helpers.sh +109 -109
  160. data/support/dummy-validation.pem +27 -27
  161. data/templates/driver/CHANGELOG.md.erb +3 -3
  162. data/templates/driver/Gemfile.erb +3 -3
  163. data/templates/driver/README.md.erb +64 -64
  164. data/templates/driver/Rakefile.erb +21 -21
  165. data/templates/driver/driver.rb.erb +23 -23
  166. data/templates/driver/gemspec.erb +29 -29
  167. data/templates/driver/gitignore.erb +17 -17
  168. data/templates/driver/license_apachev2.erb +15 -15
  169. data/templates/driver/license_lgplv3.erb +16 -16
  170. data/templates/driver/license_mit.erb +22 -22
  171. data/templates/driver/license_reserved.erb +5 -5
  172. data/templates/driver/tailor.erb +4 -4
  173. data/templates/driver/travis.yml.erb +11 -11
  174. data/templates/driver/version.rb.erb +12 -12
  175. data/templates/init/chefignore.erb +1 -1
  176. data/templates/init/kitchen.yml.erb +18 -18
  177. data/test-kitchen.gemspec +62 -62
  178. data/test/integration/default/default_spec.rb +3 -0
  179. data/testing_windows.md +37 -37
  180. metadata +23 -11
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
@@ -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