Module: Kitchen

Defined in:
lib/kitchen.rb,
lib/kitchen/cli.rb,
lib/kitchen/util.rb,
lib/kitchen/color.rb,
lib/kitchen/suite.rb,
lib/kitchen/which.rb,
lib/kitchen/config.rb,
lib/kitchen/driver.rb,
lib/kitchen/errors.rb,
lib/kitchen/logger.rb,
lib/kitchen/plugin.rb,
lib/kitchen/command.rb,
lib/kitchen/logging.rb,
lib/kitchen/version.rb,
lib/kitchen/instance.rb,
lib/kitchen/platform.rb,
lib/kitchen/verifier.rb,
lib/kitchen/lazy_hash.rb,
lib/kitchen/shell_out.rb,
lib/kitchen/transport.rb,
lib/kitchen/collection.rb,
lib/kitchen/diagnostic.rb,
lib/kitchen/rake_tasks.rb,
lib/kitchen/state_file.rb,
lib/kitchen/thor_tasks.rb,
lib/kitchen/data_munger.rb,
lib/kitchen/driver/base.rb,
lib/kitchen/driver/exec.rb,
lib/kitchen/loader/yaml.rb,
lib/kitchen/plugin_base.rb,
lib/kitchen/provisioner.rb,
lib/kitchen/command/exec.rb,
lib/kitchen/command/list.rb,
lib/kitchen/command/logs.rb,
lib/kitchen/command/sink.rb,
lib/kitchen/command/test.rb,
lib/kitchen/configurable.rb,
lib/kitchen/driver/dummy.rb,
lib/kitchen/driver/proxy.rb,
lib/kitchen/base64_stream.rb,
lib/kitchen/command/login.rb,
lib/kitchen/login_command.rb,
lib/kitchen/transport/ssh.rb,
lib/kitchen/verifier/base.rb,
lib/kitchen/command/action.rb,
lib/kitchen/command/doctor.rb,
lib/kitchen/generator/init.rb,
lib/kitchen/transport/base.rb,
lib/kitchen/transport/exec.rb,
lib/kitchen/verifier/dummy.rb,
lib/kitchen/verifier/shell.rb,
lib/kitchen/command/console.rb,
lib/kitchen/command/package.rb,
lib/kitchen/lifecycle_hooks.rb,
lib/kitchen/platform_filter.rb,
lib/kitchen/transport/dummy.rb,
lib/kitchen/transport/winrm.rb,
lib/kitchen/verifier/busser.rb,
lib/kitchen/command/diagnose.rb,
lib/kitchen/metadata_chopper.rb,
lib/kitchen/provisioner/base.rb,
lib/kitchen/chef_utils_wiring.rb,
lib/kitchen/provisioner/dummy.rb,
lib/kitchen/provisioner/shell.rb,
lib/kitchen/lifecycle_hook/base.rb,
lib/kitchen/lifecycle_hook/local.rb,
lib/kitchen/provisioner/external.rb,
lib/kitchen/lifecycle_hook/remote.rb

Overview

Copyright

Copyright (c) Chef Software Inc.

License

Apache License, Version 2.0

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Defined Under Namespace

Modules: Base64Stream, ChefUtilsWiring, Color, Command, Configurable, Driver, Error, Generator, Loader, Logging, Plugin, Provisioner, ShellOut, Transport, Util, Verifier, Which Classes: ActionFailed, CLI, ClientError, Collection, Config, DataMunger, Diagnostic, Instance, InstanceFailure, LazyHash, LifecycleHook, LifecycleHooks, Logger, LoginCommand, MetadataChopper, Platform, PlatformFilter, RakeTasks, StandardError, StateFile, StateFileLoadError, Suite, ThorTasks, TransientFailure, UserError

Constant Summary collapse

DEFAULT_LOG_LEVEL =

Default log level verbosity

:info
DEFAULT_LOG_OVERWRITE =

Overwrite the log file when Test Kitchen runs

true
DEFAULT_TEST_DIR =

Default base directory for integration tests, fixtures, etc.

"test/integration".freeze
DEFAULT_LOG_DIR =

Default base directory for instance and common log files

".kitchen/logs".freeze
VERSION =

The currently released version of Test Kitchen.

