beaker-module_install_helper 0.1.7 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Rakefile CHANGED
@@ -1,11 +1,9 @@
1
- require 'bundler/gem_tasks'
2
- task default: %i[lint spec]
1
+ # frozen_string_literal: true
3
2
 
3
+ require 'bundler/gem_tasks'
4
4
  require 'rubocop/rake_task'
5
- desc 'Run rubocop'
6
- RuboCop::RakeTask.new(:lint) do |t|
7
- t.requires << 'rubocop-rspec'
8
- end
5
+
6
+ RuboCop::RakeTask.new
9
7
 
10
8
  require 'rspec/core/rake_task'
11
9
  desc 'Run spec tests using rspec'
@@ -13,3 +11,27 @@ RSpec::Core::RakeTask.new(:spec) do |t|
13
11
  t.rspec_opts = ['--color']
14
12
  t.pattern = 'spec'
15
13
  end
14
+
15
+ begin
16
+ require 'rubygems'
17
+ require 'github_changelog_generator/task'
18
+ rescue LoadError
19
+ # github_changelog_generator isn't available, so we won't define a rake task with it
20
+ else
21
+ GitHubChangelogGenerator::RakeTask.new :changelog do |config|
22
+ config.header = <<-HEADER
23
+ # Changelog
24
+
25
+ # All notable changes to this project will be documented in this file.
26
+ HEADER
27
+ config.exclude_labels = %w[duplicate question invalid wontfix wont-fix skip-changelog]
28
+ config.user = 'voxpupuli'
29
+ config.project = 'beaker-module_install_helper'
30
+ config.future_release = Gem::Specification.load("#{config.project}.gemspec").version
31
+ end
32
+ end
33
+
34
+ task default: %w[
35
+ rubocop
36
+ spec
37
+ ]
@@ -1,11 +1,13 @@
1
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
5
 
4
6
  Gem::Specification.new do |spec|
5
7
  spec.name = 'beaker-module_install_helper'
6
- spec.version = '0.1.7'
7
- spec.authors = ['Puppet']
8
- spec.email = ['wilson@puppet.com']
8
+ spec.version = '2.0.0'
9
+ spec.authors = ['Vox Pupuli']
10
+ spec.email = ['voxpupuli@groups.io']
9
11
 
10
12
  spec.summary = 'A helper gem for use in a Puppet Modules ' \
11
13
  'spec_helper_acceptance.rb file'
@@ -13,19 +15,22 @@ Gem::Specification.new do |spec|
13
15
  'spec_helper_acceptance.rb file to help install the ' \
14
16
  'module under test and its dependencies on the system ' \
15
17
  'under test'
16
- spec.homepage = 'https://github.com/puppetlabs/beaker-module_install_helper'
18
+ spec.homepage = 'https://github.com/voxpupuli/beaker-module_install_helper'
17
19
  spec.license = 'Apache-2.0'
18
20
 
19
21
  spec.files = `git ls-files`.split("\n")
20
- spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
- spec.executables = `git ls-files -- bin/*` \
22
- .split("\n") \
22
+ spec.executables = `git ls-files -- bin/*`
23
+ .split("\n")
23
24
  .map { |f| File.basename(f) }
24
25
  spec.require_paths = ['lib']
25
26
 
26
27
  ## Testing dependencies
27
- spec.add_development_dependency 'rspec'
28
+ spec.add_development_dependency 'rspec', '~> 3.12'
29
+ spec.add_development_dependency 'voxpupuli-rubocop', '~> 1.2'
28
30
 
29
31
  # Run time dependencies
30
- spec.add_runtime_dependency 'beaker', '>= 2.0'
32
+ spec.add_runtime_dependency 'beaker', '>= 2.0', '< 6'
33
+ spec.add_runtime_dependency 'beaker-puppet', '>= 1', '< 3'
34
+
35
+ spec.required_ruby_version = '>= 2.7.0'
31
36
  end
@@ -1,205 +1,216 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'beaker'
4
+ require 'beaker-puppet'
2
5
 
3
6
  # Provides method for use in module test setup to install the module under
4
7
  # test and it's dependencies on the specified hosts
