test-kitchen 1.2.1 → 1.3.0
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 +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
|