lib/beaker/dsl/helpers.rb in beaker-1.10.0 vs lib/beaker/dsl/helpers.rb in beaker-1.11.0
- old
+ new
@@ -11,10 +11,11 @@
# prepare the state of a test case.
#
# To mix this is into a class you need the following:
# * a method *hosts* that yields any hosts implementing
# {Beaker::Host}'s interface to act upon.
+ # * a method *options* that provides an options hash, see {Beaker::Options::OptionsHash}
# * a method *logger* that yields a logger implementing
# {Beaker::Logger}'s interface.
# * the module {Beaker::DSL::Roles} that provides access to the various hosts implementing
# {Beaker::Host}'s interface to act upon
# * the module {Beaker::DSL::Wrappers} the provides convenience methods for {Beaker::DSL::Command} creation
@@ -243,11 +244,11 @@
#
# @param [Host] host
# @param [String] path The path to the generated repository config
# files. ex: /myproject/pkg/repo_configs
# @param [String] name A human-readable name for the repository
- # @param [String[ version The version of the project, as used by the
+ # @param [String] version The version of the project, as used by the
# packaging tools. This can be determined with
# `rake pl:print_build_params` from the packaging
# repo.
def deploy_package_repo host, path, name, version
host.deploy_package_repo path, name, version
@@ -665,11 +666,11 @@
# command completion. If provided, these values will
# be combined with those used in :catch_failures and
# :expect_failures to create the full list of
# passing exit codes.
#
- # @options opts [Hash] :environment Additional environment variables to be
+ # @option opts [Hash] :environment Additional environment variables to be
# passed to the 'puppet apply' command
#
# @option opts [Boolean] :catch_failures (false) By default `puppet
# --apply` will exit with 0, which does not count
# as a test failure, even if there were errors or
@@ -696,10 +697,15 @@
# @option opts [Boolean] :future_parser (false) This option enables
# the future parser option that is available
# from Puppet verion 3.2
# By default it will use the 'current' parser.
#
+ # @option opts [String] :modulepath The search path for modules, as
+ # a list of directories separated by the system
+ # path separator character. (The POSIX path separator
+ # is ‘:’, and the Windows path separator is ‘;’.)
+ #
# @param [Block] block This method will yield to a block of code passed
# by the caller; this can be used for additional
# validation, etc.
#
def apply_manifest_on(host, manifest, opts = {}, &block)
@@ -714,10 +720,11 @@
args = ["--verbose"]
args << "--parseonly" if opts[:parseonly]
args << "--trace" if opts[:trace]
args << "--parser future" if opts[:future_parser]
+ args << "--modulepath #{opts[:modulepath]}" if opts[:modulepath]
# From puppet help:
# "... an exit code of '2' means there were changes, an exit code of
# '4' means there were failures during the transaction, and an exit
# code of '6' means there were both changes and failures."
@@ -858,22 +865,28 @@
#
# forge api v1 canonical source is forge.puppetlabs.com
# forge api v3 canonical source is forgeapi.puppetlabs.com
#
# @param machine [String] the host to perform the stub on
- def stub_forge_on(machine)
- @forge_ip ||= Resolv.getaddress(forge)
+ # @param forge_host [String] The URL to use as the forge alias, will default to using :forge_host in the
+ # global options hash
+ def stub_forge_on(machine, forge_host = nil)
+ #use global options hash
+ forge_host ||= options[:forge_host]
+ @forge_ip ||= Resolv.getaddress(forge_host)
stub_hosts_on(machine, 'forge.puppetlabs.com' => @forge_ip)
stub_hosts_on(machine, 'forgeapi.puppetlabs.com' => @forge_ip)
end
# This wraps the method `stub_hosts` and makes the stub specific to
# the forge alias.
#
# @see #stub_forge_on
- def stub_forge
- stub_forge_on(default)
+ def stub_forge(forge_host = nil)
+ #use global options hash
+ forge_host ||= options[:forge_host]
+ stub_forge_on(default, forge_host)
end
def sleep_until_puppetdb_started(host)
curl_with_retries("start puppetdb", host, "http://localhost:8080", 0, 120)
curl_with_retries("start puppetdb (ssl)",
@@ -1006,9 +1019,127 @@
else
on host, "curl %s" % cmd, opts, &block
end
end
+
+ #Install local module for acceptance testing
+ # should be used as a presuite to ensure local module is copied to the hosts you want, particularly masters
+ # @api dsl
+ # @param [Host, Array<Host>, String, Symbol] host
+ # One or more hosts to act upon,
+ # or a role (String or Symbol) that identifies one or more hosts.
+ # @option opts [String] :source ('./')
+ # The current directory where the module sits, otherwise will try
+ # and walk the tree to figure out
+ # @option opts [String] :module_name (nil)
+ # Name which the module should be installed under, please do not include author,
+ # if none is provided it will attempt to parse the metadata.json and then the Modulefile to determine
+ # the name of the module
+ # @option opts [String] :target_module_path (host['puppetpath']/modules)
+ # Location where the module should be installed, will default
+ # to host['puppetpath']/modules
+ # @raise [ArgumentError] if not host is provided or module_name is not provided and can not be found in Modulefile
+ #
+ def copy_root_module_to(host, opts = {})
+ if !host
+ raise(ArgumentError, "Host must be defined")
+ end
+ source = opts[:source] || parse_for_moduleroot(Dir.getwd)
+ target_module_path = opts[:target_module_path] || "#{host['puppetpath']}/modules"
+
+ module_name = opts[:module_name] || parse_for_modulename(source)
+ if !module_name
+ logger.debug('Still unable to determine the modulename')
+ raise(ArgumentError, "Unable to determine the module name, please update your call of puppet_module_install")
+ end
+
+ module_dir = File.join(target_module_path, module_name)
+ on host, "mkdir -p #{target_module_path}"
+ ['manifests', 'lib', 'templates', 'metadata.json', 'Modulefile', 'files', 'Gemfile'].each do |item|
+ item_source = File.join(source, item)
+ if File.exists? item_source
+ options = {}
+ if File.directory? item_source
+ on host, "mkdir -p #{File.join(module_dir, item)}"
+ options = { :mkdir => true }
+ end
+ host.do_scp_to(item_source, module_dir, options)
+ end
+ end
+ end
+
+
+ #Recursive method for finding the module root
+ # Assumes that a Modulefile exists
+ # @param [String] possible_module_directory
+ # will look for Modulefile and if none found go up one level and try again until root is reached
+ #
+ # @return [String,nil]
+ def parse_for_moduleroot(possible_module_directory)
+ if File.exists?("#{possible_module_directory}/Modulefile")
+ possible_module_directory
+ elsif possible_module_directory === '/'
+ logger.error "At root, can't parse for another directory"
+ nil
+ else
+ logger.debug "No Modulefile found at #{possible_module_directory}, moving up"
+ parse_for_moduleroot File.expand_path(File.join(possible_module_directory,'..'))
+ end
+ end
+
+
+ #Parse root directory of a module for module name
+ # Searches for metadata.json and then if none found, Modulefile and parses for the Name attribute
+ # @param [String] root_module_dir
+ # @return [String] module name
+ def parse_for_modulename(root_module_dir)
+ module_name = nil
+ if File.exists?("#{root_module_dir}/metadata.json")
+ logger.debug "Attempting to parse Modulename from metadata.json"
+ module_json = JSON.parse (File.read "#{root_module_dir}/metadata.json")
+ if(module_json.has_key?('name'))
+ module_name = get_module_name(module_json['name'])
+ end
+ end
+ if !module_name && File.exists?("#{root_module_dir}/Modulefile")
+ logger.debug "Attempting to parse Modulename from Modulefile"
+ if /^name\s+'?(\w+-\w+)'?\s*$/i.match(File.read("#{root_module_dir}/Modulefile"))
+ module_name = get_module_name(Regexp.last_match[1])
+ end
+ end
+ if !module_name
+ logger.debug "Unable to determine name, returning null"
+ end
+ module_name
+ end
+
+ #Parse modulename from the pattern 'Auther-ModuleName'
+ #
+ # @param [String] author_module_name <Author>-<ModuleName> pattern
+ #
+ # @return [String,nil]
+ #
+ def get_module_name(author_module_name)
+ split_name = split_author_modulename(author_module_name)
+ if split_name
+ split_name[:module]
+ end
+ end
+
+ #Split the Author-Name into a hash
+ # @param [String] author_module_attr
+ #
+ # @return [Hash<Symbol,String>,nil] :author and :module symbols will be returned
+ #
+ def split_author_modulename(author_module_attr)
+ result = /(\w+)-(\w+)/.match(author_module_attr)
+ if result
+ {:author => result[1], :module => result[2]}
+ else
+ nil
+ end
+ end
end
end
end