Module: Beaker::ModuleInstallHelper

Includes:
DSL
Defined in:
lib/beaker/module_install_helper.rb

Overview

Provides method for use in module test setup to install the module under test and it’s dependencies on the specified hosts

Instance Method Summary collapse

Instance Method Details

#forge_apiObject



191
192
193
194
195
196
197
198
199
200
# File 'lib/beaker/module_install_helper.rb', line 191

def forge_api
  fa = ENV['BEAKER_FORGE_API']
  unless fa.nil?
    fa = 'https://' + fa if fa !~ /^(https:\/\/|http:\/\/)/i
    fa += '/' unless fa != /\/$/
    return fa
  end

  'https://forgeapi.puppetlabs.com/'
end

#forge_hostObject



180
181
182
183
184
185
186
187
188
189
# File 'lib/beaker/module_install_helper.rb', line 180

def forge_host
  fh = ENV['BEAKER_FORGE_HOST']
  unless fh.nil?
    fh = 'https://' + fh if fh !~ /^(https:\/\/|http:\/\/)/i
    fh += '/' unless fh != /\/$/
    return fh
  end

  'https://forge.puppet.com/'
end

#get_module_source_directory(call_stack) ⇒ Object

Use this property to store the module_source_dir, so we don’t traverse the tree every time



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/beaker/module_install_helper.rb', line 158

def get_module_source_directory(call_stack)
  matching_caller = call_stack.select { |i| i =~ /(spec_helper_acceptance|_spec)/i }

  raise 'Error finding module source directory' if matching_caller.empty?

  matching_caller = matching_caller[0] if matching_caller.is_a?(Array)
  search_in = matching_caller[/[^:]+/]

  module_source_dir = nil
  # here we go up the file tree and search the directories for a
  # valid metadata.json
  while module_source_dir.nil? && search_in != File.dirname(search_in)
    # remove last segment (file or folder, doesn't matter)
    search_in = File.dirname(search_in)

    # Append metadata.json, check it exists in the directory we're searching
     = File.join(search_in, 'metadata.json')
    module_source_dir = search_in if File.exist?()
  end
  module_source_dir
end

#hosts_to_install_module_onObject

This method will return array of all masters. If no masters exist, it will return all agent nodes. If no nodes tagged master or agent exist, all nodes will be returned



128
129
130
131
132
133
134
135
136
# File 'lib/beaker/module_install_helper.rb', line 128

def hosts_to_install_module_on
  masters = hosts_with_role(hosts, :master)
  return masters unless masters.empty?

  agents = hosts_with_role(hosts, :agent)
  return agents unless agents.empty?

  hosts
end

#install_moduleObject

This method calls the install_module_on method for each host which is a master, or if no master is present, on all agent nodes.



10
11
12
# File 'lib/beaker/module_install_helper.rb', line 10

def install_module
  install_module_on hosts_to_install_module_on
end

#install_module_dependencies(deps = nil) ⇒ Object

This method calls the install_module_dependencies_on method for each host which is a master, or if no master is present, on all agent nodes.



24
25
26
# File 'lib/beaker/module_install_helper.rb', line 24

def install_module_dependencies(deps = nil)
  install_module_dependencies_on(hosts_to_install_module_on, deps)
end

#install_module_dependencies_on(hsts, deps = nil) ⇒ Object

This method will install the module under tests module dependencies on the specified host(s) from the dependencies list in metadata.json



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/beaker/module_install_helper.rb', line 30

def install_module_dependencies_on(hsts, deps = nil)
  hsts = [hsts] if hsts.is_a?(Hash)
  hsts = [hsts] unless hsts.respond_to?(:each)
  deps = deps.nil? ?  : deps

  fh = ENV['BEAKER_FORGE_HOST']

  hsts.each do |host|
    deps.each do |dep|
      if fh.nil?
        install_puppet_module_via_pmt_on(host, dep)
      else
        with_forge_stubbed_on(host) do
          install_puppet_module_via_pmt_on(host, dep)
        end
      end
    end
  end
end

#install_module_from_forge(mod_name, ver_req) ⇒ Object



