beaker-module_install_helper 0.1.7 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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'