puppet_litmus 1.3.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9ccf17917e989f2e0396f8b0611dd22cdf714b1e72db8be39e44b796e29e6044
4
- data.tar.gz: fffb9cd11af3950794c48b23767e4990a278d4c9f2584497d432157b7c1cc031
3
+ metadata.gz: fb5f589532820aa9325ab3653f0f02868f0127feb8d18c7b129c64c4358ce2c3
4
+ data.tar.gz: 66246c52058e285899fd523803dd32a0e097c7eef34c15e5f7a3b7525f1b2775
5
5
  SHA512:
6
- metadata.gz: 11a2e60e31f2e4d830a1bb12ca1a872e184244852514913636edbc599489e8f5d3c94feb8c98d2166358ebba18a04e76daa4cefefda52c21cecc9306d6f18c1c
7
- data.tar.gz: 455dfdd8692055f23f79c916c0968cfd2a16d7ce7d13ea1c74b5ce8b8b83fa25ae346c4928b1fdb355cca1cdb18790beab89b57302d9f6b7f64c42bf4165c6fa
6
+ metadata.gz: 545df42c21e51cba530a74efd86d7275399190a1d3ebb5be20017eae10ac9d90ba71c92eb7c5a290dd5eed6221c955e83bcc539611d8bdcedda16d06ea61118c
7
+ data.tar.gz: fd36021b42b2d7ad2502c85394f767317f05561d37ab2bde05d38adf45d667cb045ea9c736b41518bd6dc5e54f48287069802a1e0253adebb6c4a0dbb77e36bc
data/README.md CHANGED
@@ -18,13 +18,9 @@ Litmus is a command line tool that allows you to run acceptance tests against Pu
18
18
  Litmus allows you to:
19
19
 
20
20
  - Provision targets to test against
21
-
22
21
  - Install a Puppet agent
23
-
24
22
  - Install a module
25
-
26
23
  - Run tests
27
-
28
24
  - Tear down the infrastructure
29
25
 
30
26
  Litmus also facilitates parallel test runs and running tests in isolation. Each step is standalone, allowing other operations between test runs, such as debugging or configuration updates on the test targets.
@@ -33,33 +29,49 @@ Install Litmus as a gem by running `gem install puppet_litmus`.
33
29
 
34
30
  - Note if you choose to override the `litmus_inventory.yaml` location, please ensure that the directory structure you define exists.
35
31
 
36
- ## matrix_from_metadata_v2
32
+ ## matrix_from_metadata_v3
37
33
 
38
- matrix_from_metadata_v2 tool generates a github action matrix from the supported operating systems listed in the module's metadata.json.
34
+ matrix_from_metadata_v3 tool generates a github action matrix from the supported operating systems listed in the module's metadata.json.
39
35
 
40
36
  How to use it:
