class Kitchen::Config
Base configuration class for Kitchen
. This class exposes configuration such as the location of the Kitchen
config file, instances, log_levels, etc. This object is a factory object, meaning that it is responsible for consuming the desired testing configuration in and returning Ruby objects which are used to perfom the work.
Most internal objects are created with the expectation of being immutable, meaning that internal state cannot be modified after creation. Any data manipulation or thread-unsafe activity is performed in this object so that the subsequently created objects (such as Instances, Platforms, Drivers, etc.) can safely run in concurrent threads of execution. To prevent the re-creation of duplicate objects, most created objects are memoized. The consequence of this is that once the Instance
Array has been requested (with the `#instances` message), you will always be returned the same Instance
objects.
@example fetching all instances
Kitchen::Config.new.instances
@example fetching an instance by name
Kitchen::Config.new.instances.get("default-ubuntu-16.04")
@example fetching all instances matching a regular expression
Kitchen::Config.new.instances.get_all(/ubuntu/)
@author Fletcher Nichol <fnichol@nichol.ca>
Attributes
@return [Boolean] whether to force color output or not in logger @api private
@return [Boolean] whether to enable debugging in the provisioner/verifier plugin or not @api private
@return [String] the absolute path to the root of a Test Kitchen
project @api private
@return [#read] the data loader that responds to a `#read` message,
returning a Hash data structure
@api private
@return [Symbol] the logging verbosity level @api private
@return [Boolean] whether to overwrite the log file when
Test Kitchen runs
@api private
@return [String] the absolute path to the directory into which all Test
Kitchen log files will be written
@api private
@return [String] an absolute path to the directory containing test suites @api private
Public Class Methods
Creates a new configuration, representing a particular testing configuration for a project.
@param [Hash] options configuration @option options [#read] :loader an object that responds to `#read` with
a Hash structure suitable for manipulating (default: `Kitchen::Loader::YAML.new`)
@option options [String] :kitchen_root an absolute path to the root of a
Test Kitchen project, usually containing a `.kitchen.yml` file (default `Dir.pwd`)
@option options [String] :log_root an absolute path to the directory
into which all Test Kitchen log files will be written (default: `"#{kitchen_root}/.kitchen/logs"`)
@option options [String] :test_base_path an absolute path to the
directory containing test suites and other testing-related files and directories (default: `"#{kitchen_root}/test/integration"`)
@option options [Symbol] :log_level the log level verbosity that the
loggers will use when outputing information (default: `:info`)
# File lib/kitchen/config.rb, line 102 def initialize(options = {}) @loader = options.fetch(:loader) { Kitchen::Loader::YAML.new } @kitchen_root = options.fetch(:kitchen_root) { Dir.pwd } @log_level = options.fetch(:log_level) { Kitchen::DEFAULT_LOG_LEVEL } @log_overwrite = options.fetch(:log_overwrite) { Kitchen::DEFAULT_LOG_OVERWRITE } @colorize = options.fetch(:colorize) { Kitchen.tty? } @log_root = options.fetch(:log_root) { default_log_root } @test_base_path = options.fetch(:test_base_path) { default_test_base_path } @debug = options.fetch(:debug) { false } end
Public Instance Methods
@return [Collection<Instance>] all instances, resulting from all
platform and suite combinations
# File lib/kitchen/config.rb, line 115 def instances @instances ||= Collection.new(build_instances) end
@return [Collection<Platform>] all defined platforms which will be used
in convergence integration
# File lib/kitchen/config.rb, line 121 def platforms @platforms ||= Collection.new( data.platform_data.map { |pdata| Platform.new(pdata) } ) end
@return [Collection<Suite>] all defined suites which will be used in
convergence integration
# File lib/kitchen/config.rb, line 129 def suites @suites ||= Collection.new( data.suite_data.map { |sdata| Suite.new(sdata) } ) end
Private Instance Methods
Builds the filtered list of Instance
objects.
@return [Array<Instance] an array of Instances @api private
# File lib/kitchen/config.rb, line 141 def build_instances filter_instances.map.with_index do |(suite, platform), index| new_instance(suite, platform, index) end end
Returns an object which can generate configuration hashes for all the primary Test Kitchen
objects such as Drivers, Provisioners, etc.
@return [DataMunger] a data manipulator @api private
# File lib/kitchen/config.rb, line 152 def data @data ||= DataMunger.new(loader.read, kitchen_config) end
Determines the default absolute path to a log directory, based on the value of `#kitchen_root`.
@return [String] an absolute path to the log directory @api private
# File lib/kitchen/config.rb, line 161 def default_log_root File.join(kitchen_root, Kitchen::DEFAULT_LOG_DIR) end
Determines the default absolute path to the testing files directory, based on the the value of `#kitchen_root`.
@return [String] an absolute path to the testing files directory @api private
# File lib/kitchen/config.rb, line 170 def default_test_base_path File.join(kitchen_root, Kitchen::DEFAULT_TEST_DIR) end
Generates a filtered Array of tuples (Suite/Platform pairs) which is the cartesian product of suites and platforms. A Suite
has two optional arrays (`#includes` and `#excludes`) which can be used to drop or select certain Platforms with which to join.
@return [Array<Array<Suite, Platform>>] an Array of Suite/Platform
tuples
@api private
# File lib/kitchen/config.rb, line 182 def filter_instances suites.product(platforms).select do |suite, platform| if !suite.includes.empty? suite.includes.include?(platform.name) elsif !suite.excludes.empty? !suite.excludes.include?(platform.name) else true end end end
Determines the String name for an Instance
, given a Suite
and a Platform
.
@param suite [Suite,#name] a Suite
@param platform [Platform,#name] a Platform
@return [String] an Instance
name @api private
# File lib/kitchen/config.rb, line 200 def instance_name(suite, platform) Instance.name_for(suite, platform) end
Generates the immutable Test Kitchen
configuration and reasonable defaults for Drivers, Provisioners and Transports.
@return [Hash] a configuration Hash
@api private
# File lib/kitchen/config.rb, line 209 def kitchen_config @kitchen_config ||= { defaults: { driver: Driver::DEFAULT_PLUGIN, provisioner: Provisioner::DEFAULT_PLUGIN, verifier: Verifier::DEFAULT_PLUGIN, transport: lambda do |_suite, platform| /^win/i.match?(platform) ? "winrm" : Transport::DEFAULT_PLUGIN end, }, kitchen_root: kitchen_root, test_base_path: test_base_path, log_level: log_level, log_overwrite: log_overwrite, debug: debug, } end
Builds a newly configured Driver
object, for a given Suite
and Platform
.
@param suite [Suite,#name] a Suite
@param platform [Platform,#name] a Platform
@return [Driver] a new Driver
object @api private
# File lib/kitchen/config.rb, line 233 def new_driver(suite, platform) ddata = data.driver_data_for(suite.name, platform.name) Driver.for_plugin(ddata[:name], ddata) end
Builds a newly configured Instance
object, for a given Suite
and Platform
.
@param suite [Suite,#name] a Suite
@param platform [Platform,#name] a Platform
@param index [Integer] an index used for colorizing output @return [Instance] a new Instance
object @api private
# File lib/kitchen/config.rb, line 246 def new_instance(suite, platform, index) sf = new_state_file(suite, platform) Instance.new( driver: new_driver(suite, platform), lifecycle_hooks: new_lifecycle_hooks(suite, platform, sf), logger: new_instance_logger(suite, platform, index), suite: suite, platform: platform, provisioner: new_provisioner(suite, platform), transport: new_transport(suite, platform), verifier: new_verifier(suite, platform), state_file: sf ) end
Builds a newly configured Logger
object, for a given Suite
and Platform
.
@param suite [Suite,#name] a Suite
@param platform [Platform,#name] a Platform
@param index [Integer] an index used for colorizing output @return [Logger] a new Logger
object @api private
# File lib/kitchen/config.rb, line 270 def new_instance_logger(suite, platform, index) name = instance_name(suite, platform) log_location = File.join(log_root, "#{name}.log").to_s Logger.new( stdout: STDOUT, color: Color::COLORS[index % Color::COLORS.size].to_sym, logdev: log_location, level: Util.to_logger_level(log_level), log_overwrite: log_overwrite, progname: name, colorize: @colorize ) end
Builds a newly configured LifecycleHooks
object, for a given a Suite
and Platform
.
@param suite [Suite,#name] a Suite
@param platform [Platform,#name] a Platform
@param state_file [Kitchen::StateFile] a SateFile @return [LifecycleHooks] a new LifecycleHooks
object @api private
# File lib/kitchen/config.rb, line 292 def new_lifecycle_hooks(suite, platform, state_file) lhdata = data.lifecycle_hooks_data_for(suite.name, platform.name) LifecycleHooks.new(lhdata, state_file) end
Builds a newly configured Provisioner
object, for a given Suite
and Platform
.
@param suite [Suite,#name] a Suite
@param platform [Platform,#name] a Platform
@return [Provisioner] a new Provisioner
object @api private
# File lib/kitchen/config.rb, line 304 def new_provisioner(suite, platform) pdata = data.provisioner_data_for(suite.name, platform.name) Provisioner.for_plugin(pdata[:name], pdata) end
Builds a newly configured StateFile
object, for a given Suite
and Platform
.
@param suite [Suite,#name] a Suite
@param platform [Platform,#name] a Platform
@return [StateFile] a new StateFile
object @api private
# File lib/kitchen/config.rb, line 316 def new_state_file(suite, platform) StateFile.new(kitchen_root, instance_name(suite, platform)) end
Builds a newly configured Transport
object, for a given Suite
and Platform
.
@param suite [Suite,#name] a Suite
@param platform [Platform,#name] a Platform
@return [Transport] a new Transport
object @api private
# File lib/kitchen/config.rb, line 327 def new_transport(suite, platform) tdata = data.transport_data_for(suite.name, platform.name) Transport.for_plugin(tdata[:name], tdata) end
Builds a newly configured Verifier
object, for a given a Suite
and Platform
.
@param suite [Suite,#name] a Suite
@param platform [Platform,#name] a Platform
@return [Verifier] a new Verifier
object @api private
# File lib/kitchen/config.rb, line 339 def new_verifier(suite, platform) vdata = data.verifier_data_for(suite.name, platform.name) Verifier.for_plugin(vdata[:name], vdata) end