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/errors.rb
CHANGED
|
@@ -1,229 +1,229 @@
|
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
|
2
|
-
#
|
|
3
|
-
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
|
4
|
-
#
|
|
5
|
-
# Copyright (C) 2013, Fletcher Nichol
|
|
6
|
-
#
|
|
7
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
-
# you may not use this file except in compliance with the License.
|
|
9
|
-
# You may obtain a copy of the License at
|
|
10
|
-
#
|
|
11
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
-
#
|
|
13
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
-
# See the License for the specific language governing permissions and
|
|
17
|
-
# limitations under the License.
|
|
18
|
-
|
|
19
|
-
require "English"
|
|
20
|
-
|
|
21
|
-
module Kitchen
|
|
22
|
-
|
|
23
|
-
# All Kitchen errors and exceptions.
|
|
24
|
-
#
|
|
25
|
-
# @author Fletcher Nichol <fnichol@nichol.ca>
|
|
26
|
-
module Error
|
|
27
|
-
|
|
28
|
-
# Creates an array of strings, representing a formatted exception,
|
|
29
|
-
# containing backtrace and nested exception info as necessary, that can
|
|
30
|
-
# be viewed by a human.
|
|
31
|
-
#
|
|
32
|
-
# For example:
|
|
33
|
-
#
|
|
34
|
-
# ------Exception-------
|
|
35
|
-
# Class: Kitchen::StandardError
|
|
36
|
-
# Message: Failure starting the party
|
|
37
|
-
# ---Nested Exception---
|
|
38
|
-
# Class: IOError
|
|
39
|
-
# Message: not enough directories for a party
|
|
40
|
-
# ------Backtrace-------
|
|
41
|
-
# nil
|
|
42
|
-
# ----------------------
|
|
43
|
-
#
|
|
44
|
-
# @param exception [::StandardError] an exception
|
|
45
|
-
# @return [Array<String>] a formatted message
|
|
46
|
-
def self.formatted_trace(exception)
|
|
47
|
-
arr = formatted_exception(exception).dup
|
|
48
|
-
last = arr.pop
|
|
49
|
-
if exception.respond_to?(:original) && exception.original
|
|
50
|
-
arr += formatted_exception(exception.original, "Nested Exception")
|
|
51
|
-
last = arr.pop
|
|
52
|
-
end
|
|
53
|
-
arr += ["Backtrace".center(22, "-"), exception.backtrace, last].flatten
|
|
54
|
-
arr
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# Creates an array of strings, representing a formatted exception that
|
|
58
|
-
# can be viewed by a human. Thanks to MiniTest for the inspiration
|
|
59
|
-
# upon which this output has been designed.
|
|
60
|
-
#
|
|
61
|
-
# For example:
|
|
62
|
-
#
|
|
63
|
-
# ------Exception-------
|
|
64
|
-
# Class: Kitchen::StandardError
|
|
65
|
-
# Message: I have failed you
|
|
66
|
-
# ----------------------
|
|
67
|
-
#
|
|
68
|
-
# @param exception [::StandardError] an exception
|
|
69
|
-
# @param title [String] a custom title for the message
|
|
70
|
-
# (default: `"Exception"`)
|
|
71
|
-
# @return [Array<String>] a formatted message
|
|
72
|
-
def self.formatted_exception(exception, title = "Exception")
|
|
73
|
-
[
|
|
74
|
-
title.center(22, "-"),
|
|
75
|
-
"Class: #{exception.class}",
|
|
76
|
-
"Message: #{exception.message}",
|
|
77
|
-
"".center(22, "-")
|
|
78
|
-
]
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
# Base exception class from which all Kitchen exceptions derive. This class
|
|
83
|
-
# nests an exception when this class is re-raised from a rescue block.
|
|
84
|
-
class StandardError < ::StandardError
|
|
85
|
-
|
|
86
|
-
include Error
|
|
87
|
-
|
|
88
|
-
# @return [::StandardError] the original (wrapped) exception
|
|
89
|
-
attr_reader :original
|
|
90
|
-
|
|
91
|
-
# Creates a new StandardError exception which optionally wraps an original
|
|
92
|
-
# exception if given or detected by checking the `$!` global variable.
|
|
93
|
-
#
|
|
94
|
-
# @param msg [String] exception message
|
|
95
|
-
# @param original [::StandardError] an original exception which will be
|
|
96
|
-
# wrapped (default: `$ERROR_INFO`)
|
|
97
|
-
def initialize(msg, original = $ERROR_INFO)
|
|
98
|
-
super(msg)
|
|
99
|
-
@original = original
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
# Base exception class for all exceptions that are caused by user input
|
|
104
|
-
# errors.
|
|
105
|
-
class UserError < StandardError; end
|
|
106
|
-
|
|
107
|
-
# Base exception class for all exceptions that are caused by incorrect use
|
|
108
|
-
# of an API.
|
|
109
|
-
class ClientError < StandardError; end
|
|
110
|
-
|
|
111
|
-
# Base exception class for exceptions that are caused by external library
|
|
112
|
-
# failures which may be temporary.
|
|
113
|
-
class TransientFailure < StandardError; end
|
|
114
|
-
|
|
115
|
-
# Exception class for any exceptions raised when performing an instance
|
|
116
|
-
# action.
|
|
117
|
-
class ActionFailed < TransientFailure; end
|
|
118
|
-
|
|
119
|
-
# Exception class capturing what caused an instance to die.
|
|
120
|
-
class InstanceFailure < TransientFailure; end
|
|
121
|
-
|
|
122
|
-
# Yields to a code block in order to consistently emit a useful crash/error
|
|
123
|
-
# message and exit appropriately. There are two primary failure conditions:
|
|
124
|
-
# an expected instance failure, and any other unexpected failures.
|
|
125
|
-
#
|
|
126
|
-
# **Note** This method may call `Kernel.exit` so may not return if the
|
|
127
|
-
# yielded code block raises an exception.
|
|
128
|
-
#
|
|
129
|
-
# ## Instance Failure
|
|
130
|
-
#
|
|
131
|
-
# This is an expected failure scenario which could happen if an instance
|
|
132
|
-
# couldn't be created, a Chef run didn't successfully converge, a
|
|
133
|
-
# post-convergence test suite failed, etc. In other words, you can count on
|
|
134
|
-
# encountering these failures all the time--this is Kitchen's worldview:
|
|
135
|
-
# crash early and often. In this case a cleanly formatted exception is
|
|
136
|
-
# written to `STDERR` and the exception message is written to
|
|
137
|
-
# the common Kitchen file logger.
|
|
138
|
-
#
|
|
139
|
-
# ## Unexpected Failure
|
|
140
|
-
#
|
|
141
|
-
# All other forms of `Kitchen::Error` exceptions are considered unexpected
|
|
142
|
-
# or unplanned exceptions, typically from user configuration errors, driver
|
|
143
|
-
# or provisioner coding issues or bugs, or internal code issues. Given
|
|
144
|
-
# a stable release of Kitchen and a solid set of drivers and provisioners,
|
|
145
|
-
# the most likely cause of this is user configuration error originating in
|
|
146
|
-
# the `.kitchen.yml` setup. For this reason, the exception is written to
|
|
147
|
-
# `STDERR`, a full formatted exception trace is written to the common
|
|
148
|
-
# Kitchen file logger, and a message is displayed on `STDERR` to the user
|
|
149
|
-
# informing them to check the log files and check their configuration with
|
|
150
|
-
# the `kitchen diagnose` subcommand.
|
|
151
|
-
#
|
|
152
|
-
# @raise [SystemExit] if an exception is raised in the yielded block
|
|
153
|
-
def self.with_friendly_errors
|
|
154
|
-
yield
|
|
155
|
-
rescue Kitchen::InstanceFailure => e
|
|
156
|
-
Kitchen.mutex.synchronize do
|
|
157
|
-
handle_instance_failure(e)
|
|
158
|
-
end
|
|
159
|
-
exit 10
|
|
160
|
-
rescue Kitchen::Error => e
|
|
161
|
-
Kitchen.mutex.synchronize do
|
|
162
|
-
handle_error(e)
|
|
163
|
-
end
|
|
164
|
-
exit 20
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
private
|
|
168
|
-
|
|
169
|
-
# Writes an array of lines to the common Kitchen logger's file device at the
|
|
170
|
-
# given severity level. If the Kitchen logger is set to debug severity, then
|
|
171
|
-
# the array of lines will also be written to the console output.
|
|
172
|
-
#
|
|
173
|
-
# @param level [Symbol,String] the desired log level
|
|
174
|
-
# @param lines [Array<String>] an array of strings to log
|
|
175
|
-
# @api private
|
|
176
|
-
def self.file_log(level, lines)
|
|
177
|
-
Array(lines).each do |line|
|
|
178
|
-
if Kitchen.logger.debug?
|
|
179
|
-
Kitchen.logger.debug(line)
|
|
180
|
-
else
|
|
181
|
-
Kitchen.logger.logdev && Kitchen.logger.logdev.public_send(level, line)
|
|
182
|
-
end
|
|
183
|
-
end
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
# Writes an array of lines to the `STDERR` device.
|
|
187
|
-
#
|
|
188
|
-
# @param lines [Array<String>] an array of strings to log
|
|
189
|
-
# @api private
|
|
190
|
-
def self.stderr_log(lines)
|
|
191
|
-
Array(lines).map { |line| ">>>>>> #{line}" }.each do |line|
|
|
192
|
-
line = Color.colorize(line, :red) if Kitchen.tty?
|
|
193
|
-
$stderr.puts(line)
|
|
194
|
-
end
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
# Writes an array of lines to the common Kitchen debugger with debug
|
|
198
|
-
# severity.
|
|
199
|
-
#
|
|
200
|
-
# @param lines [Array<String>] an array of strings to log
|
|
201
|
-
# @api private
|
|
202
|
-
def self.debug_log(lines)
|
|
203
|
-
Array(lines).each { |line| Kitchen.logger.debug(line) }
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
# Handles an instance failure exception.
|
|
207
|
-
#
|
|
208
|
-
# @param e [StandardError] an exception to handle
|
|
209
|
-
# @see Kitchen.with_friendly_errors
|
|
210
|
-
# @api private
|
|
211
|
-
def self.handle_instance_failure(e)
|
|
212
|
-
stderr_log(e.message.split(/\s{2,}/))
|
|
213
|
-
stderr_log(Error.formatted_exception(e.original))
|
|
214
|
-
file_log(:error, e.message.split(/\s{2,}/).first)
|
|
215
|
-
debug_log(Error.formatted_trace(e))
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
# Handles an unexpected failure exception.
|
|
219
|
-
#
|
|
220
|
-
# @param e [StandardError] an exception to handle
|
|
221
|
-
# @see Kitchen.with_friendly_errors
|
|
222
|
-
# @api private
|
|
223
|
-
def self.handle_error(e)
|
|
224
|
-
stderr_log(Error.formatted_exception(e))
|
|
225
|
-
stderr_log("Please see .kitchen/logs/kitchen.log for more details")
|
|
226
|
-
stderr_log("Also try running `kitchen diagnose --all` for configuration\n")
|
|
227
|
-
file_log(:error, Error.formatted_trace(e))
|
|
228
|
-
end
|
|
229
|
-
end
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Author:: Fletcher Nichol (<fnichol@nichol.ca>)
|
|
4
|
+
#
|
|
5
|
+
# Copyright (C) 2013, Fletcher Nichol
|
|
6
|
+
#
|
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
# you may not use this file except in compliance with the License.
|
|
9
|
+
# You may obtain a copy of the License at
|
|
10
|
+
#
|
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
#
|
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
# See the License for the specific language governing permissions and
|
|
17
|
+
# limitations under the License.
|
|
18
|
+
|
|
19
|
+
require "English"
|
|
20
|
+
|
|
21
|
+
module Kitchen
|
|
22
|
+
|
|
23
|
+
# All Kitchen errors and exceptions.
|
|
24
|
+
#
|
|
25
|
+
# @author Fletcher Nichol <fnichol@nichol.ca>
|
|
26
|
+
module Error
|
|
27
|
+
|
|
28
|
+
# Creates an array of strings, representing a formatted exception,
|
|
29
|
+
# containing backtrace and nested exception info as necessary, that can
|
|
30
|
+
# be viewed by a human.
|
|
31
|
+
#
|
|
32
|
+
# For example:
|
|
33
|
+
#
|
|
34
|
+
# ------Exception-------
|
|
35
|
+
# Class: Kitchen::StandardError
|
|
36
|
+
# Message: Failure starting the party
|
|
37
|
+
# ---Nested Exception---
|
|
38
|
+
# Class: IOError
|
|
39
|
+
# Message: not enough directories for a party
|
|
40
|
+
# ------Backtrace-------
|
|
41
|
+
# nil
|
|
42
|
+
# ----------------------
|
|
43
|
+
#
|
|
44
|
+
# @param exception [::StandardError] an exception
|
|
45
|
+
# @return [Array<String>] a formatted message
|
|
46
|
+
def self.formatted_trace(exception)
|
|
47
|
+
arr = formatted_exception(exception).dup
|
|
48
|
+
last = arr.pop
|
|
49
|
+
if exception.respond_to?(:original) && exception.original
|
|
50
|
+
arr += formatted_exception(exception.original, "Nested Exception")
|
|
51
|
+
last = arr.pop
|
|
52
|
+
end
|
|
53
|
+
arr += ["Backtrace".center(22, "-"), exception.backtrace, last].flatten
|
|
54
|
+
arr
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Creates an array of strings, representing a formatted exception that
|
|
58
|
+
# can be viewed by a human. Thanks to MiniTest for the inspiration
|
|
59
|
+
# upon which this output has been designed.
|
|
60
|
+
#
|
|
61
|
+
# For example:
|
|
62
|
+
#
|
|
63
|
+
# ------Exception-------
|
|
64
|
+
# Class: Kitchen::StandardError
|
|
65
|
+
# Message: I have failed you
|
|
66
|
+
# ----------------------
|
|
67
|
+
#
|
|
68
|
+
# @param exception [::StandardError] an exception
|
|
69
|
+
# @param title [String] a custom title for the message
|
|
70
|
+
# (default: `"Exception"`)
|
|
71
|
+
# @return [Array<String>] a formatted message
|
|
72
|
+
def self.formatted_exception(exception, title = "Exception")
|
|
73
|
+
[
|
|
74
|
+
title.center(22, "-"),
|
|
75
|
+
"Class: #{exception.class}",
|
|
76
|
+
"Message: #{exception.message}",
|
|
77
|
+
"".center(22, "-")
|
|
78
|
+
]
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Base exception class from which all Kitchen exceptions derive. This class
|
|
83
|
+
# nests an exception when this class is re-raised from a rescue block.
|
|
84
|
+
class StandardError < ::StandardError
|
|
85
|
+
|
|
86
|
+
include Error
|
|
87
|
+
|
|
88
|
+
# @return [::StandardError] the original (wrapped) exception
|
|
89
|
+
attr_reader :original
|
|
90
|
+
|
|
91
|
+
# Creates a new StandardError exception which optionally wraps an original
|
|
92
|
+
# exception if given or detected by checking the `$!` global variable.
|
|
93
|
+
#
|
|
94
|
+
# @param msg [String] exception message
|
|
95
|
+
# @param original [::StandardError] an original exception which will be
|
|
96
|
+
# wrapped (default: `$ERROR_INFO`)
|
|
97
|
+
def initialize(msg, original = $ERROR_INFO)
|
|
98
|
+
super(msg)
|
|
99
|
+
@original = original
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Base exception class for all exceptions that are caused by user input
|
|
104
|
+
# errors.
|
|
105
|
+
class UserError < StandardError; end
|
|
106
|
+
|
|
107
|
+
# Base exception class for all exceptions that are caused by incorrect use
|
|
108
|
+
# of an API.
|
|
109
|
+
class ClientError < StandardError; end
|
|
110
|
+
|
|
111
|
+
# Base exception class for exceptions that are caused by external library
|
|
112
|
+
# failures which may be temporary.
|
|
113
|
+
class TransientFailure < StandardError; end
|
|
114
|
+
|
|
115
|
+
# Exception class for any exceptions raised when performing an instance
|
|
116
|
+
# action.
|
|
117
|
+
class ActionFailed < TransientFailure; end
|
|
118
|
+
|
|
119
|
+
# Exception class capturing what caused an instance to die.
|
|
120
|
+
class InstanceFailure < TransientFailure; end
|
|
121
|
+
|
|
122
|
+
# Yields to a code block in order to consistently emit a useful crash/error
|
|
123
|
+
# message and exit appropriately. There are two primary failure conditions:
|
|
124
|
+
# an expected instance failure, and any other unexpected failures.
|
|
125
|
+
#
|
|
126
|
+
# **Note** This method may call `Kernel.exit` so may not return if the
|
|
127
|
+
# yielded code block raises an exception.
|
|
128
|
+
#
|
|
129
|
+
# ## Instance Failure
|
|
130
|
+
#
|
|
131
|
+
# This is an expected failure scenario which could happen if an instance
|
|
132
|
+
# couldn't be created, a Chef run didn't successfully converge, a
|
|
133
|
+
# post-convergence test suite failed, etc. In other words, you can count on
|
|
134
|
+
# encountering these failures all the time--this is Kitchen's worldview:
|
|
135
|
+
# crash early and often. In this case a cleanly formatted exception is
|
|
136
|
+
# written to `STDERR` and the exception message is written to
|
|
137
|
+
# the common Kitchen file logger.
|
|
138
|
+
#
|
|
139
|
+
# ## Unexpected Failure
|
|
140
|
+
#
|
|
141
|
+
# All other forms of `Kitchen::Error` exceptions are considered unexpected
|
|
142
|
+
# or unplanned exceptions, typically from user configuration errors, driver
|
|
143
|
+
# or provisioner coding issues or bugs, or internal code issues. Given
|
|
144
|
+
# a stable release of Kitchen and a solid set of drivers and provisioners,
|
|
145
|
+
# the most likely cause of this is user configuration error originating in
|
|
146
|
+
# the `.kitchen.yml` setup. For this reason, the exception is written to
|
|
147
|
+
# `STDERR`, a full formatted exception trace is written to the common
|
|
148
|
+
# Kitchen file logger, and a message is displayed on `STDERR` to the user
|
|
149
|
+
# informing them to check the log files and check their configuration with
|
|
150
|
+
# the `kitchen diagnose` subcommand.
|
|
151
|
+
#
|
|
152
|
+
# @raise [SystemExit] if an exception is raised in the yielded block
|
|
153
|
+
def self.with_friendly_errors
|
|
154
|
+
yield
|
|
155
|
+
rescue Kitchen::InstanceFailure => e
|
|
156
|
+
Kitchen.mutex.synchronize do
|
|
157
|
+
handle_instance_failure(e)
|
|
158
|
+
end
|
|
159
|
+
exit 10
|
|
160
|
+
rescue Kitchen::Error => e
|
|
161
|
+
Kitchen.mutex.synchronize do
|
|
162
|
+
handle_error(e)
|
|
163
|
+
end
|
|
164
|
+
exit 20
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
private
|
|
168
|
+
|
|
169
|
+
# Writes an array of lines to the common Kitchen logger's file device at the
|
|
170
|
+
# given severity level. If the Kitchen logger is set to debug severity, then
|
|
171
|
+
# the array of lines will also be written to the console output.
|
|
172
|
+
#
|
|
173
|
+
# @param level [Symbol,String] the desired log level
|
|
174
|
+
# @param lines [Array<String>] an array of strings to log
|
|
175
|
+
# @api private
|
|
176
|
+
def self.file_log(level, lines)
|
|
177
|
+
Array(lines).each do |line|
|
|
178
|
+
if Kitchen.logger.debug?
|
|
179
|
+
Kitchen.logger.debug(line)
|
|
180
|
+
else
|
|
181
|
+
Kitchen.logger.logdev && Kitchen.logger.logdev.public_send(level, line)
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Writes an array of lines to the `STDERR` device.
|
|
187
|
+
#
|
|
188
|
+
# @param lines [Array<String>] an array of strings to log
|
|
189
|
+
# @api private
|
|
190
|
+
def self.stderr_log(lines)
|
|
191
|
+
Array(lines).map { |line| ">>>>>> #{line}" }.each do |line|
|
|
192
|
+
line = Color.colorize(line, :red) if Kitchen.tty?
|
|
193
|
+
$stderr.puts(line)
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Writes an array of lines to the common Kitchen debugger with debug
|
|
198
|
+
# severity.
|
|
199
|
+
#
|
|
200
|
+
# @param lines [Array<String>] an array of strings to log
|
|
201
|
+
# @api private
|
|
202
|
+
def self.debug_log(lines)
|
|
203
|
+
Array(lines).each { |line| Kitchen.logger.debug(line) }
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Handles an instance failure exception.
|
|
207
|
+
#
|
|
208
|
+
# @param e [StandardError] an exception to handle
|
|
209
|
+
# @see Kitchen.with_friendly_errors
|
|
210
|
+
# @api private
|
|
211
|
+
def self.handle_instance_failure(e)
|
|
212
|
+
stderr_log(e.message.split(/\s{2,}/))
|
|
213
|
+
stderr_log(Error.formatted_exception(e.original))
|
|
214
|
+
file_log(:error, e.message.split(/\s{2,}/).first)
|
|
215
|
+
debug_log(Error.formatted_trace(e))
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# Handles an unexpected failure exception.
|
|
219
|
+
#
|
|
220
|
+
# @param e [StandardError] an exception to handle
|
|
221
|
+
# @see Kitchen.with_friendly_errors
|
|
222
|
+
# @api private
|
|
223
|
+
def self.handle_error(e)
|
|
224
|
+
stderr_log(Error.formatted_exception(e))
|
|
225
|
+
stderr_log("Please see .kitchen/logs/kitchen.log for more details")
|
|
226
|
+
stderr_log("Also try running `kitchen diagnose --all` for configuration\n")
|
|
227
|
+
file_log(:error, Error.formatted_trace(e))
|
|
228
|
+
end
|
|
229
|
+
end
|