module Beaker::DSL::InstallUtils::ModuleUtils
This module contains methods to help install puppet modules
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}
-
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
Constants
- PUPPET_MODULE_INSTALL_IGNORE
The directories in the module directory that will not be scp-ed to the test system when using `copy_module_to`
Public Instance Methods
Build an array list of files/directories to ignore when pushing to remote host Automatically adds '..' and '.' to array. If not opts of :ignore list is provided it will use the static variable PUPPET_MODULE_INSTALL_IGNORE
@param opts [Hash] @option opts [Array] :ignore_list A list of files/directories to ignore
# File lib/beaker-puppet/install_utils/module_utils.rb, line 245 def build_ignore_list(opts = {}) ignore_list = opts[:ignore_list] || PUPPET_MODULE_INSTALL_IGNORE if !ignore_list.kind_of?(Array) || ignore_list.nil? raise ArgumentError "Ignore list must be an Array" end ignore_list << '.' unless ignore_list.include? '.' ignore_list << '..' unless ignore_list.include? '..' ignore_list 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 @param [Host, Array<Host>, String, Symbol] one_or_more_hosts
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 Module file to determine the name of the module
@option opts [String] :target_module_path (host/modules)
Location where the module should be installed, will default to host['distmoduledir']/modules
@option opts [Array] :ignore_list @option opts [String] :protocol
Name of the underlying transfer method. Valid options are 'scp' or 'rsync'.
@raise [ArgumentError] if not host is provided or module_name is not provided and can not be found in Modulefile
# File lib/beaker-puppet/install_utils/module_utils.rb, line 114 def copy_module_to(one_or_more_hosts, opts = {}) block_on one_or_more_hosts do |host| opts = {:source => './', :target_module_path => host['distmoduledir'], :ignore_list => PUPPET_MODULE_INSTALL_IGNORE}.merge(opts) ignore_list = build_ignore_list(opts) target_module_dir = get_target_module_path(host, opts[:target_module_path]) source_path = File.expand_path( opts[:source] ) source_name = File.basename(source_path) if opts.has_key?(:module_name) module_name = opts[:module_name] else _, module_name = parse_for_modulename( source_path ) end target_path = File.join(target_module_dir, module_name) if host.is_powershell? #make sure our slashes are correct target_path = target_path.gsub(/\//,'\\') end opts[:protocol] ||= 'scp' case opts[:protocol] when 'scp' #move to the host logger.debug "Using scp to transfer #{source_path} to #{target_path}" scp_to host, source_path, target_module_dir, {:ignore => ignore_list} #rename to the selected module name, if not correct cur_path = File.join(target_module_dir, source_name) if host.is_powershell? #make sure our slashes are correct cur_path = cur_path.gsub(/\//,'\\') end host.mv cur_path, target_path unless cur_path == target_path when 'rsync' logger.debug "Using rsync to transfer #{source_path} to #{target_path}" rsync_to host, source_path, target_path, {:ignore => ignore_list} else logger.debug "Unsupported transfer protocol, returning nil" nil end end end
Parse modulename from the pattern 'Auther-ModuleName'
@param [String] author_module_name <Author>-<ModuleName> pattern @return [String,nil]
# File lib/beaker-puppet/install_utils/module_utils.rb, line 218 def get_module_name(author_module_name) split_name = split_author_modulename(author_module_name) if split_name return split_name[:author], split_name[:module] end end
# File lib/beaker-puppet/install_utils/module_utils.rb, line 159 def get_target_module_path(host, path=nil) if path on( host, "echo #{path}" ).stdout.chomp else path = host.puppet['basemodulepath'].split(':').first raise ArgumentError, 'Unable to find target module path to copy to' unless path path end end
Install the desired module on all hosts using either the PMT or a
staging forge
Passes options through to either `install_puppet_module_via_pmt_on`
or `copy_module_to`
@param opts [Hash]
@example Installing a module from the local directory
install_dev_puppet_module( :source => './', :module_name => 'concat' )
@example Installing a module from a staging forge
options[:forge_host] = 'my-forge-api.example.com' install_dev_puppet_module( :source => './', :module_name => 'concat' )
@see install_puppet_module_via_pmt
@see copy_module_to
# File lib/beaker-puppet/install_utils/module_utils.rb, line 51 def install_dev_puppet_module( opts ) block_on( hosts ) {|h| install_dev_puppet_module_on( h, opts ) } end
Install the desired module on all hosts using either the PMT or a
staging forge
@see install_dev_puppet_module
# File lib/beaker-puppet/install_utils/module_utils.rb, line 25 def install_dev_puppet_module_on( host, opts ) if options[:forge_host] install_puppet_module_via_pmt_on( host, opts ) else copy_module_to( host, opts ) end end
Install the desired module with the PMT on all known hosts @see install_puppet_module_via_pmt_on
# File lib/beaker-puppet/install_utils/module_utils.rb, line 90 def install_puppet_module_via_pmt( opts = {} ) install_puppet_module_via_pmt_on(hosts, opts) end
Install the desired module with the PMT on a given host
@param opts [Hash] @option opts [String] :module_name The short name of the module to be installed @option opts [String] :version The version of the module to be installed
# File lib/beaker-puppet/install_utils/module_utils.rb, line 61 def install_puppet_module_via_pmt_on( host, opts = {} ) block_on host do |h| version_info = opts[:version] ? "-v #{opts[:version]}" : "" if opts[:source] author_name, module_name = parse_for_modulename( opts[:source] ) modname = "#{author_name}-#{module_name}" else modname = opts[:module_name] end puppet_opts = {} if host[:default_module_install_opts].respond_to? :merge puppet_opts = host[:default_module_install_opts].merge( puppet_opts ) end if options[:forge_host] if options[:forge_host] =~ /^http/ puppet_opts[:module_repository] = options[:forge_host] else puppet_opts[:module_repository] = "https://#{options[:forge_host]}" end end on h, puppet("module install #{modname} #{version_info}", puppet_opts) 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
# File lib/beaker-puppet/install_utils/module_utils.rb, line 191 def parse_for_modulename(root_module_dir) author_name, module_name = nil, 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')) author_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")) author_name, module_name = get_module_name(Regexp.last_match[1]) end end if !module_name && !author_name logger.debug "Unable to determine name, returning null" end return author_name, module_name 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]
# File lib/beaker-puppet/install_utils/module_utils.rb, line 175 def parse_for_moduleroot(possible_module_directory) if File.exists?("#{possible_module_directory}/Modulefile") || File.exists?("#{possible_module_directory}/metadata.json") possible_module_directory elsif possible_module_directory === '/' logger.error "At root, can't parse for another directory" nil else logger.debug "No Modulefile or metadata.json found at #{possible_module_directory}, moving up" parse_for_moduleroot File.expand_path(File.join(possible_module_directory,'..')) end end