Returns:

  • (String)

    a semantic version string

"4.1.3".freeze

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.loggerLogger

Returns the common Kitchen logger.

Returns:

  • (Logger)

    the common Kitchen logger



55
56
57
# File 'lib/kitchen.rb', line 55

def logger
  @logger
end

.mutexMutex

Returns a common mutex for global coordination.

Returns:

  • (Mutex)

    a common mutex for global coordination



58
59
60
# File 'lib/kitchen.rb', line 58

def mutex
  @mutex
end

.run_idString

Returns the current Kitchen run identifier.

Returns:

  • (String)

    identifier for the current Kitchen process invocation



126
127
128
# File 'lib/kitchen.rb', line 126

def run_id
  @run_id ||= SecureRandom.uuid
end

Class Method Details

.debug_log(lines) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Writes an array of lines to the common Kitchen debugger with debug severity.

Parameters:

  • lines (Array<String>)

    an array of strings to log



236
237
238
# File 'lib/kitchen/errors.rb', line 236

def self.debug_log(lines)
  Array(lines).each { |line| Kitchen.logger.debug(line) }
end

.default_file_logger(level = nil, log_overwrite = nil) ⇒ Logger

Returns a default file logger which emits on standard output and to a log file.

Parameters:

  • level (Symbol) (defaults to: nil)

    logging level

  • log_overwrite (Boolean) (defaults to: nil)

    whether to overwrite the log file

Returns:



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/kitchen.rb', line 105

def default_file_logger(level = nil, log_overwrite = nil)
  level ||= env_log
  log_overwrite = log_overwrite.nil? ? env_log_overwrite : log_overwrite
  log_location = File.expand_path(File.join(DEFAULT_LOG_DIR, "kitchen.log"))
  log_location = log_location.to_s
  structured_log_location = File.expand_path(File.join(DEFAULT_LOG_DIR, "kitchen.ndjson"))
  structured_log_location = structured_log_location.to_s

  Logger.new(
    stdout: $stdout,
    logdev: log_location,
    structured_logdev: structured_log_location,
    level: Util.to_logger_level(level),
    log_overwrite:,
    metadata: { kitchen_run_id: run_id }
  )
end

.default_loggerLogger

Returns a default logger which emits on standard output.

Returns:



91
92
93
94
95
96
97
# File 'lib/kitchen.rb', line 91

def default_logger
  Logger.new(
    stdout: $stdout,
    level: Util.to_logger_level(env_log),
    metadata: { kitchen_run_id: run_id }
  )
end

.env_logSymbol?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Determine the default log level from an environment variable, if it is set.

Returns:

  • (Symbol, nil)

    a log level or nil if not set



143
144
145
# File 'lib/kitchen.rb', line 143

def env_log
  ENV["KITCHEN_LOG"] && ENV["KITCHEN_LOG"].downcase.to_sym
end

.env_log_overwriteBoolean?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Determine the log overwriting logic from an environment variable, if it is set.

Returns:

  • (Boolean, nil)


152
153
154
155
156
157
158
159
160
161
# File 'lib/kitchen.rb', line 152

def env_log_overwrite
  case ENV["KITCHEN_LOG_OVERWRITE"] && ENV["KITCHEN_LOG_OVERWRITE"].downcase
  when nil, ""
    nil
  when "false", "f", "no"
    false
  else
    true
  end
end

.file_log(level, lines) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Writes an array of lines to the common Kitchen logger's file device at the given severity level. If the Kitchen logger is set to debug severity, then the array of lines will also be written to the console output.

Parameters:

  • level (Symbol, String)

    the desired log level

  • lines (Array<String>)

    an array of strings to log



209
210
211
212
213
214
215
216
217
218
# File 'lib/kitchen/errors.rb', line 209

def self.file_log(level, lines)
  Array(lines).each do |line|
    if Kitchen.logger.debug?
      Kitchen.logger.debug(line)
    else
      Kitchen.logger.logdev && Kitchen.logger.logdev.public_send(level, line)
      Kitchen.logger.structured_logdev && Kitchen.logger.structured_logdev.public_send(level, line)
    end
  end
end

.handle_error(e) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Handles an unexpected failure exception.

Parameters:

See Also:



