puppet_litmus 0.18.0 → 0.19.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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/exe/matrix_from_metadata +62 -0
- data/lib/puppet_litmus.rb +0 -1
- data/lib/puppet_litmus/inventory_manipulation.rb +16 -8
- data/lib/puppet_litmus/puppet_helpers.rb +51 -15
- data/lib/puppet_litmus/rake_helper.rb +94 -58
- data/lib/puppet_litmus/rake_tasks.rb +120 -94
- data/lib/puppet_litmus/spec_helper_acceptance.rb +4 -1
- data/lib/puppet_litmus/version.rb +1 -1
- data/spec/lib/puppet_litmus/inventory_manipulation_spec.rb +16 -16
- data/spec/lib/puppet_litmus/puppet_helpers_spec.rb +135 -106
- data/spec/lib/puppet_litmus/rake_helper_spec.rb +23 -23
- data/spec/lib/puppet_litmus/rake_tasks_spec.rb +11 -10
- data/spec/spec_helper.rb +7 -6
- metadata +28 -22
- data/lib/puppet_litmus/honeycomb_utils.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ffba803cc6b53c4bdb7084bf11be4fac807f3b3cd237c5ddb297dcf6ca3a403d
|
4
|
+
data.tar.gz: 5cdb613f2be957e20a63fc1250b10113e468e162817657f0f987675f2ba7c055
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ea1fd95a69bfac81b56f94f3ee28b91be2587c501bf24729931c128315e41d5eaf937dce013ee0d63ec7a350469ac32ab0d7711e50411a0e5fe00340dabdd803
|
7
|
+
data.tar.gz: 899ac2b0edb422ccf35c9cdb5f46bec6b2a6a97557dca12ffc994e046ed8cf1e6eec2553865a3c4439b272d1dd29b0111fc24b2e1bb93575cb77fc0bfd7606b1
|
data/README.md
CHANGED
@@ -24,7 +24,7 @@ Install Litmus as a gem by running ```gem install puppet_litmus```.
|
|
24
24
|
|
25
25
|
## Documentation
|
26
26
|
|
27
|
-
For documentation, see our [Litmus
|
27
|
+
For documentation, see our [Litmus Docs Site](https://puppetlabs.github.io/litmus/).
|
28
28
|
|
29
29
|
## Other Resources
|
30
30
|
|
@@ -0,0 +1,62 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# this script creates a build matrix for github actions from the claimed supported platforms in metadata.json
|
5
|
+
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
IMAGE_TABLE = {
|
9
|
+
'RedHat-6' => 'rhel-6',
|
10
|
+
'RedHat-7' => 'rhel-7',
|
11
|
+
'RedHat-8' => 'rhel-8',
|
12
|
+
'SLES-12' => 'sles-12',
|
13
|
+
'SLES-15' => 'sles-15',
|
14
|
+
'Windows-2012 R2' => 'windows-2012-r2-core',
|
15
|
+
'Windows-2016' => 'windows-2016',
|
16
|
+
'Windows-2019' => 'windows-2019-core',
|
17
|
+
}.freeze
|
18
|
+
|
19
|
+
DOCKER_PLATFORMS = [
|
20
|
+
'CentOS-6',
|
21
|
+
'CentOS-7',
|
22
|
+
'CentOS-8',
|
23
|
+
'Debian-10',
|
24
|
+
'Debian-8',
|
25
|
+
'Debian-9',
|
26
|
+
'OracleLinux-6',
|
27
|
+
'OracleLinux-7',
|
28
|
+
'Scientific-6',
|
29
|
+
'Scientific-7',
|
30
|
+
'Ubuntu-14.04',
|
31
|
+
'Ubuntu-16.04',
|
32
|
+
'Ubuntu-18.04',
|
33
|
+
'Ubuntu-20.04',
|
34
|
+
].freeze
|
35
|
+
|
36
|
+
matrix = {
|
37
|
+
platform: [],
|
38
|
+
collection: %w[
|
39
|
+
puppet5
|
40
|
+
puppet6
|
41
|
+
puppet7-nightly
|
42
|
+
],
|
43
|
+
}
|
44
|
+
|
45
|
+
metadata = JSON.parse(File.read('metadata.json'))
|
46
|
+
metadata['operatingsystem_support'].sort_by { |a| a['operatingsystem'] }.each do |sup|
|
47
|
+
os = sup['operatingsystem']
|
48
|
+
sup['operatingsystemrelease'].sort_by { |a| a.to_i }.each do |ver|
|
49
|
+
image_key = "#{os}-#{ver}"
|
50
|
+
if IMAGE_TABLE.key? image_key
|
51
|
+
matrix[:platform] << IMAGE_TABLE[image_key]
|
52
|
+
elsif DOCKER_PLATFORMS.include? image_key
|
53
|
+
puts "Expecting #{image_key} test using docker on travis"
|
54
|
+
else
|
55
|
+
puts "::warning::Cannot find image for #{image_key}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
puts "::set-output name=matrix::#{JSON.generate(matrix)}"
|
61
|
+
|
62
|
+
puts "Created matrix with #{matrix[:platform].length * matrix[:collection].length} cells."
|
data/lib/puppet_litmus.rb
CHANGED
@@ -18,7 +18,7 @@ module PuppetLitmus::InventoryManipulation
|
|
18
18
|
raise "There is no inventory file at '#{inventory_full_path}'." unless File.exist?(inventory_full_path)
|
19
19
|
|
20
20
|
inventory_hash = YAML.load_file(inventory_full_path)
|
21
|
-
raise "Inventory file is incompatible (version 2 and up). Try the 'bolt project migrate' command." if inventory_hash
|
21
|
+
raise "Inventory file is incompatible (version 2 and up). Try the 'bolt project migrate' command." if inventory_hash['version'].nil? || (inventory_hash['version'] < 2)
|
22
22
|
|
23
23
|
inventory_hash
|
24
24
|
end
|
@@ -50,12 +50,11 @@ module PuppetLitmus::InventoryManipulation
|
|
50
50
|
# @param targets [Array]
|
51
51
|
# @return [Array] array of targets.
|
52
52
|
def find_targets(inventory_hash, targets)
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
targets
|
53
|
+
if targets.nil?
|
54
|
+
inventory_hash.to_s.scan(%r{uri"=>"(\S*)"}).flatten
|
55
|
+
else
|
56
|
+
[targets]
|
57
|
+
end
|
59
58
|
end
|
60
59
|
|
61
60
|
# Determines if a node_name exists in a group in the inventory_hash.
|
@@ -235,7 +234,7 @@ module PuppetLitmus::InventoryManipulation
|
|
235
234
|
#
|
236
235
|
# @param inventory_hash [Hash] hash of the inventory.yaml file
|
237
236
|
# @param feature_name [String] feature to locate in the node
|
238
|
-
# node_name [String] node of nodes to limit the search for the node_name in
|
237
|
+
# @param node_name [String] node of nodes to limit the search for the node_name in
|
239
238
|
# @return inventory.yaml file with feature removed from the node.
|
240
239
|
# @return [Hash] inventory_hash with feature added to node if node_name exists in inventory hash.
|
241
240
|
def remove_feature_from_node(inventory_hash, feature_name, node_name)
|
@@ -257,4 +256,13 @@ module PuppetLitmus::InventoryManipulation
|
|
257
256
|
def write_to_inventory_file(inventory_hash, inventory_full_path)
|
258
257
|
File.open(inventory_full_path, 'wb+') { |f| f.write(inventory_hash.to_yaml) }
|
259
258
|
end
|
259
|
+
|
260
|
+
# Add the `litmus.platform` with platform information for the target
|
261
|
+
#
|
262
|
+
# @param inventory_hash [Hash] hash of the inventory.yaml file
|
263
|
+
# @param node_name [String] node of nodes to limit the search for the node_name in
|
264
|
+
def add_platform_field(inventory_hash, node_name)
|
265
|
+
facts = facts_from_node(inventory_hash, node_name)
|
266
|
+
Honeycomb.current_span.add_field('litmus.platform', facts&.dig('platform'))
|
267
|
+
end
|
260
268
|
end
|
@@ -9,7 +9,7 @@ module PuppetLitmus::PuppetHelpers
|
|
9
9
|
# @return [Boolean] The result of the 2 apply manifests.
|
10
10
|
def idempotent_apply(manifest)
|
11
11
|
Honeycomb.start_span(name: 'litmus.idempotent_apply') do |span|
|
12
|
-
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
12
|
+
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
13
13
|
manifest_file_location = create_manifest_file(manifest)
|
14
14
|
apply_manifest(nil, expect_failures: false, manifest_file_location: manifest_file_location)
|
15
15
|
apply_manifest(nil, catch_changes: true, manifest_file_location: manifest_file_location)
|
@@ -39,7 +39,7 @@ module PuppetLitmus::PuppetHelpers
|
|
39
39
|
# @return [Object] A result object from the apply.
|
40
40
|
def apply_manifest(manifest, opts = {})
|
41
41
|
Honeycomb.start_span(name: 'litmus.apply_manifest') do |span|
|
42
|
-
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
42
|
+
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
43
43
|
span.add_field('litmus.manifest', manifest)
|
44
44
|
span.add_field('litmus.opts', opts)
|
45
45
|
|
@@ -73,7 +73,7 @@ module PuppetLitmus::PuppetHelpers
|
|
73
73
|
raise "Target '#{target_node_name}' not found in inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
|
74
74
|
|
75
75
|
span.add_field('litmus.node_name', target_node_name)
|
76
|
-
|
76
|
+
add_platform_field(inventory_hash, target_node_name)
|
77
77
|
|
78
78
|
command_to_run = "#{opts[:prefix_command]} puppet apply #{manifest_file_location}"
|
79
79
|
command_to_run += ' --trace' if !opts[:trace].nil? && (opts[:trace] == true)
|
@@ -117,7 +117,7 @@ module PuppetLitmus::PuppetHelpers
|
|
117
117
|
# @return [String] The path to the location of the manifest.
|
118
118
|
def create_manifest_file(manifest)
|
119
119
|
Honeycomb.start_span(name: 'litmus.create_manifest_file') do |span|
|
120
|
-
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
120
|
+
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
121
121
|
span.add_field('litmus.manifest', manifest)
|
122
122
|
|
123
123
|
require 'tmpdir'
|
@@ -133,9 +133,9 @@ module PuppetLitmus::PuppetHelpers
|
|
133
133
|
# transfer to TARGET_HOST
|
134
134
|
inventory_hash = inventory_hash_from_inventory_file
|
135
135
|
span.add_field('litmus.node_name', target_node_name)
|
136
|
-
|
136
|
+
add_platform_field(inventory_hash, target_node_name)
|
137
137
|
|
138
|
-
manifest_file_location =
|
138
|
+
manifest_file_location = File.basename(manifest_file)
|
139
139
|
bolt_result = upload_file(manifest_file.path, manifest_file_location, target_node_name, options: {}, config: nil, inventory: inventory_hash)
|
140
140
|
span.add_field('litmus.bolt_result', bolt_result)
|
141
141
|
raise bolt_result.first['value'].to_s unless bolt_result.first['status'] == 'success'
|
@@ -147,6 +147,42 @@ module PuppetLitmus::PuppetHelpers
|
|
147
147
|
end
|
148
148
|
end
|
149
149
|
|
150
|
+
# Writes a string variable to a file on a target node at a specified path.
|
151
|
+
#
|
152
|
+
# @param content [String] String data to write to the file.
|
153
|
+
# @param destination [String] The path on the target node to write the file.
|
154
|
+
# @return [Bool] Success. The file was succesfully writtne on the target.
|
155
|
+
def write_file(content, destination)
|
156
|
+
Honeycomb.start_span(name: 'litmus.write_file') do |span|
|
157
|
+
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
158
|
+
span.add_field('litmus.destination', destination)
|
159
|
+
|
160
|
+
require 'tmpdir'
|
161
|
+
target_node_name = ENV['TARGET_HOST']
|
162
|
+
|
163
|
+
Tempfile.create('litmus') do |tmp_file|
|
164
|
+
tmp_file.write(content)
|
165
|
+
tmp_file.flush
|
166
|
+
if target_node_name.nil? || target_node_name == 'localhost'
|
167
|
+
require 'fileutils'
|
168
|
+
# no need to transfer
|
169
|
+
FileUtils.cp(tmp_file.path, destination)
|
170
|
+
else
|
171
|
+
# transfer to TARGET_HOST
|
172
|
+
inventory_hash = inventory_hash_from_inventory_file
|
173
|
+
span.add_field('litmus.node_name', target_node_name)
|
174
|
+
add_platform_field(inventory_hash, target_node_name)
|
175
|
+
|
176
|
+
bolt_result = upload_file(tmp_file.path, destination, target_node_name, options: {}, config: nil, inventory: inventory_hash)
|
177
|
+
span.add_field('litmus.bolt_result.file_upload', bolt_result)
|
178
|
+
raise bolt_result.first['value'].to_s unless bolt_result.first['status'] == 'success'
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
true
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
150
186
|
# Runs a command against the target system
|
151
187
|
#
|
152
188
|
# @param command_to_run [String] The command to execute.
|
@@ -155,7 +191,7 @@ module PuppetLitmus::PuppetHelpers
|
|
155
191
|
# @return [Object] A result object from the command.
|
156
192
|
def run_shell(command_to_run, opts = {})
|
157
193
|
Honeycomb.start_span(name: 'litmus.run_shell') do |span|
|
158
|
-
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
194
|
+
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
159
195
|
span.add_field('litmus.command_to_run', command_to_run)
|
160
196
|
span.add_field('litmus.opts', opts)
|
161
197
|
|
@@ -164,7 +200,7 @@ module PuppetLitmus::PuppetHelpers
|
|
164
200
|
raise "Target '#{target_node_name}' not found in inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
|
165
201
|
|
166
202
|
span.add_field('litmus.node_name', target_node_name)
|
167
|
-
|
203
|
+
add_platform_field(inventory_hash, target_node_name)
|
168
204
|
|
169
205
|
bolt_result = run_command(command_to_run, target_node_name, config: nil, inventory: inventory_hash)
|
170
206
|
span.add_field('litmus.bolt_result', bolt_result)
|
@@ -192,7 +228,7 @@ module PuppetLitmus::PuppetHelpers
|
|
192
228
|
# @return [Object] A result object from the command.
|
193
229
|
def bolt_upload_file(source, destination, opts = {}, options = {})
|
194
230
|
Honeycomb.start_span(name: 'litmus.bolt_upload_file') do |span|
|
195
|
-
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
231
|
+
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
196
232
|
span.add_field('litmus.source', source)
|
197
233
|
span.add_field('litmus.destination', destination)
|
198
234
|
span.add_field('litmus.opts', opts)
|
@@ -203,7 +239,7 @@ module PuppetLitmus::PuppetHelpers
|
|
203
239
|
raise "Target '#{target_node_name}' not found in inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
|
204
240
|
|
205
241
|
span.add_field('litmus.node_name', target_node_name)
|
206
|
-
|
242
|
+
add_platform_field(inventory_hash, target_node_name)
|
207
243
|
|
208
244
|
bolt_result = upload_file(source, destination, target_node_name, options: options, config: nil, inventory: inventory_hash)
|
209
245
|
span.add_field('litmus.bolt_result', bolt_result)
|
@@ -244,7 +280,7 @@ module PuppetLitmus::PuppetHelpers
|
|
244
280
|
# @return [Object] A result object from the task.The values available are stdout, stderr and result.
|
245
281
|
def run_bolt_task(task_name, params = {}, opts = {})
|
246
282
|
Honeycomb.start_span(name: 'litmus.run_task') do |span|
|
247
|
-
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
283
|
+
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
248
284
|
span.add_field('litmus.task_name', task_name)
|
249
285
|
span.add_field('litmus.params', params)
|
250
286
|
span.add_field('litmus.opts', opts)
|
@@ -261,7 +297,7 @@ module PuppetLitmus::PuppetHelpers
|
|
261
297
|
raise "Target '#{target_node_name}' not found in inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
|
262
298
|
|
263
299
|
span.add_field('litmus.node_name', target_node_name)
|
264
|
-
|
300
|
+
add_platform_field(inventory_hash, target_node_name)
|
265
301
|
|
266
302
|
bolt_result = run_task(task_name, target_node_name, params, config: config_data, inventory: inventory_hash)
|
267
303
|
result_obj = {
|
@@ -312,7 +348,7 @@ module PuppetLitmus::PuppetHelpers
|
|
312
348
|
# @return [Object] A result object from the script run.
|
313
349
|
def bolt_run_script(script, opts = {}, arguments: [])
|
314
350
|
Honeycomb.start_span(name: 'litmus.bolt_run_script') do |span|
|
315
|
-
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
351
|
+
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
316
352
|
span.add_field('litmus.script', script)
|
317
353
|
span.add_field('litmus.opts', opts)
|
318
354
|
span.add_field('litmus.arguments', arguments)
|
@@ -322,7 +358,7 @@ module PuppetLitmus::PuppetHelpers
|
|
322
358
|
raise "Target '#{target_node_name}' not found in inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
|
323
359
|
|
324
360
|
span.add_field('litmus.node_name', target_node_name)
|
325
|
-
|
361
|
+
add_platform_field(inventory_hash, target_node_name)
|
326
362
|
|
327
363
|
bolt_result = run_script(script, target_node_name, arguments, options: opts, config: nil, inventory: inventory_hash)
|
328
364
|
|
@@ -382,7 +418,7 @@ module PuppetLitmus::PuppetHelpers
|
|
382
418
|
|
383
419
|
# Return the stdout of the puppet run
|
384
420
|
def puppet_output(bolt_result)
|
385
|
-
bolt_result.dig(0, 'value', 'stderr').to_s
|
421
|
+
bolt_result.dig(0, 'value', 'stderr').to_s + \
|
386
422
|
bolt_result.dig(0, 'value', 'stdout').to_s
|
387
423
|
end
|
388
424
|
|
@@ -2,16 +2,21 @@
|
|
2
2
|
|
3
3
|
require 'bolt_spec/run'
|
4
4
|
require 'honeycomb-beeline'
|
5
|
-
require 'puppet_litmus/
|
5
|
+
require 'puppet_litmus/version'
|
6
6
|
Honeycomb.configure do |config|
|
7
7
|
# override client if no configuration is provided, so that the pesky libhoney warning about lack of configuration is not shown
|
8
8
|
unless ENV['HONEYCOMB_WRITEKEY'] && ENV['HONEYCOMB_DATASET']
|
9
9
|
config.client = Libhoney::NullClient.new
|
10
10
|
end
|
11
11
|
end
|
12
|
-
process_span = Honeycomb.start_span(name: '
|
13
|
-
ENV['HTTP_X_HONEYCOMB_TRACE'] = process_span.to_trace_header
|
12
|
+
process_span = Honeycomb.start_span(name: "litmus: #{([$PROGRAM_NAME] + ($ARGV || [])).join(' ')}", serialized_trace: ENV['HTTP_X_HONEYCOMB_TRACE'])
|
13
|
+
ENV['HTTP_X_HONEYCOMB_TRACE'] = process_span.to_trace_header
|
14
14
|
Honeycomb.add_field_to_trace('litmus.pid', Process.pid)
|
15
|
+
if defined? PuppetLitmus::VERSION
|
16
|
+
Honeycomb.add_field_to_trace('litmus.version', PuppetLitmus::VERSION)
|
17
|
+
else
|
18
|
+
Honeycomb.add_field_to_trace('litmus.version', 'undefined')
|
19
|
+
end
|
15
20
|
if ENV['CI'] == 'true' && ENV['TRAVIS'] == 'true'
|
16
21
|
Honeycomb.add_field_to_trace('module_name', ENV['TRAVIS_REPO_SLUG'])
|
17
22
|
Honeycomb.add_field_to_trace('ci.provider', 'travis')
|
@@ -43,7 +48,7 @@ end
|
|
43
48
|
module PuppetLitmus::RakeHelper
|
44
49
|
# DEFAULT_CONFIG_DATA should be frozen for our safety, but it needs to work around https://github.com/puppetlabs/bolt/pull/1696
|
45
50
|
DEFAULT_CONFIG_DATA ||= { 'modulepath' => File.join(Dir.pwd, 'spec', 'fixtures', 'modules') } # .freeze # rubocop:disable Style/MutableConstant
|
46
|
-
SUPPORTED_PROVISIONERS ||= %w[abs docker docker_exp vagrant vmpooler].freeze
|
51
|
+
SUPPORTED_PROVISIONERS ||= %w[abs docker docker_exp provision_service vagrant vmpooler].freeze
|
47
52
|
|
48
53
|
# Gets a string representing the operating system and version.
|
49
54
|
#
|
@@ -91,7 +96,7 @@ module PuppetLitmus::RakeHelper
|
|
91
96
|
# @return [Object] the standard out stream.
|
92
97
|
def run_local_command(command)
|
93
98
|
Honeycomb.start_span(name: 'litmus.run_local_command') do |span|
|
94
|
-
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
99
|
+
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
95
100
|
span.add_field('litmus.command', command)
|
96
101
|
|
97
102
|
require 'open3'
|
@@ -114,14 +119,14 @@ module PuppetLitmus::RakeHelper
|
|
114
119
|
|
115
120
|
Honeycomb.add_field_to_trace('litmus.provisioner', provisioner)
|
116
121
|
Honeycomb.start_span(name: 'litmus.provision') do |span|
|
117
|
-
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
122
|
+
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
118
123
|
span.add_field('litmus.platform', platform)
|
119
124
|
span.add_field('litmus.inventory', params['inventory'])
|
120
125
|
span.add_field('litmus.config', DEFAULT_CONFIG_DATA)
|
121
126
|
|
122
127
|
bolt_result = run_task(provisioner_task(provisioner), 'localhost', params, config: DEFAULT_CONFIG_DATA, inventory: nil)
|
123
|
-
|
124
128
|
span.add_field('litmus.node_name', bolt_result&.first&.dig('value', 'node_name'))
|
129
|
+
raise_bolt_errors(bolt_result, "provisioning of #{platform} failed.")
|
125
130
|
|
126
131
|
bolt_result
|
127
132
|
end
|
@@ -143,7 +148,7 @@ module PuppetLitmus::RakeHelper
|
|
143
148
|
|
144
149
|
def tear_down_nodes(targets, inventory_hash)
|
145
150
|
Honeycomb.start_span(name: 'litmus.tear_down_nodes') do |span|
|
146
|
-
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
151
|
+
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
147
152
|
span.add_field('litmus.targets', targets)
|
148
153
|
|
149
154
|
include ::BoltSpec::Run
|
@@ -163,21 +168,23 @@ module PuppetLitmus::RakeHelper
|
|
163
168
|
|
164
169
|
def tear_down(node_name, inventory_hash)
|
165
170
|
Honeycomb.start_span(name: 'litmus.tear_down') do |span|
|
166
|
-
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
171
|
+
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
167
172
|
# how do we know what provisioner to use
|
168
173
|
|
169
174
|
span.add_field('litmus.node_name', node_name)
|
170
|
-
|
175
|
+
add_platform_field(inventory_hash, node_name)
|
171
176
|
|
172
177
|
params = { 'action' => 'tear_down', 'node_name' => node_name, 'inventory' => Dir.pwd }
|
173
178
|
node_facts = facts_from_node(inventory_hash, node_name)
|
174
|
-
run_task(provisioner_task(node_facts['provisioner']), 'localhost', params, config: DEFAULT_CONFIG_DATA, inventory: nil)
|
179
|
+
bolt_result = run_task(provisioner_task(node_facts['provisioner']), 'localhost', params, config: DEFAULT_CONFIG_DATA, inventory: nil)
|
180
|
+
raise_bolt_errors(bolt_result, "tear_down of #{node_name} failed.")
|
181
|
+
bolt_result
|
175
182
|
end
|
176
183
|
end
|
177
184
|
|
178
185
|
def install_agent(collection, targets, inventory_hash)
|
179
186
|
Honeycomb.start_span(name: 'litmus.install_agent') do |span|
|
180
|
-
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
187
|
+
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
181
188
|
span.add_field('litmus.collection', collection)
|
182
189
|
span.add_field('litmus.targets', targets)
|
183
190
|
|
@@ -201,81 +208,102 @@ module PuppetLitmus::RakeHelper
|
|
201
208
|
def configure_path(inventory_hash)
|
202
209
|
results = []
|
203
210
|
# fix the path on ssh_nodes
|
204
|
-
unless inventory_hash['groups'].select { |group| group['name'] == 'ssh_nodes' }.size.zero?
|
205
|
-
results
|
206
|
-
|
211
|
+
unless inventory_hash['groups'].select { |group| group['name'] == 'ssh_nodes' && !group['targets'].empty? }.size.zero?
|
212
|
+
results << run_command('echo PATH="$PATH:/opt/puppetlabs/puppet/bin" > /etc/environment',
|
213
|
+
'ssh_nodes', config: nil, inventory: inventory_hash)
|
214
|
+
end
|
215
|
+
unless inventory_hash['groups'].select { |group| group['name'] == 'winrm_nodes' && !group['targets'].empty? }.size.zero?
|
216
|
+
results << run_command('[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\Program Files\Puppet Labs\Puppet\bin;C:\Program Files (x86)\Puppet Labs\Puppet\bin", "Machine")',
|
217
|
+
'winrm_nodes', config: nil, inventory: inventory_hash)
|
207
218
|
end
|
208
219
|
results
|
209
220
|
end
|
210
221
|
|
222
|
+
# Build the module in `module_dir` and put the resulting compressed tarball into `target_dir`.
|
223
|
+
#
|
211
224
|
# @param opts Hash of options to build the module
|
212
225
|
# @param module_dir [String] The path of the module to build. If missing defaults to Dir.pwd
|
213
|
-
# @param target_dir [String] The path the module will be built into. The default is <
|
226
|
+
# @param target_dir [String] The path the module will be built into. The default is <module_dir>/pkg
|
214
227
|
# @return [String] The path to the built module
|
215
228
|
def build_module(module_dir = nil, target_dir = nil)
|
216
229
|
require 'puppet/modulebuilder'
|
217
230
|
|
218
|
-
|
219
|
-
|
231
|
+
module_dir ||= Dir.pwd
|
232
|
+
target_dir ||= File.join(source_dir, 'pkg')
|
233
|
+
|
234
|
+
puts "Building '#{module_dir}' into '#{target_dir}'"
|
235
|
+
builder = Puppet::Modulebuilder::Builder.new(module_dir, target_dir, nil)
|
220
236
|
|
221
|
-
builder = Puppet::Modulebuilder::Builder.new(source_dir, dest_dir, nil)
|
222
237
|
# Force the metadata to be read. Raises if metadata could not be found
|
223
238
|
_metadata = builder.metadata
|
224
239
|
|
225
240
|
builder.build
|
226
241
|
end
|
227
242
|
|
228
|
-
|
243
|
+
# Builds all the modules in a specified directory
|
244
|
+
#
|
245
|
+
# @param source_dir [String] the directory to get the modules from
|
246
|
+
# @param target_dir [String] temporary location to store tarballs before uploading. This directory will be cleaned before use. The default is <source_dir>/pkg
|
247
|
+
# @return [Array] an array of module tars' filenames
|
248
|
+
def build_modules_in_dir(source_dir, target_dir = nil)
|
249
|
+
target_dir ||= File.join(Dir.pwd, 'pkg')
|
250
|
+
# remove old build dir if exists, before we build afresh
|
251
|
+
FileUtils.rm_rf(target_dir) if File.directory?(target_dir)
|
252
|
+
|
253
|
+
module_tars = Dir.entries(source_dir).map do |entry|
|
254
|
+
next if ['.', '..'].include? entry
|
255
|
+
|
256
|
+
module_dir = File.join(source_dir, entry)
|
257
|
+
next unless File.directory? module_dir
|
258
|
+
|
259
|
+
build_module(module_dir, target_dir)
|
260
|
+
end
|
261
|
+
module_tars.compact
|
262
|
+
end
|
263
|
+
|
264
|
+
# @deprecated Use `build_modules_in_dir` instead
|
265
|
+
def build_modules_in_folder(source_folder)
|
266
|
+
build_modules_in_dir(source_folder)
|
267
|
+
end
|
268
|
+
|
269
|
+
# Install a specific module tarball to the specified target.
|
270
|
+
# This method installs dependencies using a forge repository.
|
271
|
+
#
|
272
|
+
# @param inventory_hash [Hash] the pre-loaded inventory
|
273
|
+
# @param target_node_name [String] the name of the target where the module should be installed
|
274
|
+
# @param module_tar [String] the filename of the module tarball to upload
|
275
|
+
# @param module_repository [String] the URL for the forge to use for downloading modules. Defaults to the public Forge API.
|
276
|
+
# @param ignore_dependencies [Boolean] flag used to ignore module dependencies defaults to false.
|
277
|
+
# @return a bolt result
|
278
|
+
def install_module(inventory_hash, target_node_name, module_tar, module_repository = nil, ignore_dependencies = false) # rubocop:disable Style/OptionalBooleanParameter
|
229
279
|
Honeycomb.start_span(name: 'install_module') do |span|
|
230
|
-
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
280
|
+
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
231
281
|
span.add_field('litmus.target_node_name', target_node_name)
|
232
282
|
span.add_field('litmus.module_tar', module_tar)
|
233
283
|
|
234
|
-
# make sure the
|
284
|
+
# make sure the module to install is not installed
|
235
285
|
# otherwise `puppet module install` might silently skip it
|
236
|
-
|
286
|
+
module_name = File.basename(module_tar, '.tar.gz').split('-', 3)[0..1].join('-')
|
287
|
+
uninstall_module(inventory_hash.clone, target_node_name, module_name, force: true)
|
237
288
|
|
238
289
|
include ::BoltSpec::Run
|
239
290
|
|
240
291
|
target_nodes = find_targets(inventory_hash, target_node_name)
|
241
292
|
span.add_field('litmus.target_nodes', target_nodes)
|
242
|
-
bolt_result = upload_file(module_tar,
|
293
|
+
bolt_result = upload_file(module_tar, File.basename(module_tar), target_nodes, options: {}, config: nil, inventory: inventory_hash.clone)
|
243
294
|
raise_bolt_errors(bolt_result, 'Failed to upload module.')
|
244
295
|
|
245
|
-
|
296
|
+
module_repository_opts = "--module_repository '#{module_repository}'" unless module_repository.nil?
|
297
|
+
install_module_command = "puppet module install #{module_repository_opts} #{File.basename(module_tar)}"
|
298
|
+
install_module_command += ' --ignore-dependencies --force' if ignore_dependencies.to_s.downcase == 'true'
|
246
299
|
span.add_field('litmus.install_module_command', install_module_command)
|
247
300
|
|
248
301
|
bolt_result = run_command(install_module_command, target_nodes, config: nil, inventory: inventory_hash.clone)
|
249
|
-
raise_bolt_errors(bolt_result, "Installation of package #{module_tar} failed.")
|
302
|
+
raise_bolt_errors(bolt_result, "Installation of package #{File.basename(module_tar)} failed.")
|
250
303
|
bolt_result
|
251
304
|
end
|
252
305
|
end
|
253
306
|
|
254
|
-
# Builds all the modules in a specified module
|
255
|
-
#
|
256
|
-
# @param source_folder [String] the folder to get the modules from
|
257
|
-
# @return [Array] an array of module tar's
|
258
|
-
def build_modules_in_folder(source_folder)
|
259
|
-
folder_list = Dir.entries(source_folder).reject { |f| File.directory? f }
|
260
|
-
module_tars = []
|
261
|
-
|
262
|
-
target_dir = File.join(Dir.pwd, 'pkg')
|
263
|
-
# remove old build folder if exists, before we build afresh
|
264
|
-
FileUtils.rm_rf(target_dir) if File.directory?(target_dir)
|
265
|
-
|
266
|
-
folder_list.each do |folder|
|
267
|
-
folder_handle = Dir.open(File.join(source_folder, folder))
|
268
|
-
next if File.symlink?(folder_handle)
|
269
|
-
|
270
|
-
module_dir = folder_handle.path
|
271
|
-
|
272
|
-
# build_module
|
273
|
-
module_tar = build_module(module_dir, target_dir)
|
274
|
-
module_tars.push(File.new(module_tar))
|
275
|
-
end
|
276
|
-
module_tars
|
277
|
-
end
|
278
|
-
|
279
307
|
def metadata_module_name
|
280
308
|
require 'json'
|
281
309
|
raise 'Could not find metadata.json' unless File.exist?(File.join(Dir.pwd, 'metadata.json'))
|
@@ -286,22 +314,30 @@ module PuppetLitmus::RakeHelper
|
|
286
314
|
metadata['name']
|
287
315
|
end
|
288
316
|
|
317
|
+
# Uninstall a module from a specified target
|
318
|
+
# @param inventory_hash [Hash] the pre-loaded inventory
|
319
|
+
# @param target_node_name [String] the name of the target where the module should be uninstalled
|
320
|
+
# @param module_to_remove [String] the name of the module to remove. Defaults to the module under test.
|
321
|
+
# @param opts [Hash] additional options to pass on to `puppet module uninstall`
|
289
322
|
def uninstall_module(inventory_hash, target_node_name, module_to_remove = nil, **opts)
|
290
323
|
include ::BoltSpec::Run
|
291
324
|
module_name = module_to_remove || metadata_module_name
|
292
325
|
target_nodes = find_targets(inventory_hash, target_node_name)
|
293
326
|
install_module_command = "puppet module uninstall #{module_name}"
|
294
327
|
install_module_command += ' --force' if opts[:force]
|
295
|
-
run_command(install_module_command, target_nodes, config: nil, inventory: inventory_hash)
|
328
|
+
bolt_result = run_command(install_module_command, target_nodes, config: nil, inventory: inventory_hash)
|
329
|
+
# `puppet module uninstall --force` fails if the module is not installed. Ignore errors when force is set
|
330
|
+
raise_bolt_errors(bolt_result, "uninstalling #{module_name} failed.") unless opts[:force]
|
331
|
+
bolt_result
|
296
332
|
end
|
297
333
|
|
298
334
|
def check_connectivity?(inventory_hash, target_node_name)
|
299
335
|
Honeycomb.start_span(name: 'litmus.check_connectivity') do |span|
|
300
|
-
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
336
|
+
ENV['HTTP_X_HONEYCOMB_TRACE'] = span.to_trace_header
|
301
337
|
# if we're only checking connectivity for a single node
|
302
338
|
if target_node_name
|
303
339
|
span.add_field('litmus.node_name', target_node_name)
|
304
|
-
|
340
|
+
add_platform_field(inventory_hash, target_node_name)
|
305
341
|
end
|
306
342
|
|
307
343
|
include ::BoltSpec::Run
|
@@ -331,7 +367,7 @@ module PuppetLitmus::RakeHelper
|
|
331
367
|
# Parse out errors messages in result set returned by Bolt command.
|
332
368
|
#
|
333
369
|
# @param result_set [Array] result set returned by Bolt command.
|
334
|
-
# @return [Hash]
|
370
|
+
# @return [Hash] Errors grouped by target.
|
335
371
|
def check_bolt_errors(result_set)
|
336
372
|
errors = {}
|
337
373
|
# iterate through each error
|
@@ -342,8 +378,7 @@ module PuppetLitmus::RakeHelper
|
|
342
378
|
|
343
379
|
target = target_result['target']
|
344
380
|
# get some info from error
|
345
|
-
|
346
|
-
errors[target] = error_msg
|
381
|
+
errors[target] = target_result['value']
|
347
382
|
end
|
348
383
|
errors
|
349
384
|
end
|
@@ -356,7 +391,8 @@ module PuppetLitmus::RakeHelper
|
|
356
391
|
errors = check_bolt_errors(result_set)
|
357
392
|
|
358
393
|
unless errors.empty?
|
359
|
-
|
394
|
+
formatted_results = errors.map { |k, v| " #{k}: #{v.inspect}" }.join("\n")
|
395
|
+
raise "#{error_msg}\nResults:\n#{formatted_results}}"
|
360
396
|
end
|
361
397
|
|
362
398
|
nil
|