lib/kitchen/configurable.rb in test-kitchen-1.3.1 vs lib/kitchen/configurable.rb in test-kitchen-1.4.0.beta.1
- old
+ new
@@ -51,10 +51,11 @@
end
@instance = instance
expand_paths!
validate_config!
+ load_needed_dependencies!
self
end
# Provides hash-like access to configuration keys.
@@ -63,10 +64,16 @@
# @return [Object] value at configuration key
def [](attr)
config[attr]
end
+ # @return [TrueClass,FalseClass] true if `:shell_type` is `"bourne"` (or
+ # unset, for backwards compatability)
+ def bourne_shell?
+ ["bourne", nil].include?(instance.platform.shell_type)
+ end
+
# Find an appropriate path to a file or directory, based on graceful
# fallback rules or returns nil if path cannot be determined.
#
# Given an instance with suite named `"server"`, a `test_base_path` of
# `"/a/b"`, and a path segement of `"roles"` then following will be tried
@@ -115,10 +122,52 @@
result = Hash.new
config_keys.sort.each { |k| result[k] = config[k] }
result
end
+ # Returns the name of this plugin, suitable for display in a CLI.
+ #
+ # @return [String] name of this plugin
+ def name
+ self.class.name.split("::").last
+ end
+
+ # @return [TrueClass,FalseClass] true if `:shell_type` is `"powershell"`
+ def powershell_shell?
+ ["powershell"].include?(instance.platform.shell_type)
+ end
+
+ # Builds a file path based on the `:os_type` (`"windows"` or `"unix"`).
+ #
+ # @return [String] joined path for instance's os_type
+ def remote_path_join(*parts)
+ path = File.join(*parts)
+ windows_os? ? path.gsub("/", "\\") : path.gsub("\\", "/")
+ end
+
+ # @return [TrueClass,FalseClass] true if `:os_type` is `"unix"` (or
+ # unset, for backwards compatibility)
+ def unix_os?
+ ["unix", nil].include?(instance.platform.os_type)
+ end
+
+ # Performs whatever tests that may be required to ensure that this plugin
+ # will be able to function in the current environment. This may involve
+ # checking for the presence of certain directories, software installed,
+ # etc.
+ #
+ # @raise [UserError] if the plugin will not be able to perform or if a
+ # documented dependency is missing from the system
+ def verify_dependencies
+ # this method may be left unimplemented if that is applicable
+ end
+
+ # @return [TrueClass,FalseClass] true if `:os_type` is `"windows"`
+ def windows_os?
+ ["windows"].include?(instance.platform.os_type)
+ end
+
private
# @return [LzayHash] a configuration hash
# @api private
attr_reader :config
@@ -146,22 +195,109 @@
expanded_paths = LazyHash.new(self.class.expanded_paths, self).to_hash
expanded_paths.each do |key, should_expand|
next if !should_expand || config[key].nil?
- config[key] = File.expand_path(config[key], root_path)
+ config[key] = if config[key].is_a?(Array)
+ config[key].map { |path| File.expand_path(path, root_path) }
+ else
+ File.expand_path(config[key], root_path)
+ end
end
end
+ # Loads any required third party Ruby libraries or runs any shell out
+ # commands to prepare the plugin. This method will be called in the
+ # context of the main thread of execution and so does not necessarily
+ # have to be thread safe.
+ #
+ # **Note:** any subclasses overriding this method would be well advised
+ # to call super when overriding this method, for example:
+ #
+ # @example overriding `#load_needed_dependencies!`
+ #
+ # class MyProvisioner < Kitchen::Provisioner::Base
+ # def load_needed_dependencies!
+ # super
+ # # any further work
+ # end
+ # end
+ #
+ # @raise [ClientError] if any library loading fails or any of the
+ # dependency requirements cannot be satisfied
+ # @api private
+ def load_needed_dependencies!
+ # this method may be left unimplemented if that is applicable
+ end
+
+ # @return [Logger] the instance's logger or Test Kitchen's common logger
+ # otherwise
+ # @api private
+ def logger
+ instance ? instance.logger : Kitchen.logger
+ end
+
+ # Builds a shell environment variable assignment string for the
+ # required shell type.
+ #
+ # @param name [String] variable name
+ # @param value [String] variable value
+ # @return [String] shell variable assignment
+ # @api private
+ def shell_env_var(name, value)
+ if powershell_shell?
+ shell_var("env:#{name}", value)
+ else
+ "#{shell_var(name, value)}; export #{name}"
+ end
+ end
+
+ # Builds a shell variable assignment string for the required shell type.
+ #
+ # @param name [String] variable name
+ # @param value [String] variable value
+ # @return [String] shell variable assignment
+ # @api private
+ def shell_var(name, value)
+ if powershell_shell?
+ %{$#{name} = "#{value}"}
+ else
+ %{#{name}="#{value}"}
+ end
+ end
+
# Runs all validations set up for the included class. Each validation is
# for a specific configuration attribute and has an associated callable
# block. Each validation block is called with the attribute, its value,
# and the included object for context.
#
# @api private
def validate_config!
self.class.validations.each do |attr, block|
block.call(attr, config[attr], self)
+ end
+ end
+
+ # Wraps a body of shell code with common context appropriate for the type
+ # of shell.
+ #
+ # @param code [String] the shell code to be wrapped
+ # @return [String] wrapped shell code
+ # @api private
+ def wrap_shell_code(code)
+ env = []
+ if config[:http_proxy]
+ env << shell_env_var("http_proxy", config[:http_proxy])
+ env << shell_env_var("HTTP_PROXY", config[:http_proxy])
+ end
+ if config[:https_proxy]
+ env << shell_env_var("https_proxy", config[:https_proxy])
+ env << shell_env_var("HTTPS_PROXY", config[:https_proxy])
+ end
+ if powershell_shell?
+ env.join("\n").concat("\n").concat(code)
+ else
+ Util.wrap_command(env.join("\n").concat("\n").concat(code))
end
end
# Class methods which will be mixed in on inclusion of Configurable module.
module ClassMethods