5
- module Beaker::ModuleInstallHelper
6
- include Beaker::DSL
8
+ module Beaker
9
+ module ModuleInstallHelper
10
+ include Beaker::DSL
11
+
12
+ # This method calls the install_module_on method for each host which is a
13
+ # master, or if no master is present, on all agent nodes.
14
+ def install_module(opts = {})
15
+ install_module_on(hosts_to_install_module_on, opts)
16
+ end
7
17
 
8
- # This method calls the install_module_on method for each host which is a
9
- # master, or if no master is present, on all agent nodes.
10
- def install_module
11
- install_module_on hosts_to_install_module_on
12
- end
18
+ # This method will install the module under test on the specified host(s) from
19
+ # the source on the local machine
20
+ def install_module_on(host, opts = {})
21
+ opts = {
22
+ source: $module_source_dir,
23
+ module_name: module_name_from_metadata,
24
+ }.merge(opts)
25
+ copy_module_to(host, opts)
26
+ end
13
27
 
14
- # This method will install the module under test on the specified host(s) from
15
- # the source on the local machine
16
- def install_module_on(host)
17
- copy_module_to(host,
18
- source: $module_source_dir,
19
- module_name: module_name_from_metadata)
20
- end
28
+ # This method calls the install_module_dependencies_on method for each
29
+ # host which is a master, or if no master is present, on all agent nodes.
30
+ def install_module_dependencies(deps = nil)
31
+ install_module_dependencies_on(hosts_to_install_module_on, deps)
32
+ end
21
33
 
22
- # This method calls the install_module_dependencies_on method for each
23
- # host which is a master, or if no master is present, on all agent nodes.
24
- def install_module_dependencies(deps = nil)
25
- install_module_dependencies_on(hosts_to_install_module_on, deps)
26
- end
34
+ # This method will install the module under tests module dependencies on the
35
+ # specified host(s) from the dependencies list in metadata.json
36
+ def install_module_dependencies_on(hsts, deps = nil)
37
+ hsts = [hsts] if hsts.is_a?(Hash)
38
+ hsts = [hsts] unless hsts.respond_to?(:each)
39
+ deps = module_dependencies_from_metadata if deps.nil?
27
40
 
28
- # This method will install the module under tests module dependencies on the
29
- # specified host(s) from the dependencies list in metadata.json
30
- def install_module_dependencies_on(hsts, deps = nil)
31
- hsts = [hsts] if hsts.is_a?(Hash)
32
- hsts = [hsts] unless hsts.respond_to?(:each)
33
- deps = deps.nil? ? module_dependencies_from_metadata : deps
34
-
35
- fh = ENV['BEAKER_FORGE_HOST']
36
-
37
- hsts.each do |host|
38
- deps.each do |dep|
39
- if fh.nil?
40
- install_puppet_module_via_pmt_on(host, dep)
41
- else
42
- with_forge_stubbed_on(host) do
41
+ fh = ENV.fetch('BEAKER_FORGE_HOST', nil)
42
+
43
+ hsts.each do |host|
44
+ deps.each do |dep|
45
+ if fh.nil?
43
46
  install_puppet_module_via_pmt_on(host, dep)
47
+ else
48
+ with_forge_stubbed_on(host) do
49
+ install_puppet_module_via_pmt_on(host, dep)
50
+ end
44
51
  end
45
52
  end
46
53
  end
47
54
  end
48
- end
49
55
 
50
- def install_module_from_forge(mod_name, ver_req)
51
- install_module_from_forge_on(hosts_to_install_module_on, mod_name, ver_req)
52
- end
56
+ def install_module_from_forge(mod_name, ver_req)
57
+ install_module_from_forge_on(hosts_to_install_module_on, mod_name, ver_req)
58
+ end
53
59
 
54
- def install_module_from_forge_on(hsts, mod_name, ver_req)
55
- mod_name.sub!('/', '-')
56
- dependency = {
57
- module_name: mod_name,
58
- version: module_version_from_requirement(mod_name, ver_req)
59
- }
60
+ def install_module_from_forge_on(hsts, mod_name, ver_req)
61
+ sub_mod_name = mod_name.sub('/', '-')
62
+ dependency = {
63
+ module_name: sub_mod_name,
64
+ version: module_version_from_requirement(sub_mod_name, ver_req),
65
+ }
60
66
 
