puppet_litmus 0.27.0 → 0.31.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +30 -8
- data/exe/matrix_from_metadata_v2 +28 -5
- data/lib/puppet_litmus/inventory_manipulation.rb +121 -23
- data/lib/puppet_litmus/puppet_helpers.rb +63 -27
- data/lib/puppet_litmus/rake_helper.rb +1 -1
- data/lib/puppet_litmus/version.rb +1 -1
- data/spec/exe/fake_metadata.json +46 -0
- data/spec/exe/matrix_from_metadata_v2_spec.rb +95 -0
- data/spec/lib/puppet_litmus/inventory_manipulation_spec.rb +69 -87
- data/spec/lib/puppet_litmus/puppet_helpers_spec.rb +39 -22
- data/spec/spec_helper.rb +13 -0
- data/spec/support/inventory.rb +130 -0
- data/spec/support/inventorytesting.yaml +41 -0
- metadata +14 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 80914970290db5501971ee324794c82101f204d1c78a74cbd618547f8fb345c0
|
4
|
+
data.tar.gz: 596c114a8c75fb36f6ab8350850eca9005036fbdf12ed7d3465e2375c937579e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eef1f207558172836438bc1bb5686610af52560bd7eb99ae2ff9ae332fa3705f249587dd4eb4f12c4ffd83c0011d03764dd6fa974b21be4012144829d984a429
|
7
|
+
data.tar.gz: 57d962b1ea4e49fd483319514197f5b1d119ab9b69e981c2e3a17f151b71358477b6a7276bbee3101f3d0a5f1d00a0cb081de953dfbf750e1ba6d53016836f58
|
data/README.md
CHANGED
@@ -12,17 +12,39 @@
|
|
12
12
|
Litmus is a command line tool that allows you to run acceptance tests against Puppet modules.
|
13
13
|
|
14
14
|
Litmus allows you to:
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
|
16
|
+
- Provision targets to test against
|
17
|
+
|
18
|
+
- Install a Puppet agent
|
19
|
+
|
20
|
+
- Install a module
|
21
|
+
|
22
|
+
- Run tests
|
23
|
+
|
24
|
+
- Tear down the infrastructure
|
20
25
|
|
21
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.
|
22
27
|
|
23
|
-
Install Litmus as a gem by running
|
28
|
+
Install Litmus as a gem by running `gem install puppet_litmus`.
|
29
|
+
|
30
|
+
- Note if you choose to override the `litmus_inventory.yaml` location, please ensure that the directory strutcture you define exists.
|
31
|
+
|
32
|
+
## matrix_from_metadata_v2
|
33
|
+
|
34
|
+
matrix_from_metadata_v2 tool generates github actions matrix from metadata.json
|
35
|
+
|
36
|
+
How to use it: in the project module root directory run `bundle exec matrix_from_metadata_v2`
|
37
|
+
|
38
|
+
### --exclude-platforms parameter
|
39
|
+
|
40
|
+
matrix_from_metadata_v2 accepts `--exclude-platforms <JSON array>` option in order to exclude some platforms from GA matrixes.
|
41
|
+
|
42
|
+
In order to use this new functionality just simply run:
|
43
|
+
|
44
|
+
`$: bundle exec matrix_from_metadata_v2 --exclude-platforms '["debian-11","centos-8"]'`
|
24
45
|
|
25
|
-
|
46
|
+
> Note: The option value should be JSON string otherwise it will throw an error.
|
47
|
+
> 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.
|
26
48
|
|
27
49
|
## Documentation
|
28
50
|
|
@@ -30,4 +52,4 @@ For documentation, see our [Litmus Docs Site](https://puppetlabs.github.io/litmu
|
|
30
52
|
|
31
53
|
## Other Resources
|
32
54
|
|
33
|
-
|
55
|
+
- [Is it Worth the Time?](https://xkcd.com/1205/)
|
data/exe/matrix_from_metadata_v2
CHANGED
@@ -13,15 +13,19 @@ IMAGE_TABLE = {
|
|
13
13
|
'Windows-2012 R2' => 'windows-2012-r2-core',
|
14
14
|
'Windows-2016' => 'windows-2016',
|
15
15
|
'Windows-2019' => 'windows-2019-core',
|
16
|
+
'Windows-2022' => 'windows-2022',
|
16
17
|
}.freeze
|
17
18
|
|
18
19
|
DOCKER_PLATFORMS = {
|
19
20
|
'CentOS-6' => 'litmusimage/centos:6',
|
20
21
|
'CentOS-7' => 'litmusimage/centos:7',
|
21
22
|
'CentOS-8' => 'litmusimage/centos:8',
|
22
|
-
'
|
23
|
+
'Rocky-8' => 'litmusimage/rockylinux:8',
|
24
|
+
'AlmaLinux-8' => 'litmusimage/almalinux:8',
|
23
25
|
# 'Debian-8' => 'litmusimage/debian:8', Removing from testing: https://puppet.com/docs/pe/2021.0/supported_operating_systems.html
|
24
26
|
'Debian-9' => 'litmusimage/debian:9',
|
27
|
+
'Debian-10' => 'litmusimage/debian:10',
|
28
|
+
'Debian-11' => 'litmusimage/debian:11',
|
25
29
|
'OracleLinux-6' => 'litmusimage/oraclelinux:6',
|
26
30
|
'OracleLinux-7' => 'litmusimage/oraclelinux:7',
|
27
31
|
'Scientific-6' => 'litmusimage/scientificlinux:6',
|
@@ -54,26 +58,45 @@ spec_matrix = {
|
|
54
58
|
include: [],
|
55
59
|
}
|
56
60
|
|
57
|
-
|
61
|
+
if ARGV.include?('--exclude-platforms')
|
62
|
+
exclude_platforms_occurencies = ARGV.select { |arg| arg == '--exclude-platforms' }.length
|
63
|
+
raise '--exclude-platforms argument should be present just one time in the command' unless exclude_platforms_occurencies <= 1
|
64
|
+
|
65
|
+
exclude_platforms_list = ARGV[ARGV.find_index('--exclude-platforms') + 1]
|
66
|
+
raise 'you need to provide a list of platforms in JSON format' if exclude_platforms_list.nil?
|
67
|
+
|
68
|
+
begin
|
69
|
+
exclude_list = JSON.parse(exclude_platforms_list).map { |platform| platform.downcase }
|
70
|
+
rescue JSON::ParserError
|
71
|
+
raise 'the exclude platforms list must valid JSON'
|
72
|
+
end
|
73
|
+
else
|
74
|
+
exclude_list = []
|
75
|
+
end
|
76
|
+
|
77
|
+
metadata_path = ENV['TEST_MATRIX_FROM_METADATA'] || 'metadata.json'
|
78
|
+
metadata = JSON.parse(File.read(metadata_path))
|
58
79
|
# Set platforms based on declared operating system support
|
59
80
|
metadata['operatingsystem_support'].sort_by { |a| a['operatingsystem'] }.each do |sup|
|
60
81
|
os = sup['operatingsystem']
|
61
82
|
sup['operatingsystemrelease'].sort_by { |a| a.to_i }.each do |ver|
|
62
83
|
image_key = "#{os}-#{ver}"
|
63
|
-
|
84
|
+
|
85
|
+
if IMAGE_TABLE.key?(image_key) && !exclude_list.include?(image_key.downcase)
|
64
86
|
matrix[:platforms] << {
|
65
87
|
label: image_key,
|
66
88
|
provider: 'provision::provision_service',
|
67
89
|
image: IMAGE_TABLE[image_key],
|
68
90
|
}
|
69
|
-
elsif DOCKER_PLATFORMS.key? image_key
|
91
|
+
elsif DOCKER_PLATFORMS.key?(image_key) && !exclude_list.include?(image_key.downcase)
|
70
92
|
matrix[:platforms] << {
|
71
93
|
label: image_key,
|
72
94
|
provider: 'provision::docker',
|
73
95
|
image: DOCKER_PLATFORMS[image_key],
|
74
96
|
}
|
75
97
|
else
|
76
|
-
puts "::warning
|
98
|
+
puts "::warning::#{image_key} was excluded from testing" if exclude_list.include?(image_key.downcase)
|
99
|
+
puts "::warning::Cannot find image for #{image_key}" unless exclude_list.include?(image_key.downcase)
|
77
100
|
end
|
78
101
|
end
|
79
102
|
end
|
@@ -6,8 +6,8 @@ module PuppetLitmus; end # rubocop:disable Style/Documentation
|
|
6
6
|
module PuppetLitmus::InventoryManipulation
|
7
7
|
# Creates an inventory hash from the inventory.yaml.
|
8
8
|
#
|
9
|
-
# @param inventory_full_path [String] path to the
|
10
|
-
# @return [Hash] hash of the
|
9
|
+
# @param inventory_full_path [String] path to the litmus_inventory.yaml file
|
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
13
|
inventory_full_path = if inventory_full_path.nil?
|
@@ -53,6 +53,85 @@ module PuppetLitmus::InventoryManipulation
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
+
# Recursively find and iterate over the groups in an inventory. If no block is passed
|
57
|
+
# to the function then only the name of the group is returned. If a block is passed
|
58
|
+
# then the block is executed against each group and the value of the block is returned.
|
59
|
+
#
|
60
|
+
# @param inventory_hash [Hash] Inventory hash from inventory.yaml
|
61
|
+
# @param block [Block] Block to execute against each node
|
62
|
+
def groups_in_inventory(inventory_hash, &block)
|
63
|
+
inventory_hash['groups'].flat_map do |group|
|
64
|
+
output_collector = []
|
65
|
+
output_collector << if block_given?
|
66
|
+
yield group
|
67
|
+
else
|
68
|
+
group['name'].downcase
|
69
|
+
end
|
70
|
+
output_collector << groups_in_inventory({ 'groups' => group['groups'] }, &block) if group.key? 'groups'
|
71
|
+
output_collector.flatten.compact
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Iterate over all targets in an inventory. If no block is given to the function
|
76
|
+
# it will return the name of every target in the inventory. If a block is passed
|
77
|
+
# it will execute the block on each target and return the value of the block.
|
78
|
+
#
|
79
|
+
# @param inventory_hash [Hash] Inventory hash from inventory.yaml
|
80
|
+
# @param block [Block] Block to execute against each node
|
81
|
+
def targets_in_inventory(inventory_hash)
|
82
|
+
groups_in_inventory(inventory_hash) do |group|
|
83
|
+
if group.key? 'targets'
|
84
|
+
group['targets'].map do |target|
|
85
|
+
if block_given?
|
86
|
+
(yield target)
|
87
|
+
else
|
88
|
+
target['uri'].downcase
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Find all targets in an inventory that have a role. The roles for a target are
|
96
|
+
# specified in the vars hash for a target. This function is tolerant to the roles
|
97
|
+
# hash being called either 'role' or 'roles' and it is tolerant to the roles being
|
98
|
+
# either a single key value or an array of roles.
|
99
|
+
#
|
100
|
+
# @param role [String] The name of a role to search for
|
101
|
+
# @param inventory [Hash] Inventory hash from inventory.yaml
|
102
|
+
def nodes_with_role(role, inventory)
|
103
|
+
output_collector = []
|
104
|
+
targets_in_inventory(inventory) do |target|
|
105
|
+
vars = target['vars']
|
106
|
+
roles = [(vars['role'] || vars['roles'])].flatten
|
107
|
+
roles = roles.map { |r| r.downcase }
|
108
|
+
output_collector << target['uri'] if roles.include? role.downcase
|
109
|
+
end
|
110
|
+
output_collector unless output_collector.empty?
|
111
|
+
end
|
112
|
+
|
113
|
+
# Searches through the inventory hash to either validate that a group being targeted exists,
|
114
|
+
# validate that a specific target being targeted exists, or resolves role names to a
|
115
|
+
# list of nodes to target. Targets and roles can be specified as strings or as symbols, and
|
116
|
+
# the functions are tolerant to incorrect capitalization.
|
117
|
+
#
|
118
|
+
# @param target [String] || [Array[String]] A list of targets
|
119
|
+
# @param inventory [Hash] inventory hash from inventory.yaml
|
120
|
+
def search_for_target(target, inventory)
|
121
|
+
result_collector = []
|
122
|
+
groups = groups_in_inventory(inventory)
|
123
|
+
Array(target).map do |name|
|
124
|
+
result_collector << name if groups.include? name.to_s.downcase
|
125
|
+
result_collector << name if targets_in_inventory(inventory).include? name.to_s.downcase
|
126
|
+
result_collector << nodes_with_role(name.to_s, inventory)
|
127
|
+
end
|
128
|
+
|
129
|
+
result_collector = result_collector.flatten.compact
|
130
|
+
raise 'targets not found in inventory' if result_collector.empty?
|
131
|
+
|
132
|
+
result_collector
|
133
|
+
end
|
134
|
+
|
56
135
|
# Determines if a node_name exists in a group in the inventory_hash.
|
57
136
|
#
|
58
137
|
# @param inventory_hash [Hash] hash of the inventory.yaml file
|
@@ -86,14 +165,13 @@ module PuppetLitmus::InventoryManipulation
|
|
86
165
|
# @param node_name [String] node to locate in the group
|
87
166
|
# @return [Hash] config for node of name node_name
|
88
167
|
def config_from_node(inventory_hash, node_name)
|
89
|
-
inventory_hash
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
end
|
94
|
-
end
|
168
|
+
config = targets_in_inventory(inventory_hash) do |target|
|
169
|
+
next unless target['uri'].downcase == node_name.downcase
|
170
|
+
|
171
|
+
return target['config'] unless target['config'].nil?
|
95
172
|
end
|
96
|
-
|
173
|
+
|
174
|
+
config.empty? ? nil : config[0]
|
97
175
|
end
|
98
176
|
|
99
177
|
# Finds a facts hash in the inventory hash by searching for a node name.
|
@@ -102,14 +180,13 @@ module PuppetLitmus::InventoryManipulation
|
|
102
180
|
# @param node_name [String] node to locate in the group
|
103
181
|
# @return [Hash] facts for node of name node_name
|
104
182
|
def facts_from_node(inventory_hash, node_name)
|
105
|
-
inventory_hash
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
end
|
110
|
-
end
|
183
|
+
facts = targets_in_inventory(inventory_hash) do |target|
|
184
|
+
next unless target['uri'].downcase == node_name.downcase
|
185
|
+
|
186
|
+
target['facts'] unless target['facts'].nil?
|
111
187
|
end
|
112
|
-
|
188
|
+
|
189
|
+
facts.empty? ? nil : facts[0]
|
113
190
|
end
|
114
191
|
|
115
192
|
# Finds a var hash in the inventory hash by searching for a node name.
|
@@ -118,14 +195,12 @@ module PuppetLitmus::InventoryManipulation
|
|
118
195
|
# @param node_name [String] node to locate in the group
|
119
196
|
# @return [Hash] vars for node of name node_name
|
120
197
|
def vars_from_node(inventory_hash, node_name)
|
121
|
-
inventory_hash
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
end
|
126
|
-
end
|
198
|
+
vars = targets_in_inventory(inventory_hash) do |target|
|
199
|
+
next unless target['uri'].downcase == node_name.downcase
|
200
|
+
|
201
|
+
target['vars'] unless target['vars'].nil?
|
127
202
|
end
|
128
|
-
{}
|
203
|
+
vars.empty? ? {} : vars[0]
|
129
204
|
end
|
130
205
|
|
131
206
|
# Adds a node to a group specified, if group_name exists in inventory hash.
|
@@ -266,4 +341,27 @@ module PuppetLitmus::InventoryManipulation
|
|
266
341
|
end
|
267
342
|
Honeycomb.current_span.add_field('litmus.platform', facts&.dig('platform'))
|
268
343
|
end
|
344
|
+
|
345
|
+
# Add platform custom information field to the current span for each node being targeted.
|
346
|
+
# If more than one node is being targeted, each node will be given a separate custom field.
|
347
|
+
#
|
348
|
+
# @param span [Honeycomb::Span] The current span
|
349
|
+
# @param target_node_names [Array[String]] Nodes being targeted
|
350
|
+
# @param inventory_hash [Hash] Hash of the inventory.yaml file
|
351
|
+
def add_node_fields_to_span(span, target_node_names, inventory_hash)
|
352
|
+
node_counter = 1
|
353
|
+
Array(target_node_names).each do |target_name|
|
354
|
+
name_field = 'litmus.node_name'
|
355
|
+
platform_field = 'litmus.platform'
|
356
|
+
|
357
|
+
name_field = "#{name_field}_#{node_counter}"
|
358
|
+
platform_field = "#{platform_field}_#{node_counter}"
|
359
|
+
span.add_field(name_field, target_name)
|
360
|
+
if target_in_inventory?(inventory_hash, target_name)
|
361
|
+
facts = facts_from_node(inventory_hash, target_name)
|
362
|
+
span.add_field(platform_field, facts&.dig('platform')) unless facts.nil?
|
363
|
+
end
|
364
|
+
node_counter += 1
|
365
|
+
end
|
366
|
+
end
|
269
367
|
end
|
@@ -6,13 +6,24 @@ module PuppetLitmus::PuppetHelpers
|
|
6
6
|
# Applies a manifest twice. First checking for errors. Secondly to make sure no changes occur.
|
7
7
|
#
|
8
8
|
# @param manifest [String] puppet manifest code to be applied.
|
9
|
+
# @param opts [Hash] Alters the behaviour of the command. Valid options are:
|
10
|
+
# :catch_changes [Boolean] (false) We're after idempotency so allow exit code 0 only.
|
11
|
+
# :expect_changes [Boolean] (false) We're after changes specifically so allow exit code 2 only.
|
12
|
+
# :catch_failures [Boolean] (false) We're after only complete success so allow exit codes 0 and 2 only.
|
13
|
+
# :expect_failures [Boolean] (false) We're after failures specifically so allow exit codes 1, 4, and 6 only.
|
14
|
+
# :manifest_file_location [Path] The place on the target system.
|
15
|
+
# :hiera_config [Path] The path to the hiera.yaml configuration on the target.
|
16
|
+
# :prefix_command [String] prefixes the puppet apply command; eg "export LANGUAGE='ja'".
|
17
|
+
# :trace [Boolean] run puppet apply with the trace flag (defaults to `true`).
|
18
|
+
# :debug [Boolean] run puppet apply with the debug flag.
|
19
|
+
# :noop [Boolean] run puppet apply with the noop flag.
|
9
20
|
# @return [Boolean] The result of the 2 apply manifests.
|
10
|
-
def idempotent_apply(manifest)
|
21
|
+
def idempotent_apply(manifest, opts = {})
|
11
22
|
Honeycomb.start_span(name: 'litmus.idempotent_apply') do |span|
|
12
23
|
ENV['HONEYCOMB_TRACE'] = span.to_trace_header
|
13
24
|
manifest_file_location = create_manifest_file(manifest)
|
14
|
-
apply_manifest(nil, catch_failures: true, manifest_file_location: manifest_file_location)
|
15
|
-
apply_manifest(nil, catch_changes: true, manifest_file_location: manifest_file_location)
|
25
|
+
apply_manifest(nil, **opts, catch_failures: true, manifest_file_location: manifest_file_location)
|
26
|
+
apply_manifest(nil, **opts, catch_changes: true, manifest_file_location: manifest_file_location)
|
16
27
|
end
|
17
28
|
end
|
18
29
|
|
@@ -70,10 +81,15 @@ module PuppetLitmus::PuppetHelpers
|
|
70
81
|
|
71
82
|
manifest_file_location = opts[:manifest_file_location] || create_manifest_file(manifest)
|
72
83
|
inventory_hash = File.exist?('spec/fixtures/litmus_inventory.yaml') ? inventory_hash_from_inventory_file : localhost_inventory_hash
|
73
|
-
raise "Target '#{target_node_name}' not found in spec/fixtures/litmus_inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
|
74
84
|
|
75
|
-
|
76
|
-
|
85
|
+
target_option = opts['targets'] || opts[:targets]
|
86
|
+
if target_option.nil?
|
87
|
+
raise "Target '#{target_node_name}' not found in spec/fixtures/litmus_inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
|
88
|
+
else
|
89
|
+
target_node_name = search_for_target(target_option, inventory_hash)
|
90
|
+
end
|
91
|
+
|
92
|
+
add_node_fields_to_span(span, target_node_name, inventory_hash)
|
77
93
|
|
78
94
|
# Forcibly set the locale of the command
|
79
95
|
locale = if os[:family] != 'windows'
|
@@ -132,7 +148,7 @@ module PuppetLitmus::PuppetHelpers
|
|
132
148
|
#
|
133
149
|
# @param manifest [String] puppet manifest code.
|
134
150
|
# @return [String] The path to the location of the manifest.
|
135
|
-
def create_manifest_file(manifest)
|
151
|
+
def create_manifest_file(manifest, opts = {})
|
136
152
|
Honeycomb.start_span(name: 'litmus.create_manifest_file') do |span|
|
137
153
|
ENV['HONEYCOMB_TRACE'] = span.to_trace_header
|
138
154
|
span.add_field('litmus.manifest', manifest)
|
@@ -149,8 +165,9 @@ module PuppetLitmus::PuppetHelpers
|
|
149
165
|
else
|
150
166
|
# transfer to TARGET_HOST
|
151
167
|
inventory_hash = inventory_hash_from_inventory_file
|
152
|
-
|
153
|
-
|
168
|
+
target_option = opts['targets'] || opts[:targets]
|
169
|
+
target_node_name = search_for_target(target_option, inventory_hash) unless target_option.nil?
|
170
|
+
add_node_fields_to_span(span, target_node_name, inventory_hash)
|
154
171
|
|
155
172
|
manifest_file_location = File.basename(manifest_file)
|
156
173
|
bolt_result = upload_file(manifest_file.path, manifest_file_location, target_node_name, options: {}, config: nil, inventory: inventory_hash)
|
@@ -169,13 +186,16 @@ module PuppetLitmus::PuppetHelpers
|
|
169
186
|
# @param content [String] String data to write to the file.
|
170
187
|
# @param destination [String] The path on the target node to write the file.
|
171
188
|
# @return [Bool] Success. The file was succesfully writtne on the target.
|
172
|
-
def write_file(content, destination)
|
189
|
+
def write_file(content, destination, opts = {})
|
173
190
|
Honeycomb.start_span(name: 'litmus.write_file') do |span|
|
174
191
|
ENV['HONEYCOMB_TRACE'] = span.to_trace_header
|
175
192
|
span.add_field('litmus.destination', destination)
|
176
193
|
|
177
194
|
require 'tmpdir'
|
195
|
+
inventory_hash = inventory_hash_from_inventory_file
|
178
196
|
target_node_name = ENV['TARGET_HOST']
|
197
|
+
target_option = opts['targets'] || opts[:targets]
|
198
|
+
target_node_name = search_for_target(target_option, inventory_hash) unless target_option.nil?
|
179
199
|
|
180
200
|
Tempfile.create('litmus') do |tmp_file|
|
181
201
|
tmp_file.write(content)
|
@@ -186,9 +206,7 @@ module PuppetLitmus::PuppetHelpers
|
|
186
206
|
FileUtils.cp(tmp_file.path, destination)
|
187
207
|
else
|
188
208
|
# transfer to TARGET_HOST
|
189
|
-
|
190
|
-
span.add_field('litmus.node_name', target_node_name)
|
191
|
-
add_platform_field(inventory_hash, target_node_name)
|
209
|
+
add_node_fields_to_span(span, target_node_name, inventory_hash)
|
192
210
|
|
193
211
|
bolt_result = upload_file(tmp_file.path, destination, target_node_name, options: {}, config: nil, inventory: inventory_hash)
|
194
212
|
span.add_field('litmus.bolt_result.file_upload', bolt_result)
|
@@ -212,12 +230,17 @@ module PuppetLitmus::PuppetHelpers
|
|
212
230
|
span.add_field('litmus.command_to_run', command_to_run)
|
213
231
|
span.add_field('litmus.opts', opts)
|
214
232
|
|
215
|
-
target_node_name = targeting_localhost? ? 'litmus_localhost' : ENV['TARGET_HOST']
|
216
233
|
inventory_hash = File.exist?('spec/fixtures/litmus_inventory.yaml') ? inventory_hash_from_inventory_file : localhost_inventory_hash
|
217
|
-
raise "Target '#{target_node_name}' not found in spec/fixtures/litmus_inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
|
218
234
|
|
219
|
-
|
220
|
-
|
235
|
+
target_option = opts['targets'] || opts[:targets]
|
236
|
+
if target_option.nil?
|
237
|
+
target_node_name = targeting_localhost? ? 'litmus_localhost' : ENV['TARGET_HOST']
|
238
|
+
raise "Target '#{target_node_name}' not found in spec/fixtures/litmus_inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
|
239
|
+
else
|
240
|
+
target_node_name = search_for_target(target_option, inventory_hash)
|
241
|
+
end
|
242
|
+
|
243
|
+
add_node_fields_to_span(span, target_node_name, inventory_hash)
|
221
244
|
|
222
245
|
bolt_result = run_command(command_to_run, target_node_name, config: nil, inventory: inventory_hash)
|
223
246
|
span.add_field('litmus.bolt_result', bolt_result)
|
@@ -251,12 +274,16 @@ module PuppetLitmus::PuppetHelpers
|
|
251
274
|
span.add_field('litmus.opts', opts)
|
252
275
|
span.add_field('litmus.options', options)
|
253
276
|
|
254
|
-
target_node_name = targeting_localhost? ? 'litmus_localhost' : ENV['TARGET_HOST']
|
255
277
|
inventory_hash = File.exist?('spec/fixtures/litmus_inventory.yaml') ? inventory_hash_from_inventory_file : localhost_inventory_hash
|
256
|
-
|
278
|
+
target_option = opts['targets'] || opts[:targets]
|
279
|
+
if target_option.nil?
|
280
|
+
target_node_name = targeting_localhost? ? 'litmus_localhost' : ENV['TARGET_HOST']
|
281
|
+
raise "Target '#{target_node_name}' not found in spec/fixtures/litmus_inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
|
282
|
+
else
|
283
|
+
target_node_name = search_for_target(target_option, inventory_hash)
|
284
|
+
end
|
257
285
|
|
258
|
-
span
|
259
|
-
add_platform_field(inventory_hash, target_node_name)
|
286
|
+
add_node_fields_to_span(span, target_node_name, inventory_hash)
|
260
287
|
|
261
288
|
bolt_result = upload_file(source, destination, target_node_name, options: options, config: nil, inventory: inventory_hash)
|
262
289
|
span.add_field('litmus.bolt_result', bolt_result)
|
@@ -311,10 +338,15 @@ module PuppetLitmus::PuppetHelpers
|
|
311
338
|
else
|
312
339
|
localhost_inventory_hash
|
313
340
|
end
|
314
|
-
raise "Target '#{target_node_name}' not found in spec/fixtures/litmus_inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
|
315
341
|
|
316
|
-
|
317
|
-
|
342
|
+
target_option = opts['targets'] || opts[:targets]
|
343
|
+
if target_option.nil?
|
344
|
+
raise "Target '#{target_node_name}' not found in spec/fixtures/litmus_inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
|
345
|
+
else
|
346
|
+
target_node_name = search_for_target(target_option, inventory_hash)
|
347
|
+
end
|
348
|
+
|
349
|
+
add_node_fields_to_span(span, target_node_name, inventory_hash)
|
318
350
|
|
319
351
|
bolt_result = run_task(task_name, target_node_name, params, config: config_data, inventory: inventory_hash)
|
320
352
|
result_obj = {
|
@@ -372,10 +404,14 @@ module PuppetLitmus::PuppetHelpers
|
|
372
404
|
|
373
405
|
target_node_name = targeting_localhost? ? 'litmus_localhost' : ENV['TARGET_HOST']
|
374
406
|
inventory_hash = File.exist?('spec/fixtures/litmus_inventory.yaml') ? inventory_hash_from_inventory_file : localhost_inventory_hash
|
375
|
-
|
407
|
+
target_option = opts['targets'] || opts[:targets]
|
408
|
+
if target_option.nil?
|
409
|
+
raise "Target '#{target_node_name}' not found in spec/fixtures/litmus_inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
|
410
|
+
else
|
411
|
+
target_node_name = search_for_target(target_option, inventory_hash)
|
412
|
+
end
|
376
413
|
|
377
|
-
span
|
378
|
-
add_platform_field(inventory_hash, target_node_name)
|
414
|
+
add_node_fields_to_span(span, target_node_name, inventory_hash)
|
379
415
|
|
380
416
|
bolt_result = run_script(script, target_node_name, arguments, options: opts, config: nil, inventory: inventory_hash)
|
381
417
|
|
@@ -464,7 +464,7 @@ module PuppetLitmus::RakeHelper
|
|
464
464
|
|
465
465
|
class LitmusTimeoutError < StandardError; end
|
466
466
|
|
467
|
-
def with_retries(options: { tries: Float::INFINITY }, max_wait_minutes:
|
467
|
+
def with_retries(options: { tries: Float::INFINITY }, max_wait_minutes: 15)
|
468
468
|
stop = Time.now + (max_wait_minutes * 60)
|
469
469
|
Retryable.retryable(options.merge(not: [LitmusTimeoutError])) do
|
470
470
|
raise LitmusTimeoutError if Time.now > stop
|
@@ -0,0 +1,46 @@
|
|
1
|
+
{
|
2
|
+
"name": "puppetlabs-fake_module",
|
3
|
+
"version": "3.1.0",
|
4
|
+
"author": "puppetlabs",
|
5
|
+
"summary": "fake_module is a test",
|
6
|
+
"license": "Apache-2.0",
|
7
|
+
"source": "it has no source",
|
8
|
+
"project_page": "it has no project page",
|
9
|
+
"issues_url": "https://tickets.puppetlabs.com/browse/MODULES",
|
10
|
+
"dependencies": [
|
11
|
+
{
|
12
|
+
"name": "puppetlabs/stdlib",
|
13
|
+
"version_requirement": ">= 4.0.0 < 9.0.0"
|
14
|
+
}
|
15
|
+
],
|
16
|
+
"operatingsystem_support": [
|
17
|
+
{
|
18
|
+
"operatingsystem": "CentOS",
|
19
|
+
"operatingsystemrelease": [
|
20
|
+
"6"
|
21
|
+
]
|
22
|
+
},
|
23
|
+
{
|
24
|
+
"operatingsystem": "RedHat",
|
25
|
+
"operatingsystemrelease": [
|
26
|
+
"8"
|
27
|
+
]
|
28
|
+
},
|
29
|
+
{
|
30
|
+
"operatingsystem": "Ubuntu",
|
31
|
+
"operatingsystemrelease": [
|
32
|
+
"14.04",
|
33
|
+
"18.04"
|
34
|
+
]
|
35
|
+
}
|
36
|
+
],
|
37
|
+
"requirements": [
|
38
|
+
{
|
39
|
+
"name": "puppet",
|
40
|
+
"version_requirement": ">= 6.0.0 < 8.0.0"
|
41
|
+
}
|
42
|
+
],
|
43
|
+
"template-url": "https://github.com/puppetlabs/pdk-templates.git#main",
|
44
|
+
"template-ref": "heads/main-0-g2381db6",
|
45
|
+
"pdk-version": "2.1.1"
|
46
|
+
}
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe 'matrix_from_metadata_v2' do
|
6
|
+
context 'without arguments' do
|
7
|
+
let(:result) { run_matrix_from_metadata_v2 }
|
8
|
+
|
9
|
+
it 'run successfully' do
|
10
|
+
expect(result.status_code).to eq 0
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'generates the matrix' do
|
14
|
+
expect(result.stdout).to include('::warning::Cannot find image for Ubuntu-14.04')
|
15
|
+
expect(result.stdout).to include(
|
16
|
+
[
|
17
|
+
'::set-output name=matrix::{',
|
18
|
+
'"platforms":[',
|
19
|
+
'{"label":"CentOS-6","provider":"provision::docker","image":"litmusimage/centos:6"},',
|
20
|
+
'{"label":"RedHat-8","provider":"provision::provision_service","image":"rhel-8"},',
|
21
|
+
'{"label":"Ubuntu-18.04","provider":"provision::docker","image":"litmusimage/ubuntu:18.04"}',
|
22
|
+
'],',
|
23
|
+
'"collection":[',
|
24
|
+
'"puppet6-nightly","puppet7-nightly"',
|
25
|
+
']',
|
26
|
+
'}',
|
27
|
+
].join,
|
28
|
+
)
|
29
|
+
expect(result.stdout).to include(
|
30
|
+
'::set-output name=spec_matrix::{"include":[{"puppet_version":"~> 6.0","ruby_version":2.5},{"puppet_version":"~> 7.0","ruby_version":2.7}]}',
|
31
|
+
)
|
32
|
+
expect(result.stdout).to include("Created matrix with 8 cells:\n - Acceptance Test Cells: 6\n - Spec Test Cells: 2")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'with --exclude-platforms ["ubuntu-18.04"]' do
|
37
|
+
let(:result) { run_matrix_from_metadata_v2({ '--exclude-platforms' => ['ubuntu-18.04'] }) }
|
38
|
+
|
39
|
+
it 'run successfully' do
|
40
|
+
expect(result.status_code).to eq 0
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'generates the matrix without excluded platforms' do
|
44
|
+
expect(result.stdout).to include('::warning::Cannot find image for Ubuntu-14.04')
|
45
|
+
expect(result.stdout).to include('::warning::Ubuntu-18.04 was excluded from testing')
|
46
|
+
expect(result.stdout).to include(
|
47
|
+
[
|
48
|
+
'::set-output name=matrix::{',
|
49
|
+
'"platforms":[',
|
50
|
+
'{"label":"CentOS-6","provider":"provision::docker","image":"litmusimage/centos:6"},',
|
51
|
+
'{"label":"RedHat-8","provider":"provision::provision_service","image":"rhel-8"}',
|
52
|
+
'],',
|
53
|
+
'"collection":[',
|
54
|
+
'"puppet6-nightly","puppet7-nightly"',
|
55
|
+
']',
|
56
|
+
'}',
|
57
|
+
].join,
|
58
|
+
)
|
59
|
+
expect(result.stdout).to include(
|
60
|
+
'::set-output name=spec_matrix::{"include":[{"puppet_version":"~> 6.0","ruby_version":2.5},{"puppet_version":"~> 7.0","ruby_version":2.7}]}',
|
61
|
+
)
|
62
|
+
expect(result.stdout).to include("Created matrix with 6 cells:\n - Acceptance Test Cells: 4\n - Spec Test Cells: 2")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'with --exclude-platforms \'["ubuntu-18.04","redhat-8"]\'' do
|
67
|
+
let(:result) { run_matrix_from_metadata_v2({ '--exclude-platforms' => ['ubuntu-18.04', 'redhat-8'] }) }
|
68
|
+
|
69
|
+
it 'run successfully' do
|
70
|
+
expect(result.status_code).to eq 0
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'generates the matrix without excluded platforms' do
|
74
|
+
expect(result.stdout).to include('::warning::Cannot find image for Ubuntu-14.04')
|
75
|
+
expect(result.stdout).to include('::warning::Ubuntu-18.04 was excluded from testing')
|
76
|
+
expect(result.stdout).to include('::warning::RedHat-8 was excluded from testing')
|
77
|
+
expect(result.stdout).to include(
|
78
|
+
[
|
79
|
+
'::set-output name=matrix::{',
|
80
|
+
'"platforms":[',
|
81
|
+
'{"label":"CentOS-6","provider":"provision::docker","image":"litmusimage/centos:6"}',
|
82
|
+
'],',
|
83
|
+
'"collection":[',
|
84
|
+
'"puppet6-nightly","puppet7-nightly"',
|
85
|
+
']',
|
86
|
+
'}',
|
87
|
+
].join,
|
88
|
+
)
|
89
|
+
expect(result.stdout).to include(
|
90
|
+
'::set-output name=spec_matrix::{"include":[{"puppet_version":"~> 6.0","ruby_version":2.5},{"puppet_version":"~> 7.0","ruby_version":2.7}]}',
|
91
|
+
)
|
92
|
+
expect(result.stdout).to include("Created matrix with 4 cells:\n - Acceptance Test Cells: 2\n - Spec Test Cells: 2")
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|