50
51
52
# File 'lib/beaker/module_install_helper.rb', line 50

def install_module_from_forge(mod_name, ver_req)
  install_module_from_forge_on(hosts_to_install_module_on, mod_name, ver_req)
end

#install_module_from_forge_on(hsts, mod_name, ver_req) ⇒ Object



54
55
56
57
58
59
60
61
62
# File 'lib/beaker/module_install_helper.rb', line 54

def install_module_from_forge_on(hsts, mod_name, ver_req)
  mod_name.sub!('/', '-')
  dependency = {
    module_name: mod_name,
    version: module_version_from_requirement(mod_name, ver_req)
  }

  install_module_dependencies_on(hsts, [dependency])
end

#install_module_on(host) ⇒ Object

This method will install the module under test on the specified host(s) from the source on the local machine



16
17
18
19
20
# File 'lib/beaker/module_install_helper.rb', line 16

def install_module_on(host)
  copy_module_to(host,
                 source:      $module_source_dir,
                 module_name: )
end

#module_dependencies_from_metadataObject

This method returns an array of dependencies from the metadata.json file in the format of an array of hashes, containing :module_name and optionally :version elements. If no dependencies are specified, empty array is returned



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/beaker/module_install_helper.rb', line 67

def 
   = 
  return [] unless .key?('dependencies')

  dependencies = []
  ['dependencies'].each do |d|
    tmp = { module_name: d['name'].sub('/', '-') }

    if d.key?('version_requirement')
      tmp[:version] = module_version_from_requirement(tmp[:module_name],
                                                      d['version_requirement'])
    end
    dependencies.push(tmp)
  end

  dependencies
end

#module_metadataObject

This method uses the module_source_directory path to read the metadata.json file into a json array



148
149
150
151
152
153
154
# File 'lib/beaker/module_install_helper.rb', line 148

def 
   = "#{$module_source_dir}/metadata.json"
  unless File.exist?()
    raise "Error loading metadata.json file from #{$module_source_dir}"
  end
  JSON.parse(File.read())
end

#module_name_from_metadataObject

This method will read the ‘name’ attribute from metadata.json file and remove the first segment. E.g. puppetlabs-vcsrepo -> vcsrepo



140
141
142
143
144
# File 'lib/beaker/module_install_helper.rb', line 140

def 
  res = get_module_name ['name']
  raise 'Error getting module name' unless res
  res[1]
end

#module_version_from_requirement(mod_name, vr_str) ⇒ Object

This method takes a module name and the version requirement string from the metadata.json file, containing either lower bounds of version or both lower and upper bounds. The function then uses the forge rest endpoint to find the most recent release of the given module matching the version requirement



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/beaker/module_install_helper.rb', line 89

def module_version_from_requirement(mod_name, vr_str)
  require 'net/http'
  uri = URI("#{forge_api}v3/modules/#{mod_name}")
  response = Net::HTTP.get(uri)
  forge_data = JSON.parse(response)

  vrs = version_requirements_from_string(vr_str)

  # Here we iterate the releases of the given module and pick the most recent
  # that matches to version requirement
  forge_data['releases'].each do |rel|
    return rel['version'] if vrs.all? { |vr| vr.match?('', rel['version']) }
  end

  raise "No release version found matching '#{vr_str}'"
end

#version_requirements_from_string(vr_str) ⇒ Object

This method takes a version requirement string as specified in the link below, with either simply a lower bound, or both lower and upper bounds and returns an array of Gem::Dependency objects docs.puppet.com/puppet/latest/modules_metadata.html



110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/beaker/module_install_helper.rb', line 110

def version_requirements_from_string(vr_str)
  ops = vr_str.scan(/[(<|>|=)]{1,2}/i)
  vers = vr_str.scan(/[(0-9|\.)]+/i)

  raise 'Invalid version requirements' if ops.count != 0 &&
                                          ops.count != vers.count

  vrs = []
  ops.each_with_index do |op, index|
    vrs.push(Gem::Dependency.new('', "#{op} #{vers[index]}"))
  end

  vrs
end