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

Included in:
Beaker::DSL::InstallUtils
Defined in:
lib/beaker/dsl/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']

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



230
231
232
233
234
235
236
237
238
# File 'lib/beaker/dsl/install_utils/module_utils.rb', line 230

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



108
109
110
111
112
113
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
# File 'lib/beaker/dsl/install_utils/module_utils.rb', line 108

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)


203
204
205
206
207
208
# File 'lib/beaker/dsl/install_utils/module_utils.rb', line 203

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:



53
54
55
# File 'lib/beaker/dsl/install_utils/module_utils.rb', line 53

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
32
33
# File 'lib/beaker/dsl/install_utils/module_utils.rb', line 25

def install_dev_puppet_module_on( host, opts )
  if options[:forge_host]
    with_forge_stubbed_on( host ) do
      install_puppet_module_via_pmt_on( host, opts )
    end
  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



84
85
86
# File 'lib/beaker/dsl/install_utils/module_utils.rb', line 84

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



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/beaker/dsl/install_utils/module_utils.rb', line 63

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

    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



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/beaker/dsl/install_utils/module_utils.rb', line 176

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)


160
161
162
163
164
165
166
167
168
169
170
# File 'lib/beaker/dsl/install_utils/module_utils.rb', line 160

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



215
216
217
218
219
220
221
222
# File 'lib/beaker/dsl/install_utils/module_utils.rb', line 215

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