61
- install_module_dependencies_on(hsts, [dependency])
62
- end
67
+ install_module_dependencies_on(hsts, [dependency])
68
+ end
63
69
 
64
- # This method returns an array of dependencies from the metadata.json file
65
- # in the format of an array of hashes, containing :module_name and optionally
66
- # :version elements. If no dependencies are specified, empty array is returned
67
- def module_dependencies_from_metadata
68
- metadata = module_metadata
69
- return [] unless metadata.key?('dependencies')
70
+ # This method returns an array of dependencies from the metadata.json file
71
+ # in the format of an array of hashes, containing :module_name and optionally
72
+ # :version elements. If no dependencies are specified, empty array is returned
73
+ def module_dependencies_from_metadata
74
+ metadata = module_metadata
75
+ return [] unless metadata.key?('dependencies')
70
76
 
71
- dependencies = []
72
- metadata['dependencies'].each do |d|
73
- tmp = { module_name: d['name'].sub('/', '-') }
77
+ dependencies = []
78
+ metadata['dependencies'].each do |d|
79
+ tmp = { module_name: d['name'].sub('/', '-') }
74
80
 
75
- if d.key?('version_requirement')
76
- tmp[:version] = module_version_from_requirement(tmp[:module_name],
77
- d['version_requirement'])
81
+ if d.key?('version_requirement')
82
+ tmp[:version] = module_version_from_requirement(tmp[:module_name],
83
+ d['version_requirement'])
84
+ end
85
+ dependencies.push(tmp)
78
86
  end
79
- dependencies.push(tmp)
87
+
88
+ dependencies
80
89
  end
81
90
 
82
- dependencies
83
- end
91
+ # This method takes a module name and the version requirement string from the
92
+ # metadata.json file, containing either lower bounds of version or both lower
93
+ # and upper bounds. The function then uses the forge rest endpoint to find
94
+ # the most recent release of the given module matching the version requirement
95
+ def module_version_from_requirement(mod_name, vr_str)
96
+ require 'net/http'
97
+ uri = URI("#{forge_api}v3/modules/#{mod_name}")
98
+ response = Net::HTTP.get_response(uri)
99
+ raise "Puppetforge API error '#{uri}': '#{response.body}'" if response.code.to_i >= 400
100
+
101
+ forge_data = JSON.parse(response.body)
102
+
103
+ vrs = version_requirements_from_string(vr_str)
84
104
 
85
- # This method takes a module name and the version requirement string from the
86
- # metadata.json file, containing either lower bounds of version or both lower
87
- # and upper bounds. The function then uses the forge rest endpoint to find
88
- # the most recent release of the given module matching the version requirement
89
- def module_version_from_requirement(mod_name, vr_str)
90
- require 'net/http'
91
- uri = URI("#{forge_api}v3/modules/#{mod_name}")
92
- response = Net::HTTP.get(uri)
93
- forge_data = JSON.parse(response)
94
-
95
- vrs = version_requirements_from_string(vr_str)
96
-
97
- # Here we iterate the releases of the given module and pick the most recent
98
- # that matches to version requirement
99
- forge_data['releases'].each do |rel|
100
- return rel['version'] if vrs.all? { |vr| vr.match?('', rel['version']) }
105
+ # Here we iterate the releases of the given module and pick the most recent
106
+ # that matches to version requirement
107
+ forge_data['releases'].each do |rel|
108
+ return rel['version'] if vrs.all? { |vr| vr.match?('', rel['version']) }
109
+ end
110
+
111
+ raise "No release version found matching '#{mod_name}' '#{vr_str}'"
101
112
  end
102
113
 
103
- raise "No release version found matching '#{vr_str}'"
104
- end
114
+ # This method takes a version requirement string as specified in the link
115
+ # below, with either simply a lower bound, or both lower and upper bounds and
116
+ # returns an array of Gem::Dependency objects
117
+ # https://docs.puppet.com/puppet/latest/modules_metadata.html
118
+ def version_requirements_from_string(vr_str)
119
+ ops = vr_str.scan(/[(<|>=)]{1,2}/i)
120
+ vers = vr_str.scan(/[(0-9|.)]+/i)
105
121
 
