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