257
258
259
260
261
262
# File 'lib/kitchen/errors.rb', line 257

def self.handle_error(e)
  stderr_log(Error.formatted_exception(e))
  stderr_log("Please see .kitchen/logs/kitchen.log for more details")
  stderr_log("Also try running `kitchen diagnose --all` for configuration\n")
  file_log(:error, Error.formatted_trace(e))
end

.handle_instance_failure(e) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Handles an instance failure exception.

Parameters:

See Also:



245
246
247
248
249
250
# File 'lib/kitchen/errors.rb', line 245

def self.handle_instance_failure(e)
  stderr_log(e.message.split(/\s{2,}/))
  stderr_log(Error.formatted_exception(e.original))
  file_log(:error, e.message.split(/\s{2,}/).first)
  debug_log(Error.formatted_trace(e))
end

.mutex_chdirMutex

Deprecated.

Use Kitchen::Util.mutex_chdir, which owns the mutex and is available without loading all of Test Kitchen.

Returns the mutex used for Dir.chdir coordination.

Returns:

  • (Mutex)

    a mutex used for Dir.chdir coordination



65
66
67
# File 'lib/kitchen.rb', line 65

def mutex_chdir
  Kitchen::Util.mutex_chdir
end

.mutex_chdir=(mutex) ⇒ Mutex

Sets the mutex used for Dir.chdir coordination.

Parameters:

  • mutex (Mutex)

    the mutex to use for Dir.chdir coordination

Returns:

  • (Mutex)

    the newly set mutex



74
75
76
# File 'lib/kitchen.rb', line 74

def mutex_chdir=(mutex)
  Kitchen::Util.mutex_chdir = mutex
end

.source_rootPathname

Returns the root path of the Kitchen gem source code.

Returns:

  • (Pathname)

    root path of gem



84
85
86
# File 'lib/kitchen.rb', line 84

def source_root
  @source_root ||= Pathname.new(File.expand_path("..", __dir__))
end

.stderr_log(lines) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Writes an array of lines to the STDERR device.

Parameters:

  • lines (Array<String>)

    an array of strings to log



224
225
226
227
228
229
# File 'lib/kitchen/errors.rb', line 224

def self.stderr_log(lines)
  Array(lines).map { |line| ">>>>>> #{line}" }.each do |line|
    line = Color.colorize(line, :red) if Kitchen.tty?
    $stderr.puts(line)
  end
end

.tty?true, false

Returns whether or not standard output is associated with a terminal device (tty).

Returns:

  • (true, false)

    is there a tty?



134
135
136
# File 'lib/kitchen.rb', line 134

def tty?
  $stdout.tty?
end

.with_friendly_errorsObject

Yields to a code block in order to consistently emit a useful crash/error message and exit appropriately. There are two primary failure conditions: an expected instance failure, and any other unexpected failures.

Note This method may call Kernel.exit so may not return if the yielded code block raises an exception.

Instance Failure

This is an expected failure scenario which could happen if an instance couldn't be created, a Chef run didn't successfully converge, a post-convergence test suite failed, etc. In other words, you can count on encountering these failures all the time--this is Kitchen's worldview: crash early and often. In this case a cleanly formatted exception is written to STDERR and the exception message is written to the common Kitchen file logger.

Unexpected Failure

All other forms of Kitchen::Error exceptions are considered unexpected or unplanned exceptions, typically from user configuration errors, driver or provisioner coding issues or bugs, or internal code issues. Given a stable release of Kitchen and a solid set of drivers and provisioners, the most likely cause of this is user configuration error originating in the .kitchen.yml setup. For this reason, the exception is written to STDERR, a full formatted exception trace is written to the common Kitchen file logger, and a message is displayed on STDERR to the user informing them to check the log files and check their configuration with the kitchen diagnose subcommand.

Raises:

  • (SystemExit)

    if an exception is raised in the yielded block



188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/kitchen/errors.rb', line 188

def self.with_friendly_errors
  yield
rescue Kitchen::InstanceFailure => e
  Kitchen.mutex.synchronize do
    handle_instance_failure(e)
  end
  exit 10
rescue Kitchen::Error => e
  Kitchen.mutex.synchronize do
    handle_error(e)
  end
  exit 20
end