106
- # This method takes a version requirement string as specified in the link
107
- # below, with either simply a lower bound, or both lower and upper bounds and
108
- # returns an array of Gem::Dependency objects
109
- # https://docs.puppet.com/puppet/latest/modules_metadata.html
110
- def version_requirements_from_string(vr_str)
111
- ops = vr_str.scan(/[(<|>|=)]{1,2}/i)
112
- vers = vr_str.scan(/[(0-9|\.)]+/i)
122
+ raise 'Invalid version requirements' if ops.count != 0 &&
123
+ ops.count != vers.count
113
124
 
114
- raise 'Invalid version requirements' if ops.count != 0 &&
115
- ops.count != vers.count
125
+ vrs = []
126
+ ops.each_with_index do |op, index|
127
+ vrs.push(Gem::Dependency.new('', "#{op} #{vers[index]}"))
128
+ end
116
129
 
117
- vrs = []
118
- ops.each_with_index do |op, index|
119
- vrs.push(Gem::Dependency.new('', "#{op} #{vers[index]}"))
130
+ vrs
120
131
  end
121
132
 
122
- vrs
123
- end
133
+ # This method will return array of all masters. If no masters exist, it will
134
+ # return all agent nodes. If no nodes tagged master or agent exist, all nodes
135
+ # will be returned
136
+ def hosts_to_install_module_on
137
+ masters = hosts_with_role(hosts, :master)
138
+ return masters unless masters.empty?
124
139
 
125
- # This method will return array of all masters. If no masters exist, it will
126
- # return all agent nodes. If no nodes tagged master or agent exist, all nodes
127
- # will be returned
128
- def hosts_to_install_module_on
129
- masters = hosts_with_role(hosts, :master)
130
- return masters unless masters.empty?
140
+ agents = hosts_with_role(hosts, :agent)
141
+ return agents unless agents.empty?
131
142
 
132
- agents = hosts_with_role(hosts, :agent)
133
- return agents unless agents.empty?
143
+ hosts
144
+ end
134
145
 
135
- hosts
136
- end
146
+ # This method will read the 'name' attribute from metadata.json file and
147
+ # remove the first segment. E.g. puppetlabs-vcsrepo -> vcsrepo
148
+ def module_name_from_metadata
149
+ res = get_module_name module_metadata['name']
150
+ raise 'Error getting module name' unless res
137
151
 
138
- # This method will read the 'name' attribute from metadata.json file and
139
- # remove the first segment. E.g. puppetlabs-vcsrepo -> vcsrepo
140
- def module_name_from_metadata
141
- res = get_module_name module_metadata['name']
142
- raise 'Error getting module name' unless res
143
- res[1]
144
- end
152
+ res[1]
153
+ end
145
154
 
146
- # This method uses the module_source_directory path to read the metadata.json
147
- # file into a json array
148
- def module_metadata
149
- metadata_path = "#{$module_source_dir}/metadata.json"
150
- unless File.exist?(metadata_path)
151
- raise "Error loading metadata.json file from #{$module_source_dir}"
155
+ # This method uses the module_source_directory path to read the metadata.json
156
+ # file into a json array
157
+ def module_metadata
158
+ metadata_path = "#{$module_source_dir}/metadata.json"
159
+ raise "Error loading metadata.json file from #{$module_source_dir}" unless File.exist?(metadata_path)
160
+
161
+ JSON.parse(File.read(metadata_path))
152
162
  end
153
- JSON.parse(File.read(metadata_path))
154
- end
155
163
 
156
- # Use this property to store the module_source_dir, so we don't traverse
157
- # the tree every time
158
- def get_module_source_directory(call_stack)
159
- matching_caller = call_stack.select { |i| i =~ /(spec_helper_acceptance|_spec)/i }
164
+ # Use this property to store the module_source_dir, so we don't traverse
165
+ # the tree every time
166
+ def get_module_source_directory(call_stack)
167
+ matching_caller = call_stack.grep(/(spec_helper_acceptance|_spec)/i)
160
168
 
161
- raise 'Error finding module source directory' if matching_caller.empty?
169
+ raise 'Error finding module source directory' if matching_caller.empty?
162
170
 