41
- in the project module root directory run `bundle exec matrix_from_metadata_v2`
42
-
43
- ### --exclude-platforms parameter
44
-
45
- matrix_from_metadata_v2 accepts the `--exclude-platforms <JSON array>` argument in order to exclude some platforms from the matrix.
46
-
47
- For example:
48
-
49
- `$: bundle exec matrix_from_metadata_v2 --exclude-platforms '["debian-11","centos-8"]'`
50
-
51
- > Note: The option value should be JSON string otherwise it will throw an error.
52
- > The values provided in the json array are case-insensitive `["debian-11","centos-8"]'` or `["Debian-11","CentOS-8"]'` are treated as being the same.
53
-
54
- ### --custom-matrix parameter
55
-
56
- matrix_from_metadata_v2 accepts the `--custom-matrix /path/to/matrix.json` argument in order to execute your test suite against a custom matrix. This is useful for use cases that do not fit the default matrix generated.
57
-
58
- In order to use this new functionality, run:
59
-
60
- `$: bundle exec matrix_from_metadata_v2 --custom-matrix matrix.json`
61
-
62
- > Note: The file should contain a valid Array of JSON Objects (i.e. see [here](https://github.com/puppetlabs/puppet_litmus/blob/main/docs/custom_matrix.json)), otherwise it will throw an error.
37
+ in the project module root directory run `bundle exec matrix_from_metadata_v3`
38
+
39
+ ### Optional arguments
40
+
41
+ | argument | value | default | description |
42
+ |---------------------|-------|-------------------|-------------|
43
+ | --matrix | FILE | built-in | File containing possible collections and provisioners |
44
+ | --metadata | FILE | metadata.json | File containing module metadata json |
45
+ | --debug | | | Enable debug messages |
46
+ | --quiet | | | Disable notice messages |
47
+ | --output | TYPE | auto | Type of output to generate; auto, github or stdout |
48
+ | --runner | NAME | ubuntu-latest | Default Github action runner |
49
+ | --puppet-include | MAJOR | | Select puppet major version |
50
+ | --puppet-exclude | MAJOR | | Filter puppet major version |
51
+ | --platform-include | REGEX | | Select platform |
52
+ | --platform-exclude | REGEX | | Filter platform |
53
+ | --arch-include | REGEX | | Select architecture |
54
+ | --arch-exclude | REGEX | | Filter architecture |
55
+ | --provision-prefer | NAME | docker | Prefer provisioner |
56
+ | --provision-include | NAME | all | Select provisioner |
57
+ | --provision-exclude | NAME | provision_service | Filter provisioner |
58
+
59
+ > Refer to the [built-in matrix.json](https://github.com/puppetlabs/puppet_litmus/blob/main/exe/matrix.json) for a list of supported collection, provisioners, and platforms.
60
+
61
+ ### Examples
62
+
63
+ * Only specific platforms
64
+ ```sh
65
+ matrix_from_metadata_v3 --platform-include redhat --platform-include 'ubuntu-(20|22).04'
66
+ ```
67
+ * Exclude platforms
68
+ ```sh
69
+ matrix_from_metadata_v3 --platform-exclude redhat-7 --platform-exclude ubuntu-18.04
70
+ ```
71
+ * Exclude architecture
72
+ ```sh
73
+ matrix_from_metadata_v3 --arch-exclude x86_64
74
+ ```
63
75
 
64
76
  ## Documentation
65
77
 
data/exe/matrix.json ADDED
@@ -0,0 +1,94 @@
1
+ {
2
+ "collections": [
3
+ {
4
+ "puppet": 7.24,
5
+ "ruby": 2.7
6
+ },
7
+ {
8
+ "puppet": 8.0,
9
+ "ruby": 3.2
10
+ }
11
+ ],
12
+ "provisioners": {
13
+ "provision_service": {
14
+ "AlmaLinux": {
15
+ "8": { "x86_64": "almalinux-cloud/almalinux-8" },
16
+ "9": { "x86_64": "almalinux-cloud/almalinux-9" }
17
+ },
18
+ "CentOS": {
19
+ "7": { "x86_64": "centos-7" },
20
+ "8": { "x86_64": "centos-stream-8" },
21
+ "9": { "x86_64": "centos-stream-9" }
22
+ },
23
+ "Rocky": {
24
+ "8": { "x86_64": "rocky-linux-cloud/rocky-linux-8" },
25
+ "9": { "x86_64": "rocky-linux-cloud/rocky-linux-9" }
26
+ },
27
+ "Debian": {
28
+ "10": { "x86_64": "debian-10" },
29
+ "11": { "x86_64": "debian-11" },
30
+ "12": { "x86_64": "debian-12", "arm": "debian-12-arm64" }
31
+ },
32
+ "RedHat": {
33
+ "7": { "x86_64": "rhel-7" },
34
+ "8": { "x86_64": "rhel-8" },
35
+ "9": { "x86_64": "rhel-9", "arm": "rhel-9-arm64" }
36
+ },
37
+ "SLES" : {
38
+ "12": { "x86_64": "sles-12" },
39
+ "15": { "x86_64": "sles-15" }
40
+ },
41
+ "Ubuntu": {
42
+ "20.04": { "x86_64": "ubuntu-2004-lts" },
43
+ "22.04": { "x86_64": "ubuntu-2204-lts", "arm": "ubuntu-2204-lts-arm64" }
44
+ },
45
+ "Windows": {
46
+ "2016": { "x86_64": "windows-2016" },
47
+ "2019": { "x86_64": "windows-2019" },
48
+ "2022": { "x86_64": "windows-2022" }
49
+ }
50
+ },
51
+ "docker": {
52
+ "AmazonLinux": {
53
+ "2": { "x86_64": "litmusimage/amazonlinux:2" },
54
+ "2023": { "x86_64": "litmusimage/amazonlinux:2023" }
55
+ },
56
+ "CentOS": {
57
+ "7": { "x86_64": "litmusimage/centos:7" },
58
+ "8": { "x86_64": "litmusimage/centos:stream8" },
59
+ "9": { "x86_64": "litmusimage/centos:stream9" }
60
+ },
61
+ "Rocky": {
62
+ "8": { "x86_64": "litmusimage/rockylinux:8" },
63
+ "9": { "x86_64": "litmusimage/rockylinux:9" }
64
+ },
65
+ "AlmaLinux": {
66
+ "8": { "x86_64": "litmusimage/almalinux:8" },
67
+ "9": { "x86_64": "litmusimage/almalinux:9" }
68
+ },
69
+ "Debian": {
70
+ "10": { "x86_64": "litmusimage/debian:10" },
71
+ "11": { "x86_64": "litmusimage/debian:11" },
72
+ "12": { "x86_64": "litmusimage/debian:12" }
73
+ },
74
+ "OracleLinux": {
75
+ "7": { "x86_64": "litmusimage/oraclelinux:7" },
76
+ "8": { "x86_64": "litmusimage/oraclelinux:8" },
77
+ "9": { "x86_64": "litmusimage/oraclelinux:9" }
78
+ },
79
+ "Scientific": {
80
+ "7": { "x86_64": "litmusimage/scientificlinux:7" }
81
+ },
82
+ "Ubuntu": {
83
+ "18.04": { "x86_64": "litmusimage/ubuntu:18.04" },
84
+ "20.04": { "x86_64": "litmusimage/ubuntu:20.04" },
85
+ "22.04": { "x86_64": "litmusimage/ubuntu:22.04" }
86
+ }
87
+ }
88
+ },
89
+ "github_runner": {
90
+ "docker": {
91
+ "^(AmazonLinux-2|(CentOS|OracleLinux|Scientific)-7|Ubuntu-18|Debian-10)": "ubuntu-20.04"
92
+ }
93
+ }
94
+ }
@@ -37,7 +37,6 @@ IMAGE_TABLE = {
37
37
  }.freeze
38
38
 
39
39
  DOCKER_PLATFORMS = [
40
- 'CentOS-6',
41
40
  'CentOS-7',
42
41
  'CentOS-8',
43
42
  'Debian-10',
@@ -36,27 +36,28 @@ IMAGE_TABLE = {
36
36
  }.freeze
37
37
 
38
38
  ARM_IMAGE_TABLE = {
39
+ 'Debian-12-arm' => 'debian-12-arm64',
39
40
  'RedHat-9-arm' => 'rhel-9-arm64',
40
41
  'Ubuntu-22.04-arm' => 'ubuntu-2204-lts-arm64'
41
42
  }.freeze
42
43
 
43
44
  DOCKER_PLATFORMS = {
44
- 'CentOS-6' => 'litmusimage/centos:6',
45
+ 'AmazonLinux-2' => 'litmusimage/amazonlinux:2',
46
+ 'AmazonLinux-2023' => 'litmusimage/amazonlinux:2023',
45
47
  'CentOS-7' => 'litmusimage/centos:7',
46
48
  'CentOS-8' => 'litmusimage/centos:stream8', # Support officaly moved to Stream8, metadata is being left as is
49
+ 'CentOS-9' => 'litmusimage/centos:stream9',
47
50
  'Rocky-8' => 'litmusimage/rockylinux:8',
51
+ 'Rocky-9' => 'litmusimage/rockylinux:9',
48
52
  'AlmaLinux-8' => 'litmusimage/almalinux:8',
49
- # 'Debian-8' => 'litmusimage/debian:8', Removing from testing: https://puppet.com/docs/pe/2021.0/supported_operating_systems.html
50
- 'Debian-9' => 'litmusimage/debian:9',
53
+ 'AlmaLinux-9' => 'litmusimage/almalinux:9',
51
54
  'Debian-10' => 'litmusimage/debian:10',
52
55
  'Debian-11' => 'litmusimage/debian:11',
53
56
  'Debian-12' => 'litmusimage/debian:12',
54
- 'OracleLinux-6' => 'litmusimage/oraclelinux:6',
55
57
  'OracleLinux-7' => 'litmusimage/oraclelinux:7',
56
- 'Scientific-6' => 'litmusimage/scientificlinux:6',
58
+ 'OracleLinux-8' => 'litmusimage/oraclelinux:8',
59
+ 'OracleLinux-9' => 'litmusimage/oraclelinux:9',
57
60
  'Scientific-7' => 'litmusimage/scientificlinux:7',
58
- # 'Ubuntu-14.04' => 'litmusimage/ubuntu:14.04', Removing from testing: https://puppet.com/docs/pe/2021.0/supported_operating_systems.html
59
- # 'Ubuntu-16.04' => 'litmusimage/ubuntu:16.04', Support Dropped
60
61
  'Ubuntu-18.04' => 'litmusimage/ubuntu:18.04',
61
62
  'Ubuntu-20.04' => 'litmusimage/ubuntu:20.04',
62
63
  'Ubuntu-22.04' => 'litmusimage/ubuntu:22.04'
@@ -108,11 +109,15 @@ if ARGV.include?('--provision-service')
108
109
  # NOTE: that the below are the only available images for the provision service
109
110
  updated_platforms = {
110
111
  'AlmaLinux-8' => 'almalinux-cloud/almalinux-8',
112
+ 'AlmaLinux-9' => 'almalinux-cloud/almalinux-9',
111
113
  'CentOS-7' => 'centos-7',
112
114
  'CentOS-8' => 'centos-stream-8',
115
+ 'CentOS-9' => 'centos-stream-9',
113
116
  'Rocky-8' => 'rocky-linux-cloud/rocky-linux-8',
117
+ 'Rocky-9' => 'rocky-linux-cloud/rocky-linux-9',
114
118
  'Debian-10' => 'debian-10',
115
119
  'Debian-11' => 'debian-11',
120
+ 'Debian-12' => 'debian-12',
116
121
  'Ubuntu-20.04' => 'ubuntu-2004-lts',
117
122
  'Ubuntu-22.04' => 'ubuntu-2204-lts'
118
123
  }
@@ -123,6 +128,12 @@ if ARGV.include?('--provision-service')
123
128
  DOCKER_PLATFORMS = {}.freeze
124
129
  end
125
130
 
131
+ # disable provision service if repository owner is not puppetlabs
132
+ unless ['puppetlabs', nil].include?(ENV.fetch('GITHUB_REPOSITORY_OWNER', nil))
133
+ IMAGE_TABLE = {}.freeze
134
+ ARM_IMAGE_TABLE = {}.freeze
135
+ end
136
+
126
137
  metadata_path = ENV['TEST_MATRIX_FROM_METADATA'] || 'metadata.json'
127
138
  metadata = JSON.parse(File.read(metadata_path))
128
139
 
@@ -0,0 +1,314 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'English'
5
+ require 'json'
6
+ require 'optparse'
7
+ require 'ostruct'
8
+
9
+ # wrap up running in a Github Action
10
+ module Action
11
+ class << self
12
+ attr_reader :type
13
+
14
+ def init(to = 'auto')
15
+ @notice = true
16
+ @type = if to.eql? 'auto'
17
+ ENV['GITHUB_ACTIONS'] ? 'github' : 'stdout'
18
+ else
19
+ to
20
+ end
21
+ $stderr = $stdout if @type == 'github'
22
+ end
23
+
24
+ def config(**args)
25
+ error("invalid Action.config: #{args}") unless args.is_a?(Hash)
26
+ args.each do |arg|
27
+ instance_variable_set(:"@#{arg[0]}", arg[1])
28
+ end
29
+ end
30
+
31
+ def debug(msg = nil)
32
+ return @debug if msg.nil?
33
+
34
+ output(msg, '::debug::') if @debug
35
+ end
36
+
37
+ def notice(msg = nil)
38
+ return @notice if msg.nil?
39
+
40
+ output(msg, '::notice::') if @notice
41
+ end
42
+
43
+ def error(msg)
44
+ output(msg, '::error::')
45
+ exit 1
46
+ end
47
+
48
+ def warning(msg)
49
+ output(msg, '::warning::')
50
+ end
51
+
52
+ def group(name, data, **kwargs)
53
+ output(name, '::group::')
54
+ output(data, **kwargs)
55
+ output('', '::endgroup::') if @type == 'github'
56
+
57
+ self
58
+ end
59
+
60
+ def set_output(key, value)
61
+ @output ||= @type == 'github' ? ENV.fetch('GITHUB_OUTPUT', nil) : '/dev/stdout'
62
+
63
+ if @output.nil?
64
+ Action.warning('GITHUB_OUTPUT environment is not set, sending output to stdout')
65
+ @output = '/dev/stdout'
66
+ end
67
+
68
+ File.open(@output, 'a') { |f| f.puts "#{key}=#{JSON.generate(value)}" }
69
+
70
+ self
71
+ end
72
+
73
+ private
74
+
75
+ def output(msg, prefix = nil, pretty: false)
76
+ $stderr.print prefix if @type == 'github'
77
+ $stderr.puts pretty ? JSON.pretty_generate(msg) : msg.to_s
78
+
79
+ self
80
+ end
81
+ end
82
+ end
83
+
84
+ options = OpenStruct.new(
85
+ puppet_exclude: [],
86
+ puppet_include: [],
87
+ platform_exclude: [],
88
+ platform_include: [],
89
+ arch_include: [],
90
+ arch_exclude: [],
91
+ provision_prefer: [],
92
+ provision_include: [],
93
+ provision_exclude: []
94
+ )
95
+
96
+ default_options = {
97
+ 'provision-prefer': 'docker',
98
+ runner: 'ubuntu-latest',
99
+ output: 'auto',
100
+ matrix: File.join(File.dirname(__FILE__), 'matrix.json'),
101
+ metadata: 'metadata.json'
102
+ }
103
+
104
+ begin
105
+ Action.init
106
+
107
+ # default disable provision_service if puppetlabs is not the owner
108
+ default_options[:'provision-exclude'] = 'provision_service' \
109
+ if ARGV.reject! { |x| x == '--puppetlabs' }.nil? && !['puppetlabs'].include?(ENV.fetch('GITHUB_REPOSITORY_OWNER', nil))
110
+
111
+ # apply default_options if not overridden on the command line
112
+ default_options.each do |arg, value|
113
+ ARGV.unshift("--#{arg}", value) unless ARGV.grep(/\A--#{arg}(=.*)?\z/).any?
114
+ end
115
+
116
+ OptionParser.accept(JSON) do |v|
117
+ begin
118
+ x = JSON.parse(File.read(v)) if v
119
+ raise "nothing parsed from file #{v}" if x.empty?
120
+
121
+ x
122
+ rescue JSON::ParserError
123
+ raise "error parsing file #{v}"
124
+ end
125
+ rescue RuntimeError, Errno::ENOENT
126
+ raise OptionParser::InvalidArgument, $ERROR_INFO unless ARGV.grep(/^-(h|help)$/).any?
127
+ end
128
+
129
+ OutputType = ->(value) {}
130
+ OptionParser.accept(OutputType) do |v|
131
+ raise OptionParser::InvalidArgument, v \
132
+ unless %w[auto github stdout].include?(v)
133
+
134
+ Action.init(v)
135
+ end
136
+
137
+ OptionParser.accept(Regexp) { |v| Regexp.new(v, Regexp::IGNORECASE) }
138
+
139
+ OptionParser.new do |opt|
140
+ opt.separator "Generate Github Actions Matrices from Puppet metadata.json\n\nOptions:"
141
+ opt.on('--matrix FILE', JSON, 'File containing possible collections and provisioners (default: built-in)') { |o| options.matrix = o }
142
+ opt.on('--metadata FILE', JSON, "File containing module metadata json (default: #{default_options[:metadata]})\n\n") { |o| options.metadata = o }
143
+
144
+ opt.on('--debug', TrueClass, 'Enable debug messages') { |o| options.debug = o }
145
+ opt.on('--quiet', TrueClass, 'Disable notice messages') { |o| options.quiet = o }
146
+ opt.on('--output TYPE', OutputType, "Type of output to generate; auto, github or stdout (default: #{default_options[:output]})\n\n") { |o| options.output = o }
147
+
148
+ opt.on('--runner NAME', String, "Default Github action runner (default: #{default_options[:runner]})") { |o| options.runner = o }
149
+
150
+ opt.on('--puppet-include MAJOR', Integer, 'Select puppet major version') { |o| options.puppet_include << o }
151
+ opt.on('--puppet-exclude MAJOR', Integer, 'Filter puppet major version') { |o| options.puppet_exclude << o }
152
+
153
+ opt.on('--platform-include REGEX', Regexp, 'Select platform') { |o| options.platform_include << o }
154
+ opt.on('--platform-exclude REGEX', Regexp, 'Filter platform') { |o| options.platform_exclude << o }
155
+
156
+ opt.on('--arch-include REGEX', Regexp, 'Select architecture') { |o| options.arch_include << o }
157
+ opt.on('--arch-exclude REGEX', Regexp, 'Filter architecture') { |o| options.arch_exclude << o }
158
+
159
+ opt.on('--provision-prefer NAME', String, "Prefer provisioner (default: #{default_options[:'provision-prefer']})") { |o| options.provision_prefer.push(*o.split(',')) }
160
+ opt.on('--provision-include NAME', String, 'Select provisioner (default: all)') { |o| options.provision_include.push(*o.split(',')) }
161
+ opt.on('--provision-exclude NAME', String, "Filter provisioner (default: #{default_options[:'provision-exclude'] || 'none'})") { |o| options.provision_exclude.push(*o.split(',')) }
162
+ end.parse!
163
+
164
+ Action.config(debug: true) if options[:debug]
165
+ Action.config(notice: false) if options[:quiet] && !options[:debug]
166
+
167
+ # validate provisioners
168
+ options[:provision_include].select! do |p|
169
+ options[:matrix]['provisioners'].key?(p) or raise OptionParser::InvalidArgument, "--provision-include '#{p}' not found in provisioners"
170
+ end
171
+
172
+ # filter provisioners
173
+ unless options[:provision_include].empty?
174
+ options[:matrix]['provisioners'].delete_if do |k, _|
175
+ unless options[:provision_include].include?(k.to_s)
176
+ Action.debug("provision-include filtered #{k}")
177
+ true
178
+ end
179
+ end
180
+ end
181
+ options[:matrix]['provisioners'].delete_if do |k, _|
182
+ if options[:provision_exclude].include?(k.to_s)
183
+ Action.debug("provision-exclude filtered #{k}")
184
+ true
185
+ end
186
+ end
187
+
188
+ # sort provisioners
189
+ options[:matrix]['provisioners'] = options[:matrix]['provisioners'].sort_by { |key, _| options[:provision_prefer].index(key.to_s) || options[:provision_prefer].length }.to_h \
190
+ unless options[:provision_prefer].empty?
191
+
192
+ # union regexp option values
193
+ %w[platform arch].each do |c|
194
+ [:"#{c}_exclude", :"#{c}_include"].each do |k|
195
+ options[k] = if options[k].empty?
196
+ nil
197
+ else
198
+ Regexp.new(format('\A(?:%s)\z', Regexp.union(options[k])), Regexp::IGNORECASE)
199
+ end
200
+ end
201
+ end
202
+
203
+ raise OptionParser::ParseError, 'no provisioners left after filters applied' if options[:matrix]['provisioners'].empty?
204
+ rescue OptionParser::ParseError => e
205
+ Action.error(e)
206
+ end
207
+
208
+ matrix = { platforms: [], collection: [] }
209
+ spec_matrix = { include: [] }
210
+
211
+ # collection matrix
212
+ version_re = /([>=<]{1,2})\s*([\d.]+)/
213
+ options[:metadata]['requirements']&.each do |req|
214
+ next unless req['name'] == 'puppet' && req['version_requirement']
215
+
216
+ puppet_version_reqs = req['version_requirement'].scan(version_re).map(&:join)
217
+ if puppet_version_reqs.empty?
218
+ Action.warning("Didn't recognize version_requirement '#{req['version_requirement']}'")
219
+ break
220
+ end
221
+
222
+ options[:matrix]['collections'].each do |collection|
223
+ next unless options[:puppet_include].each do |major|
224
+ break if major != collection['puppet'].to_i
225
+
226
+ Action.debug("puppet-include matched collection #{collection.inspect}")
227
+ end
228
+
229
+ next unless options[:puppet_exclude].each do |major|
230
+ if major.eql? collection['puppet'].to_i
231
+ Action.debug("puppet-exclude matched collection #{collection.inspect}")
232
+ break
233
+ end
234
+ end
235
+
236
+ # Test against the "largest" puppet version in a collection, e.g. `7.9999` to allow puppet requirements with a non-zero lower bound on minor/patch versions.
237
+ # This assumes that such a boundary will always allow the latest actually existing puppet version of a release stream, trading off simplicity vs accuracy here.
238
+ gem_req = Gem::Requirement.create(puppet_version_reqs)
239
+ next unless gem_req.satisfied_by?(Gem::Version.new("#{collection['puppet'].to_i}.9999"))
240
+
241
+ matrix[:collection] << "puppet#{collection['puppet'].to_i}-nightly"
242
+
243
+ spec_matrix[:include] << {
244
+ puppet_version: "~> #{collection['puppet']}",
245
+ ruby_version: collection['ruby']
246
+ }
247
+ end
248
+ end
249
+
250
+ # Set platforms based on declared operating system support
251
+ options[:metadata]['operatingsystem_support'].each do |os_sup|
252
+ os_sup['operatingsystemrelease'].sort_by(&:to_i).each do |os_ver|
253
+ os_ver_platforms = []
254
+ platform_key = [os_sup['operatingsystem'], os_ver]
255
+
256
+ # filter platforms
257
+ if options[:platform_include] && platform_key[0].match?(options[:platform_include]) == false && platform_key.join('-').match?(options[:platform_include]) == false
258
+ Action.notice("platform-include filtered #{platform_key.join('-')}")
259
+ next
260
+ end
261
+
262
+ if options[:platform_exclude] && (platform_key[0].match?(options[:platform_exclude]) || platform_key.join('-').match?(options[:platform_exclude]))
263
+ Action.notice("platform-exclude filtered #{platform_key.join('-')}")
264
+ next
265
+ end
266
+
267
+ options[:matrix]['provisioners'].each do |provisioner, platforms|
268
+ images = platforms.dig(*platform_key)
269
+ next if images.nil?
270
+
271
+ # filter arch
272
+ images.delete_if do |arch, _|
273
+ next if options[:arch_include]&.match?(arch.downcase) == true
274
+ next unless options[:arch_exclude]&.match?(arch.downcase)
275
+
276
+ Action.notice("arch filtered #{platform_key.join('-')}-#{arch} from #{provisioner}")
277
+ end
278
+ next if images.empty?
279
+
280
+ images.each do |arch, image|
281
+ label = (arch.eql?('x86_64') ? platform_key : platform_key + [arch]).join('-')
282
+ next if os_ver_platforms.any? { |h| h[:label] == label }
283
+
284
+ runner = options[:matrix]['github_runner'][provisioner]&.reduce(options[:runner]) do |memo, (reg, run)|
285
+ label.match?(/#{reg}/i) ? run : memo
286
+ end
287
+
288
+ os_ver_platforms << {
289
+ label: label,
290
+ provider: provisioner,
291
+ arch: arch,
292
+ image: image,
293
+ runner: runner.nil? ? options[:runner] : runner
294
+ }
295
+ end
296
+ end
297
+
298
+ if os_ver_platforms.empty?
299
+ Action.warning("#{platform_key.join('-')} no provisioner found")
300
+ else
301
+ matrix[:platforms].push(*os_ver_platforms)
302
+ end
303
+ end
304
+ end
305
+
306
+ Action.group('matrix', matrix, pretty: true).group('spec_matrix', spec_matrix, pretty: true) if Action.type == 'github' && Action.notice
307
+
308
+ Action.error('no supported puppet versions') if matrix[:collection].empty?
309
+
310
+ if Action.type == 'stdout'
311
+ $stdout.puts JSON.generate({ matrix: matrix, spec_matrix: spec_matrix })
312
+ else
313
+ Action.set_output('matrix', matrix).set_output('spec_matrix', spec_matrix)
314
+ end
@@ -10,11 +10,7 @@ module PuppetLitmus::InventoryManipulation
10
10
  # @return [Hash] hash of the litmus_inventory.yaml file.
11
11
  def inventory_hash_from_inventory_file(inventory_full_path = nil)
12
12
  require 'yaml'
13
- inventory_full_path = if inventory_full_path.nil?
14
- "#{Dir.pwd}/spec/fixtures/litmus_inventory.yaml"
15
- else
16
- inventory_full_path
17
- end
13
+ inventory_full_path = "#{Dir.pwd}/spec/fixtures/litmus_inventory.yaml" if inventory_full_path.nil?
18
14
  raise "There is no inventory file at '#{inventory_full_path}'." unless File.exist?(inventory_full_path)
19
15
 
20
16
  YAML.load_file(inventory_full_path)
@@ -103,7 +99,7 @@ module PuppetLitmus::InventoryManipulation
103
99
  output_collector = []
104
100
  targets_in_inventory(inventory) do |target|
105
101
  vars = target['vars']
106
- roles = [(vars['role'] || vars['roles'])].flatten
102
+ roles = [vars['role'] || vars['roles']].flatten
107
103
  roles = roles.map(&:downcase)
108
104
  output_collector << target['uri'] if roles.include? role.downcase
109
105
  end
@@ -7,7 +7,7 @@ require 'puppet_litmus/version'
7
7
  module PuppetLitmus::RakeHelper
8
8
  # DEFAULT_CONFIG_DATA should be frozen for our safety, but it needs to work around https://github.com/puppetlabs/bolt/pull/1696
9
9
  DEFAULT_CONFIG_DATA = { 'modulepath' => File.join(Dir.pwd, 'spec', 'fixtures', 'modules') } # .freeze # rubocop:disable Style/MutableConstant
10
- SUPPORTED_PROVISIONERS = %w[abs docker docker_exp provision_service vagrant vmpooler].freeze
10
+ SUPPORTED_PROVISIONERS = %w[abs docker docker_exp lxd provision_service vagrant vmpooler].freeze
11
11
 
12
12
  # Gets a string representing the operating system and version.
13
13
  #
@@ -68,7 +68,7 @@ module PuppetLitmus::RakeHelper
68
68
  raise "the provision module was not found in #{DEFAULT_CONFIG_DATA['modulepath']}, please amend the .fixtures.yml file" unless
69
69
  File.directory?(File.join(DEFAULT_CONFIG_DATA['modulepath'], 'provision'))
70
70
 
71
- params = { 'action' => 'provision', 'platform' => platform, 'inventory' => Dir.pwd }
71
+ params = { 'action' => 'provision', 'platform' => platform, 'inventory' => File.join(Dir.pwd, 'spec', 'fixtures', 'litmus_inventory.yaml') }
72
72
  params['vars'] = inventory_vars unless inventory_vars.nil?
73
73
 
74
74
  task_name = provisioner_task(provisioner)
@@ -83,12 +83,9 @@ module PuppetLitmus::RakeHelper
83
83
  inventory_vars = provision_hash[key]['vars']
84
84
  # Splat the params into environment variables to pass to the provision task but only in this runspace
85
85
  provision_hash[key]['params']&.each { |k, value| ENV[k.upcase] = value.to_s }
86
- results = []
87
-
88
- provision_hash[key]['images'].each do |image|
89
- results << provision(provisioner, image, inventory_vars)
86
+ provision_hash[key]['images'].map do |image|
87
+ provision(provisioner, image, inventory_vars)
90
88
  end
91
- results
92
89
  end
93
90
 
94
91
  def tear_down_nodes(targets, inventory_hash)
@@ -123,7 +120,7 @@ module PuppetLitmus::RakeHelper
123
120
  # how do we know what provisioner to use
124
121
  add_platform_field(inventory_hash, node_name)
125
122
 
126
- params = { 'action' => 'tear_down', 'node_name' => node_name, 'inventory' => Dir.pwd }
123
+ params = { 'action' => 'tear_down', 'node_name' => node_name, 'inventory' => File.join(Dir.pwd, 'spec', 'fixtures', 'litmus_inventory.yaml') }
127
124
  node_facts = facts_from_node(inventory_hash, node_name)
128
125
  bolt_result = run_task(provisioner_task(node_facts['provisioner']), 'localhost', params, config: DEFAULT_CONFIG_DATA, inventory: nil)
129
126
  raise_bolt_errors(bolt_result, "tear_down of #{node_name} failed.")
@@ -160,11 +157,11 @@ module PuppetLitmus::RakeHelper
160
157
  def configure_path(inventory_hash)
161
158
  results = []
162
159
  # fix the path on ssh_nodes
163
- unless inventory_hash['groups'].select { |group| group['name'] == 'ssh_nodes' && !group['targets'].empty? }.empty?
160
+ unless inventory_hash['groups'].none? { |group| group['name'] == 'ssh_nodes' && !group['targets'].empty? }
164
161
  results << run_command('echo PATH="$PATH:/opt/puppetlabs/puppet/bin" > /etc/environment',
165
162
  'ssh_nodes', config: nil, inventory: inventory_hash)
166
163
  end
167
- unless inventory_hash['groups'].select { |group| group['name'] == 'winrm_nodes' && !group['targets'].empty? }.empty?
164
+ unless inventory_hash['groups'].none? { |group| group['name'] == 'winrm_nodes' && !group['targets'].empty? }
168
165
  results << run_command('[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\Program Files\Puppet Labs\Puppet\bin;C:\Program Files (x86)\Puppet Labs\Puppet\bin", "Machine")',
169
166
  'winrm_nodes', config: nil, inventory: inventory_hash)
170
167
  end