module Kitchen

Test Kitchen base module.

@author Fletcher Nichol <fnichol@nichol.ca>

Author

Fletcher Nichol (<fnichol@nichol.ca>)

Copyright (C) 2014, Fletcher Nichol

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

http://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.

Copyright

Copyright © 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

http://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.

Author

Fletcher Nichol (<fnichol@nichol.ca>)

Copyright (C) 2013, Fletcher Nichol

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

http://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.

Author

Fletcher Nichol (<fnichol@nichol.ca>)

Copyright (C) 2013, Fletcher Nichol

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

http://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.

Author

Fletcher Nichol (<fnichol@nichol.ca>)

Copyright (C) 2012, 2013, 2014, Fletcher Nichol

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

http://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.

Author

Fletcher Nichol (<fnichol@nichol.ca>)

Copyright (C) 2013, Fletcher Nichol

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

http://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.

Author

Fletcher Nichol (<fnichol@nichol.ca>)

Copyright (C) 2013, Fletcher Nichol

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

http://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.

Author

Fletcher Nichol (<fnichol@nichol.ca>)

Copyright (C) 2012, Fletcher Nichol

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

http://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.

Author

Fletcher Nichol (<fnichol@nichol.ca>)

Copyright (C) 2012, Fletcher Nichol

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

http://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.

Author

Baptiste Courtois (<b.courtois@criteo.com>)

Copyright (C) 2021, Baptiste Courtois

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

http://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.

Author

Fletcher Nichol (<fnichol@nichol.ca>)

Copyright (C) 2014, Fletcher Nichol

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

http://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.

Author

Fletcher Nichol (<fnichol@nichol.ca>)

Copyright (C) 2012, 2013, Fletcher Nichol

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

http://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.

Constants

DEFAULT_LOG_DIR

Default base directory for instance and common log files

DEFAULT_LOG_LEVEL

Default log level verbosity

DEFAULT_LOG_OVERWRITE

Overwrite the log file when Test Kitchen runs

DEFAULT_TEST_DIR

Default base directory for integration tests, fixtures, etc.

VERSION

Attributes

logger[RW]

@return [Logger] the common Kitchen logger

mutex[RW]

@return [Mutex] a common mutex for global coordination

mutex_chdir[RW]

@return [Mutex] a mutex used for Dir.chdir coordination

Public Class Methods

debug_log(lines) click to toggle source

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

@param lines [Array<String>] an array of strings to log @api private

# File lib/kitchen/errors.rb, line 229
def self.debug_log(lines)
  Array(lines).each { |line| Kitchen.logger.debug(line) }
end
default_file_logger(level = nil, log_overwrite = nil) click to toggle source

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

@param [Symbol] level logging level @param [Boolean] log_overwrite logging level @return [Logger] a logger

# File lib/kitchen.rb, line 84
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

  Logger.new(
    stdout: $stdout,
    logdev: log_location,
    level: Util.to_logger_level(level),
    log_overwrite: log_overwrite
  )
end
default_logger() click to toggle source

Returns a default logger which emits on standard output.

@return [Logger] a logger

# File lib/kitchen.rb, line 74
def default_logger
  Logger.new(stdout: $stdout, level: Util.to_logger_level(env_log))
end
env_log() click to toggle source

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

@return [Symbol,nil] a log level or nil if not set @api private

# File lib/kitchen.rb, line 111
def env_log
  ENV["KITCHEN_LOG"] && ENV["KITCHEN_LOG"].downcase.to_sym
end
env_log_overwrite() click to toggle source

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

@return [Boolean,nil] @api private

# File lib/kitchen.rb, line 120
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) click to toggle source

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.

@param level [Symbol,String] the desired log level @param lines [Array<String>] an array of strings to log @api private

# File lib/kitchen/errors.rb, line 203
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)
    end
  end
end
handle_error(e) click to toggle source

Handles an unexpected failure exception.

@param e [StandardError] an exception to handle @see Kitchen.with_friendly_errors @api private

# File lib/kitchen/errors.rb, line 250
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) click to toggle source

Handles an instance failure exception.

@param e [StandardError] an exception to handle @see Kitchen.with_friendly_errors @api private

# File lib/kitchen/errors.rb, line 238
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
source_root() click to toggle source

Returns the root path of the Kitchen gem source code.

@return [Pathname] root path of gem

# File lib/kitchen.rb, line 67
def source_root
  @source_root ||= Pathname.new(File.expand_path("..", __dir__))
end
stderr_log(lines) click to toggle source

Writes an array of lines to the `STDERR` device.

@param lines [Array<String>] an array of strings to log @api private

# File lib/kitchen/errors.rb, line 217
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?() click to toggle source

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

@return [true,false] is there a tty?

# File lib/kitchen.rb, line 102
def tty?
  $stdout.tty?
end
with_friendly_errors() { || ... } click to toggle source

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.

@raise [SystemExit] if an exception is raised in the yielded block

# File lib/kitchen/errors.rb, line 182
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