Module: Beaker::DSL::InstallUtils::ModuleUtils

Included in:
BeakerPuppet::InstallUtils
Defined in:
lib/beaker-puppet/install_utils/module_utils.rb

Overview

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 Host‘s interface to act upon.

  • a method options that provides an options hash, see Options::OptionsHash

  • the module Roles that provides access to the various hosts implementing Host‘s interface to act upon

  • the module Wrappers the provides convenience methods for Command creation

Constant Summary collapse

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`

['.bundle', '.git', '.idea', '.vagrant', '.vendor', 'vendor', 'acceptance',
'bundle', 'spec', 'tests', 'log', '.svn', 'junit', 'pkg', 'example']

Instance Method Summary collapse

Instance Method Details

#build_ignore_list(opts = {}) ⇒ Object

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

Parameters:

  • opts (Hash) (defaults to: {})

Options Hash (opts):

  • :ignore_list (Array)

    A list of files/directories to ignore



236
237
238
239
240
241
242
243
244
# File 'lib/beaker-puppet/install_utils/module_utils.rb', line 236

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

#copy_module_to(one_or_more_hosts, opts = {}) ⇒ Object Also known as: copy_root_module_to

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

Parameters:

  • one_or_more_hosts (Host, Array<Host>, String, Symbol)

    One or more hosts to act upon, or a role (String or Symbol) that identifies one or more hosts.

  • opts (Hash) (defaults to: {})

    a customizable set of options

Options Hash (opts):

  • :source (String) — default: './'

    The current directory where the module sits, otherwise will try

    and walk the tree to figure out
    
  • :module_name (String) — default: 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
    
  • :target_module_path (String) — default: host['distmoduledir']/modules

    Location where the module should be installed, will default

    to host['distmoduledir']/modules
    
  • :ignore_list (Array)
  • :protocol (String)

    Name of the underlying transfer method. Valid options are ‘scp’ or ‘rsync’.

Raises:

  • (ArgumentError)

    if not host is provided or module_name is not provided and can not be found in Modulefile



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# 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 = on( host, "echo #{opts[:target_module_path]}" ).stdout.chomp
    source_path = File.expand_path( opts[:source] )
    source_dir = File.dirname(source_path)
    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

#get_module_name(author_module_name) ⇒ String?

Parse modulename from the pattern ‘Auther-ModuleName’

Parameters:

  • author_module_name (String)

    <Author>-<ModuleName> pattern

Returns:

  • (String, nil)


209
210
211
212
213
214
# File 'lib/beaker-puppet/install_utils/module_utils.rb', line 209

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

#install_dev_puppet_module(opts) ⇒ Object Also known as: puppet_module_install

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`

Examples:

Installing a module from the local directory

install_dev_puppet_module( :source => './', :module_name => 'concat' )

Installing a module from a staging forge

options[:forge_host] = 'my-forge-api.example.com'
install_dev_puppet_module( :source => './', :module_name => 'concat' )

Parameters:

  • opts (Hash)

See Also:



51
52
53
# 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_dev_puppet_module_on(host, opts) ⇒ Object Also known as: puppet_module_install_on

Install the desired module on all hosts using either the PMT or a

staging forge


25
26
27
28
29
30
31
# 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_puppet_module_via_pmt(opts = {}) ⇒ Object

Install the desired module with the PMT on all known hosts



90
91
92
# 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_puppet_module_via_pmt_on(host, opts = {}) ⇒ Object

Install the desired module with the PMT on a given host

Parameters:

  • opts (Hash) (defaults to: {})

Options Hash (opts):

  • :module_name (String)

    The short name of the module to be installed

  • :version (String)

    The version of the module to be installed



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# 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_for_modulename(root_module_dir) ⇒ String

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

Parameters:

  • root_module_dir (String)

Returns:

  • (String)

    module name



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/beaker-puppet/install_utils/module_utils.rb', line 182

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

#parse_for_moduleroot(possible_module_directory) ⇒ String?

Recursive method for finding the module root Assumes that a Modulefile exists

Parameters:

  • possible_module_directory (String)

    will look for Modulefile and if none found go up one level and try again until root is reached

Returns:

  • (String, nil)


166
167
168
169
170
171
172
173
174
175
176
# File 'lib/beaker-puppet/install_utils/module_utils.rb', line 166

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

#split_author_modulename(author_module_attr) ⇒ Hash<Symbol,String>?

Split the Author-Name into a hash

Parameters:

  • author_module_attr (String)

Returns:

  • (Hash<Symbol,String>, nil)

    :author and :module symbols will be returned



221
222
223
224
225
226
227
228
# File 'lib/beaker-puppet/install_utils/module_utils.rb', line 221

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