test-kitchen 1.2.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.cane +1 -1
- data/.rubocop.yml +3 -0
- data/.travis.yml +20 -9
- data/CHANGELOG.md +219 -108
- data/Gemfile +10 -6
- data/Guardfile +38 -9
- data/README.md +11 -1
- data/Rakefile +21 -37
- data/bin/kitchen +4 -4
- data/features/kitchen_action_commands.feature +161 -0
- data/features/kitchen_console_command.feature +34 -0
- data/features/kitchen_diagnose_command.feature +64 -0
- data/features/kitchen_init_command.feature +29 -17
- data/features/kitchen_list_command.feature +2 -2
- data/features/kitchen_login_command.feature +56 -0
- data/features/{sink_command.feature → kitchen_sink_command.feature} +0 -0
- data/features/kitchen_test_command.feature +88 -0
- data/features/step_definitions/gem_steps.rb +8 -6
- data/features/step_definitions/git_steps.rb +4 -2
- data/features/step_definitions/output_steps.rb +5 -0
- data/features/support/env.rb +12 -9
- data/lib/kitchen.rb +60 -38
- data/lib/kitchen/base64_stream.rb +55 -0
- data/lib/kitchen/busser.rb +124 -58
- data/lib/kitchen/cli.rb +121 -38
- data/lib/kitchen/collection.rb +3 -3
- data/lib/kitchen/color.rb +4 -4
- data/lib/kitchen/command.rb +78 -11
- data/lib/kitchen/command/action.rb +3 -2
- data/lib/kitchen/command/console.rb +12 -5
- data/lib/kitchen/command/diagnose.rb +17 -3
- data/lib/kitchen/command/driver_discover.rb +26 -7
- data/lib/kitchen/command/exec.rb +41 -0
- data/lib/kitchen/command/list.rb +44 -14
- data/lib/kitchen/command/login.rb +2 -1
- data/lib/kitchen/command/sink.rb +2 -1
- data/lib/kitchen/command/test.rb +5 -4
- data/lib/kitchen/config.rb +146 -14
- data/lib/kitchen/configurable.rb +314 -0
- data/lib/kitchen/data_munger.rb +522 -18
- data/lib/kitchen/diagnostic.rb +43 -4
- data/lib/kitchen/driver.rb +4 -4
- data/lib/kitchen/driver/base.rb +80 -115
- data/lib/kitchen/driver/dummy.rb +34 -6
- data/lib/kitchen/driver/proxy.rb +14 -3
- data/lib/kitchen/driver/ssh_base.rb +61 -7
- data/lib/kitchen/errors.rb +109 -9
- data/lib/kitchen/generator/driver_create.rb +39 -5
- data/lib/kitchen/generator/init.rb +130 -45
- data/lib/kitchen/instance.rb +162 -28
- data/lib/kitchen/lazy_hash.rb +79 -7
- data/lib/kitchen/loader/yaml.rb +159 -27
- data/lib/kitchen/logger.rb +267 -21
- data/lib/kitchen/logging.rb +30 -3
- data/lib/kitchen/login_command.rb +11 -2
- data/lib/kitchen/metadata_chopper.rb +2 -2
- data/lib/kitchen/provisioner.rb +4 -4
- data/lib/kitchen/provisioner/base.rb +107 -103
- data/lib/kitchen/provisioner/chef/berkshelf.rb +36 -8
- data/lib/kitchen/provisioner/chef/librarian.rb +40 -11
- data/lib/kitchen/provisioner/chef_base.rb +206 -167
- data/lib/kitchen/provisioner/chef_solo.rb +25 -7
- data/lib/kitchen/provisioner/chef_zero.rb +105 -29
- data/lib/kitchen/provisioner/dummy.rb +1 -1
- data/lib/kitchen/provisioner/shell.rb +21 -6
- data/lib/kitchen/rake_tasks.rb +8 -3
- data/lib/kitchen/shell_out.rb +15 -18
- data/lib/kitchen/ssh.rb +122 -27
- data/lib/kitchen/state_file.rb +24 -7
- data/lib/kitchen/thor_tasks.rb +9 -4
- data/lib/kitchen/util.rb +43 -118
- data/lib/kitchen/version.rb +1 -1
- data/lib/vendor/hash_recursive_merge.rb +10 -2
- data/spec/kitchen/base64_stream_spec.rb +77 -0
- data/spec/kitchen/busser_spec.rb +490 -0
- data/spec/kitchen/collection_spec.rb +10 -10
- data/spec/kitchen/color_spec.rb +2 -2
- data/spec/kitchen/config_spec.rb +234 -62
- data/spec/kitchen/configurable_spec.rb +490 -0
- data/spec/kitchen/data_munger_spec.rb +1070 -862
- data/spec/kitchen/diagnostic_spec.rb +79 -0
- data/spec/kitchen/driver/base_spec.rb +80 -85
- data/spec/kitchen/driver/dummy_spec.rb +43 -14
- data/spec/kitchen/driver/proxy_spec.rb +134 -0
- data/spec/kitchen/driver/ssh_base_spec.rb +644 -0
- data/spec/kitchen/driver_spec.rb +15 -15
- data/spec/kitchen/errors_spec.rb +309 -0
- data/spec/kitchen/instance_spec.rb +143 -46
- data/spec/kitchen/lazy_hash_spec.rb +36 -9
- data/spec/kitchen/loader/yaml_spec.rb +237 -226
- data/spec/kitchen/logger_spec.rb +419 -0
- data/spec/kitchen/logging_spec.rb +59 -0
- data/spec/kitchen/login_command_spec.rb +49 -0
- data/spec/kitchen/metadata_chopper_spec.rb +82 -0
- data/spec/kitchen/platform_spec.rb +4 -4
- data/spec/kitchen/provisioner/base_spec.rb +65 -125
- data/spec/kitchen/provisioner/chef_base_spec.rb +798 -0
- data/spec/kitchen/provisioner/chef_solo_spec.rb +316 -0
- data/spec/kitchen/provisioner/chef_zero_spec.rb +624 -0
- data/spec/kitchen/provisioner/shell_spec.rb +269 -0
- data/spec/kitchen/provisioner_spec.rb +6 -6
- data/spec/kitchen/shell_out_spec.rb +143 -0
- data/spec/kitchen/ssh_spec.rb +683 -0
- data/spec/kitchen/state_file_spec.rb +28 -21
- data/spec/kitchen/suite_spec.rb +7 -7
- data/spec/kitchen/util_spec.rb +68 -10
- data/spec/kitchen_spec.rb +107 -0
- data/spec/spec_helper.rb +18 -13
- data/support/chef-client-zero.rb +10 -9
- data/support/chef_helpers.sh +16 -0
- data/support/download_helpers.sh +109 -0
- data/test-kitchen.gemspec +42 -33
- metadata +107 -33
data/lib/kitchen/diagnostic.rb
CHANGED
@@ -16,7 +16,8 @@
|
|
16
16
|
# See the License for the specific language governing permissions and
|
17
17
|
# limitations under the License.
|
18
18
|
|
19
|
-
require
|
19
|
+
require "kitchen/util"
|
20
|
+
require "kitchen/version"
|
20
21
|
|
21
22
|
module Kitchen
|
22
23
|
|
@@ -26,12 +27,23 @@ module Kitchen
|
|
26
27
|
# @author Fletcher Nichol <fnichol@nichol.ca>
|
27
28
|
class Diagnostic
|
28
29
|
|
30
|
+
# Constructs a new Diagnostic object with an optional loader and optional
|
31
|
+
# instances array.
|
32
|
+
#
|
33
|
+
# @param options [Hash] optional configuration
|
34
|
+
# @option options [#diagnose,Hash] :loader a loader instance that responds
|
35
|
+
# to `#diagnose` or an error Hash
|
36
|
+
# @option options [Array<#diagnose>,Hash] :instances an Array of instances
|
37
|
+
# that respond to `#diagnose` or an error Hash
|
29
38
|
def initialize(options = {})
|
30
39
|
@loader = options.fetch(:loader, nil)
|
31
40
|
@instances = options.fetch(:instances, [])
|
32
41
|
@result = Hash.new
|
33
42
|
end
|
34
43
|
|
44
|
+
# Returns a Hash with stringified keys containing diagnostic information.
|
45
|
+
#
|
46
|
+
# @return [Hash] a configuration Hash
|
35
47
|
def read
|
36
48
|
prepare_common
|
37
49
|
prepare_loader
|
@@ -42,13 +54,31 @@ module Kitchen
|
|
42
54
|
|
43
55
|
private
|
44
56
|
|
45
|
-
|
57
|
+
# @return [Hash] a result hash
|
58
|
+
# @api private
|
59
|
+
attr_reader :result
|
46
60
|
|
61
|
+
# @return [#diagnose,Hash] a loader instance that responds to `#diagnose`
|
62
|
+
# or an error Hash
|
63
|
+
# @api private
|
64
|
+
attr_reader :loader
|
65
|
+
|
66
|
+
# @return [Array<#diagnose>,Hash] an Array of instances that respond to
|
67
|
+
# `#diagnose` or an error Hash
|
68
|
+
# @api private
|
69
|
+
attr_reader :instances
|
70
|
+
|
71
|
+
# Adds common information to the result Hash.
|
72
|
+
#
|
73
|
+
# @api private
|
47
74
|
def prepare_common
|
48
|
-
result[:timestamp] = Time.now.gmtime
|
75
|
+
result[:timestamp] = Time.now.gmtime.to_s
|
49
76
|
result[:kitchen_version] = Kitchen::VERSION
|
50
77
|
end
|
51
78
|
|
79
|
+
# Adds loader information to the result Hash.
|
80
|
+
#
|
81
|
+
# @api private
|
52
82
|
def prepare_loader
|
53
83
|
if error_hash?(loader)
|
54
84
|
result[:loader] = loader
|
@@ -57,6 +87,9 @@ module Kitchen
|
|
57
87
|
end
|
58
88
|
end
|
59
89
|
|
90
|
+
# Adds instance information to the result Hash.
|
91
|
+
#
|
92
|
+
# @api private
|
60
93
|
def prepare_instances
|
61
94
|
result[:instances] = Hash.new
|
62
95
|
if error_hash?(instances)
|
@@ -66,8 +99,14 @@ module Kitchen
|
|
66
99
|
end
|
67
100
|
end
|
68
101
|
|
102
|
+
# Determins whether or not the object is an error hash. An error hash is
|
103
|
+
# defined as a Hash containing an `:error` key.
|
104
|
+
#
|
105
|
+
# @param obj [Object] an object
|
106
|
+
# @return [true,false] whether or not the object is an error hash
|
107
|
+
# @api private
|
69
108
|
def error_hash?(obj)
|
70
|
-
obj.is_a?(Hash) && obj.
|
109
|
+
obj.is_a?(Hash) && obj.key?(:error)
|
71
110
|
end
|
72
111
|
end
|
73
112
|
end
|
data/lib/kitchen/driver.rb
CHANGED
@@ -16,7 +16,7 @@
|
|
16
16
|
# See the License for the specific language governing permissions and
|
17
17
|
# limitations under the License.
|
18
18
|
|
19
|
-
require
|
19
|
+
require "thor/util"
|
20
20
|
|
21
21
|
module Kitchen
|
22
22
|
|
@@ -40,7 +40,7 @@ module Kitchen
|
|
40
40
|
first_load = require("kitchen/driver/#{plugin}")
|
41
41
|
|
42
42
|
str_const = Thor::Util.camel_case(plugin)
|
43
|
-
klass =
|
43
|
+
klass = const_get(str_const)
|
44
44
|
object = klass.new(config)
|
45
45
|
object.verify_dependencies if first_load
|
46
46
|
object
|
@@ -48,8 +48,8 @@ module Kitchen
|
|
48
48
|
raise
|
49
49
|
rescue LoadError, NameError
|
50
50
|
raise ClientError,
|
51
|
-
"Could not load the '#{plugin}' driver from the load path."
|
52
|
-
" Please ensure that your driver is installed as a gem or included"
|
51
|
+
"Could not load the '#{plugin}' driver from the load path." \
|
52
|
+
" Please ensure that your driver is installed as a gem or included" \
|
53
53
|
" in your Gemfile if using Bundler."
|
54
54
|
end
|
55
55
|
end
|
data/lib/kitchen/driver/base.rb
CHANGED
@@ -16,9 +16,9 @@
|
|
16
16
|
# See the License for the specific language governing permissions and
|
17
17
|
# limitations under the License.
|
18
18
|
|
19
|
-
require
|
19
|
+
require "thor/util"
|
20
20
|
|
21
|
-
require
|
21
|
+
require "kitchen/lazy_hash"
|
22
22
|
|
23
23
|
module Kitchen
|
24
24
|
|
@@ -30,78 +30,58 @@ module Kitchen
|
|
30
30
|
class Base
|
31
31
|
|
32
32
|
include ShellOut
|
33
|
+
include Configurable
|
33
34
|
include Logging
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
40
|
-
|
36
|
+
# Creates a new Driver object using the provided configuration data
|
37
|
+
# which will be merged with any default configuration.
|
38
|
+
#
|
39
|
+
# @param config [Hash] provided driver configuration
|
41
40
|
def initialize(config = {})
|
42
|
-
|
43
|
-
self.class.defaults.each do |attr, value|
|
44
|
-
@config[attr] = value unless @config.has_key?(attr)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def validate_config!
|
49
|
-
Array(self.class.validations).each do |tuple|
|
50
|
-
tuple.last.call(tuple.first, config[tuple.first], self)
|
51
|
-
end
|
41
|
+
init_config(config)
|
52
42
|
end
|
53
43
|
|
54
44
|
# Returns the name of this driver, suitable for display in a CLI.
|
55
45
|
#
|
56
46
|
# @return [String] name of this driver
|
57
47
|
def name
|
58
|
-
self.class.name.split(
|
59
|
-
end
|
60
|
-
|
61
|
-
# Provides hash-like access to configuration keys.
|
62
|
-
#
|
63
|
-
# @param attr [Object] configuration key
|
64
|
-
# @return [Object] value at configuration key
|
65
|
-
def [](attr)
|
66
|
-
config[attr]
|
67
|
-
end
|
68
|
-
|
69
|
-
# Returns an array of configuration keys.
|
70
|
-
#
|
71
|
-
# @return [Array] array of configuration keys
|
72
|
-
def config_keys
|
73
|
-
config.keys
|
48
|
+
self.class.name.split("::").last
|
74
49
|
end
|
75
50
|
|
76
51
|
# Creates an instance.
|
77
52
|
#
|
78
53
|
# @param state [Hash] mutable instance and driver state
|
79
54
|
# @raise [ActionFailed] if the action could not be completed
|
80
|
-
def create(state)
|
55
|
+
def create(state) # rubocop:disable Lint/UnusedMethodArgument
|
56
|
+
end
|
81
57
|
|
82
58
|
# Converges a running instance.
|
83
59
|
#
|
84
60
|
# @param state [Hash] mutable instance and driver state
|
85
61
|
# @raise [ActionFailed] if the action could not be completed
|
86
|
-
def converge(state)
|
62
|
+
def converge(state) # rubocop:disable Lint/UnusedMethodArgument
|
63
|
+
end
|
87
64
|
|
88
65
|
# Sets up an instance.
|
89
66
|
#
|
90
67
|
# @param state [Hash] mutable instance and driver state
|
91
68
|
# @raise [ActionFailed] if the action could not be completed
|
92
|
-
def setup(state)
|
69
|
+
def setup(state) # rubocop:disable Lint/UnusedMethodArgument
|
70
|
+
end
|
93
71
|
|
94
72
|
# Verifies a converged instance.
|
95
73
|
#
|
96
74
|
# @param state [Hash] mutable instance and driver state
|
97
75
|
# @raise [ActionFailed] if the action could not be completed
|
98
|
-
def verify(state)
|
76
|
+
def verify(state) # rubocop:disable Lint/UnusedMethodArgument
|
77
|
+
end
|
99
78
|
|
100
79
|
# Destroys an instance.
|
101
80
|
#
|
102
81
|
# @param state [Hash] mutable instance and driver state
|
103
82
|
# @raise [ActionFailed] if the action could not be completed
|
104
|
-
def destroy(state)
|
83
|
+
def destroy(state) # rubocop:disable Lint/UnusedMethodArgument
|
84
|
+
end
|
105
85
|
|
106
86
|
# Returns the shell command that will log into an instance.
|
107
87
|
#
|
@@ -109,7 +89,7 @@ module Kitchen
|
|
109
89
|
# @return [LoginCommand] an object containing the array of command line
|
110
90
|
# tokens and exec options to be used in a fork/exec
|
111
91
|
# @raise [ActionFailed] if the action could not be completed
|
112
|
-
def login_command(state)
|
92
|
+
def login_command(state) # rubocop:disable Lint/UnusedMethodArgument
|
113
93
|
raise ActionFailed, "Remote login is not supported in this driver."
|
114
94
|
end
|
115
95
|
|
@@ -120,36 +100,80 @@ module Kitchen
|
|
120
100
|
#
|
121
101
|
# @raise [UserError] if the driver will not be able to perform or if a
|
122
102
|
# documented dependency is missing from the system
|
123
|
-
def verify_dependencies
|
103
|
+
def verify_dependencies
|
104
|
+
end
|
124
105
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
result = Hash.new
|
130
|
-
config_keys.sort.each { |k| result[k] = config[k] }
|
131
|
-
result
|
106
|
+
class << self
|
107
|
+
# @return [Array<Symbol>] an array of action method names that cannot
|
108
|
+
# be run concurrently and must be run in serial via a shared mutex
|
109
|
+
attr_reader :serial_actions
|
132
110
|
end
|
133
111
|
|
134
|
-
|
112
|
+
# Registers certain driver actions that cannot be safely run concurrently
|
113
|
+
# in threads across multiple instances. Typically this might be used
|
114
|
+
# for create or destroy actions that use an underlying resource that
|
115
|
+
# cannot be used at the same time.
|
116
|
+
#
|
117
|
+
# A shared mutex for this driver object will be used to synchronize all
|
118
|
+
# registered methods.
|
119
|
+
#
|
120
|
+
# @example a single action method that cannot be run concurrently
|
121
|
+
#
|
122
|
+
# no_parallel_for :create
|
123
|
+
#
|
124
|
+
# @example multiple action methods that cannot be run concurrently
|
125
|
+
#
|
126
|
+
# no_parallel_for :create, :destroy
|
127
|
+
#
|
128
|
+
# @param methods [Array<Symbol>] one or more actions as symbols
|
129
|
+
# @raise [ClientError] if any method is not a valid action method name
|
130
|
+
def self.no_parallel_for(*methods)
|
131
|
+
action_methods = [:create, :converge, :setup, :verify, :destroy]
|
135
132
|
|
136
|
-
|
133
|
+
Array(methods).each do |meth|
|
134
|
+
next if action_methods.include?(meth)
|
137
135
|
|
138
|
-
|
139
|
-
|
136
|
+
raise ClientError, "##{meth} is not a valid no_parallel_for method"
|
137
|
+
end
|
140
138
|
|
139
|
+
@serial_actions ||= []
|
140
|
+
@serial_actions += methods
|
141
|
+
end
|
142
|
+
|
143
|
+
private
|
144
|
+
|
145
|
+
# Returns a suitable logger to use for output.
|
146
|
+
#
|
147
|
+
# @return [Kitchen::Logger] a logger
|
141
148
|
def logger
|
142
149
|
instance ? instance.logger : Kitchen.logger
|
143
150
|
end
|
144
151
|
|
152
|
+
# Intercepts any bare #puts calls in subclasses and issues an INFO log
|
153
|
+
# event instead.
|
154
|
+
#
|
155
|
+
# @param msg [String] message string
|
145
156
|
def puts(msg)
|
146
157
|
info(msg)
|
147
158
|
end
|
148
159
|
|
160
|
+
# Intercepts any bare #print calls in subclasses and issues an INFO log
|
161
|
+
# event instead.
|
162
|
+
#
|
163
|
+
# @param msg [String] message string
|
149
164
|
def print(msg)
|
150
165
|
info(msg)
|
151
166
|
end
|
152
167
|
|
168
|
+
# Delegates to Kitchen::ShellOut.run_command, overriding some default
|
169
|
+
# options:
|
170
|
+
#
|
171
|
+
# * `:use_sudo` defaults to the value of `config[:use_sudo]` in the
|
172
|
+
# Driver object
|
173
|
+
# * `:log_subject` defaults to a String representation of the Driver's
|
174
|
+
# class name
|
175
|
+
#
|
176
|
+
# @see ShellOut#run_command
|
153
177
|
def run_command(cmd, options = {})
|
154
178
|
base_options = {
|
155
179
|
:use_sudo => config[:use_sudo],
|
@@ -158,70 +182,11 @@ module Kitchen
|
|
158
182
|
super(cmd, base_options)
|
159
183
|
end
|
160
184
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
def busser_sync_cmd
|
166
|
-
busser.sync_cmd
|
167
|
-
end
|
168
|
-
|
169
|
-
def busser_run_cmd
|
170
|
-
busser.run_cmd
|
171
|
-
end
|
172
|
-
|
185
|
+
# Returns the Busser object associated with the driver.
|
186
|
+
#
|
187
|
+
# @return [Busser] a busser
|
173
188
|
def busser
|
174
|
-
|
175
|
-
raise ClientError, "Instance must be set for Driver" if instance.nil?
|
176
|
-
instance.busser
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
def self.defaults
|
181
|
-
@defaults ||= Hash.new.merge(super_defaults)
|
182
|
-
end
|
183
|
-
|
184
|
-
def self.super_defaults
|
185
|
-
klass = self.superclass
|
186
|
-
|
187
|
-
if klass.respond_to?(:defaults)
|
188
|
-
klass.defaults
|
189
|
-
else
|
190
|
-
Hash.new
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
def self.default_config(attr, value = nil, &block)
|
195
|
-
defaults[attr] = block_given? ? block : value
|
196
|
-
end
|
197
|
-
|
198
|
-
def self.validations
|
199
|
-
@validations
|
200
|
-
end
|
201
|
-
|
202
|
-
def self.required_config(attr, &block)
|
203
|
-
@validations = [] if @validations.nil?
|
204
|
-
if ! block_given?
|
205
|
-
klass = self
|
206
|
-
block = lambda do |attr, value, driver|
|
207
|
-
if value.nil? || value.to_s.empty?
|
208
|
-
attribute = "#{klass}#{driver.instance.to_str}#config[:#{attr}]"
|
209
|
-
raise UserError, "#{attribute} cannot be blank"
|
210
|
-
end
|
211
|
-
end
|
212
|
-
end
|
213
|
-
@validations << [attr, block]
|
214
|
-
end
|
215
|
-
|
216
|
-
def self.no_parallel_for(*methods)
|
217
|
-
Array(methods).each do |meth|
|
218
|
-
if ! ACTION_METHODS.include?(meth)
|
219
|
-
raise ClientError, "##{meth} is not a valid no_parallel_for method"
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
@serial_actions ||= []
|
224
|
-
@serial_actions += methods
|
189
|
+
instance.busser
|
225
190
|
end
|
226
191
|
end
|
227
192
|
end
|
data/lib/kitchen/driver/dummy.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
4
4
|
#
|
5
|
-
# Copyright (C) 2012, Fletcher Nichol
|
5
|
+
# Copyright (C) 2012, 2013, 2014 Fletcher Nichol
|
6
6
|
#
|
7
7
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
8
|
# you may not use this file except in compliance with the License.
|
@@ -16,13 +16,16 @@
|
|
16
16
|
# See the License for the specific language governing permissions and
|
17
17
|
# limitations under the License.
|
18
18
|
|
19
|
-
require
|
19
|
+
require "kitchen"
|
20
20
|
|
21
21
|
module Kitchen
|
22
22
|
|
23
23
|
module Driver
|
24
24
|
|
25
|
-
# Dummy driver for Kitchen.
|
25
|
+
# Dummy driver for Kitchen. This driver does nothing but report what would
|
26
|
+
# happen if this driver did anything of consequence. As a result it may
|
27
|
+
# be a useful driver to use when debugging or developing new features or
|
28
|
+
# plugins.
|
26
29
|
#
|
27
30
|
# @author Fletcher Nichol <fnichol@nichol.ca>
|
28
31
|
class Dummy < Kitchen::Driver::Base
|
@@ -30,23 +33,28 @@ module Kitchen
|
|
30
33
|
default_config :sleep, 0
|
31
34
|
default_config :random_failure, false
|
32
35
|
|
36
|
+
# (see Base#create)
|
33
37
|
def create(state)
|
34
38
|
state[:my_id] = "#{instance.name}-#{Time.now.to_i}"
|
35
39
|
report(:create, state)
|
36
40
|
end
|
37
41
|
|
42
|
+
# (see Base#converge)
|
38
43
|
def converge(state)
|
39
44
|
report(:converge, state)
|
40
45
|
end
|
41
46
|
|
47
|
+
# (see Base#setup)
|
42
48
|
def setup(state)
|
43
49
|
report(:setup, state)
|
44
50
|
end
|
45
51
|
|
52
|
+
# (see Base#verify)
|
46
53
|
def verify(state)
|
47
54
|
report(:verify, state)
|
48
55
|
end
|
49
56
|
|
57
|
+
# (see Base#destroy)
|
50
58
|
def destroy(state)
|
51
59
|
report(:destroy, state)
|
52
60
|
state.delete(:my_id)
|
@@ -54,25 +62,45 @@ module Kitchen
|
|
54
62
|
|
55
63
|
private
|
56
64
|
|
65
|
+
# Report what action is taking place, sleeping if so configured, and
|
66
|
+
# possibly fail randomly.
|
67
|
+
#
|
68
|
+
# @param action [Symbol] the action currently taking place
|
69
|
+
# @param state [Hash] the state hash
|
70
|
+
# @api private
|
57
71
|
def report(action, state)
|
58
72
|
what = action.capitalize
|
59
73
|
info("[Dummy] #{what} on instance=#{instance} with state=#{state}")
|
60
74
|
sleep_if_set
|
61
|
-
|
75
|
+
failure_if_set(action)
|
62
76
|
debug("[Dummy] #{what} completed (#{config[:sleep]}s).")
|
63
77
|
end
|
64
78
|
|
79
|
+
# Sleep for a period of time, if a value is set in the config.
|
80
|
+
#
|
81
|
+
# @api private
|
65
82
|
def sleep_if_set
|
66
83
|
sleep(config[:sleep].to_f) if config[:sleep].to_f > 0.0
|
67
84
|
end
|
68
85
|
|
69
|
-
|
70
|
-
|
86
|
+
# Simulate a failure in an action, if set in the config.
|
87
|
+
#
|
88
|
+
# @param action [Symbol] the action currently taking place
|
89
|
+
# @api private
|
90
|
+
def failure_if_set(action)
|
91
|
+
if config[:"fail_#{action}"]
|
92
|
+
debug("[Dummy] Failure for action ##{action}.")
|
93
|
+
raise ActionFailed, "Action ##{action} failed for #{instance.to_str}."
|
94
|
+
elsif config[:random_failure] && randomly_fail?
|
71
95
|
debug("[Dummy] Random failure for action ##{action}.")
|
72
96
|
raise ActionFailed, "Action ##{action} failed for #{instance.to_str}."
|
73
97
|
end
|
74
98
|
end
|
75
99
|
|
100
|
+
# Determine whether or not to randomly fail.
|
101
|
+
#
|
102
|
+
# @return [true, false]
|
103
|
+
# @api private
|
76
104
|
def randomly_fail?
|
77
105
|
[true, false].sample
|
78
106
|
end
|