163
- matching_caller = matching_caller[0] if matching_caller.is_a?(Array)
164
- search_in = matching_caller[/[^:]+/]
171
+ matching_caller = matching_caller[0] if matching_caller.is_a?(Array)
172
+ search_in = matching_caller[/[^:]+/]
165
173
 
166
- module_source_dir = nil
167
- # here we go up the file tree and search the directories for a
168
- # valid metadata.json
169
- while module_source_dir.nil? && search_in != File.dirname(search_in)
170
- # remove last segment (file or folder, doesn't matter)
171
- search_in = File.dirname(search_in)
174
+ module_source_dir = nil
175
+ # here we go up the file tree and search the directories for a
176
+ # valid metadata.json
177
+ while module_source_dir.nil? && search_in != File.dirname(search_in)
178
+ # remove last segment (file or folder, doesn't matter)
179
+ search_in = File.dirname(search_in)
172
180
 
173
- # Append metadata.json, check it exists in the directory we're searching
174
- metadata_path = File.join(search_in, 'metadata.json')
175
- module_source_dir = search_in if File.exist?(metadata_path)
181
+ # Append metadata.json, check it exists in the directory we're searching
182
+ metadata_path = File.join(search_in, 'metadata.json')
183
+ module_source_dir = search_in if File.exist?(metadata_path)
184
+ end
185
+ module_source_dir
176
186
  end
177
- module_source_dir
178
- end
179
187
 
180
- def forge_host
181
- fh = ENV['BEAKER_FORGE_HOST']
182
- unless fh.nil?
183
- fh = 'https://' + fh if fh !~ /^(https:\/\/|http:\/\/)/i
184
- fh += '/' unless fh != /\/$/
185
- return fh
188
+ def forge_host
189
+ fh = ENV['BEAKER_FORGE_HOST'] # rubocop:disable Style/FetchEnvVar
190
+ unless fh.nil?
191
+ fh = "https://#{fh}" unless %r{^(https://|http://)}i.match?(fh)
192
+ fh += '/' unless fh != %r{/$}
193
+ return fh
194
+ end
195
+
196
+ 'https://forge.puppet.com/'
186
197
  end
187
198
 
188
- 'https://forge.puppet.com/'
189
- end
199
+ def forge_api
200
+ fa = ENV['BEAKER_FORGE_API'] # rubocop:disable Style/FetchEnvVar
201
+ unless fa.nil?
202
+ fa = "https://#{fa}" unless %r{^(https://|http://)}i.match?(fa)
203
+ fa += '/' unless fa != %r{/$}
204
+ return fa
205
+ end
190
206
 
191
- def forge_api
192
- fa = ENV['BEAKER_FORGE_API']
193
- unless fa.nil?
194
- fa = 'https://' + fa if fa !~ /^(https:\/\/|http:\/\/)/i
195
- fa += '/' unless fa != /\/$/
196
- return fa
207
+ 'https://forgeapi.puppetlabs.com/'
197
208
  end
198
-
199
- 'https://forgeapi.puppetlabs.com/'
200
209
  end
201
210
  end
202
211
 
212
+ # rubocop:disable Style/MixinUsage
203
213
  include Beaker::ModuleInstallHelper
214
+ # rubocop:enable Style/MixinUsage
204
215
  # Use the caller (requirer) of this file to begin search for module source dir
205
216
  $module_source_dir = get_module_source_directory caller
data/spec/spec_helper.rb CHANGED
@@ -1 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require 'simplecov'
5
+ require 'simplecov-console'
6
+ require 'codecov'
7
+ rescue LoadError
8
+ else
9
+ SimpleCov.start do
10
+ track_files 'lib/**/*.rb'
11
+
12
+ add_filter '/spec'
13
+
14
+ enable_coverage :branch
15
+
16
+ # do not track vendored files
17
+ add_filter '/vendor'
18
+ add_filter '/.vendor'
19
+ end
20
+
21
+ SimpleCov.formatters = [
22
+ SimpleCov::Formatter::Console,
23
+ SimpleCov::Formatter::Codecov,
24
+ ]
25
+ end
26
+
1
27
  require 'beaker/module_install_helper'