puppet_litmus 1.0.2 → 1.0.3
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/lib/puppet_litmus/inventory_manipulation.rb +4 -30
- data/lib/puppet_litmus/puppet_helpers.rb +217 -302
- data/lib/puppet_litmus/rake_helper.rb +83 -182
- data/lib/puppet_litmus/rake_tasks.rb +3 -8
- data/lib/puppet_litmus/version.rb +1 -1
- data/spec/lib/puppet_litmus/puppet_helpers_spec.rb +0 -20
- data/spec/lib/puppet_litmus/rake_tasks_spec.rb +1 -1
- metadata +2 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f42320bf296d7e6efb9370a3e39b775a868417f9dc337aa7c5dee5052b055c6f
|
4
|
+
data.tar.gz: 607ab4fe445eb6f8b29d758212e84065b3e15b0273af85debec7676ea70c9115
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6abadc5c20561dd3f0db0b0bfcd96b55ba0df2e2fdfa97576fb48caabe538287ccb86750264fe10c0831b23e20f89d34946d4df2dd3cdf2e1e0adccb7d3f6538
|
7
|
+
data.tar.gz: f500ac82345c2c05abddf4e50d8c3492e37ef711b5c20a14fcda8d16ad6d5cecb13b64b43d343bd9e11eba242d80ef9584fa73f60fb36329c1b078d3c72f86bd
|
@@ -323,35 +323,9 @@ module PuppetLitmus::InventoryManipulation
|
|
323
323
|
# @param inventory_hash [Hash] hash of the inventory.yaml file
|
324
324
|
# @param node_name [String] node of nodes to limit the search for the node_name in
|
325
325
|
def add_platform_field(inventory_hash, node_name)
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
{}
|
331
|
-
end
|
332
|
-
Honeycomb.current_span.add_field('litmus.platform', facts&.dig('platform'))
|
333
|
-
end
|
334
|
-
|
335
|
-
# Add platform custom information field to the current span for each node being targeted.
|
336
|
-
# If more than one node is being targeted, each node will be given a separate custom field.
|
337
|
-
#
|
338
|
-
# @param span [Honeycomb::Span] The current span
|
339
|
-
# @param target_node_names [Array[String]] Nodes being targeted
|
340
|
-
# @param inventory_hash [Hash] Hash of the inventory.yaml file
|
341
|
-
def add_node_fields_to_span(span, target_node_names, inventory_hash)
|
342
|
-
node_counter = 1
|
343
|
-
Array(target_node_names).each do |target_name|
|
344
|
-
name_field = 'litmus.node_name'
|
345
|
-
platform_field = 'litmus.platform'
|
346
|
-
|
347
|
-
name_field = "#{name_field}_#{node_counter}"
|
348
|
-
platform_field = "#{platform_field}_#{node_counter}"
|
349
|
-
span.add_field(name_field, target_name)
|
350
|
-
if target_in_inventory?(inventory_hash, target_name)
|
351
|
-
facts = facts_from_node(inventory_hash, target_name)
|
352
|
-
span.add_field(platform_field, facts&.dig('platform')) unless facts.nil?
|
353
|
-
end
|
354
|
-
node_counter += 1
|
355
|
-
end
|
326
|
+
facts_from_node(inventory_hash, node_name)
|
327
|
+
rescue StandardError => e
|
328
|
+
warn e
|
329
|
+
{}
|
356
330
|
end
|
357
331
|
end
|
@@ -19,12 +19,9 @@ module PuppetLitmus::PuppetHelpers
|
|
19
19
|
# :noop [Boolean] run puppet apply with the noop flag.
|
20
20
|
# @return [Boolean] The result of the 2 apply manifests.
|
21
21
|
def idempotent_apply(manifest, opts = {})
|
22
|
-
|
23
|
-
|
24
|
-
|
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)
|
27
|
-
end
|
22
|
+
manifest_file_location = create_manifest_file(manifest)
|
23
|
+
apply_manifest(nil, **opts, catch_failures: true, manifest_file_location: manifest_file_location)
|
24
|
+
apply_manifest(nil, **opts, catch_changes: true, manifest_file_location: manifest_file_location)
|
28
25
|
end
|
29
26
|
|
30
27
|
# Applies a manifest. returning the result of that apply. Mimics the apply_manifest from beaker
|
@@ -49,99 +46,85 @@ module PuppetLitmus::PuppetHelpers
|
|
49
46
|
# @yieldreturn [Block] this method will yield to a block of code passed by the caller; this can be used for additional validation, etc.
|
50
47
|
# @return [Object] A result object from the apply.
|
51
48
|
def apply_manifest(manifest, opts = {})
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
acceptable_exit_codes = [2]
|
77
|
-
else
|
78
|
-
use_detailed_exit_codes = false
|
79
|
-
acceptable_exit_codes = [0]
|
80
|
-
end
|
49
|
+
target_node_name = targeting_localhost? ? 'litmus_localhost' : ENV.fetch('TARGET_HOST', nil)
|
50
|
+
raise 'manifest and manifest_file_location in the opts hash are mutually exclusive arguments, pick one' if !manifest.nil? && !opts[:manifest_file_location].nil?
|
51
|
+
raise 'please pass a manifest or the manifest_file_location in the opts hash' if (manifest.nil? || manifest == '') && opts[:manifest_file_location].nil?
|
52
|
+
raise 'please specify only one of `catch_changes`, `expect_changes`, `catch_failures` or `expect_failures`' if
|
53
|
+
[opts[:catch_changes], opts[:expect_changes], opts[:catch_failures], opts[:expect_failures]].compact.length > 1
|
54
|
+
|
55
|
+
opts = { trace: true }.merge(opts)
|
56
|
+
|
57
|
+
if opts[:catch_changes]
|
58
|
+
use_detailed_exit_codes = true
|
59
|
+
acceptable_exit_codes = [0]
|
60
|
+
elsif opts[:catch_failures]
|
61
|
+
use_detailed_exit_codes = true
|
62
|
+
acceptable_exit_codes = [0, 2]
|
63
|
+
elsif opts[:expect_failures]
|
64
|
+
use_detailed_exit_codes = true
|
65
|
+
acceptable_exit_codes = [1, 4, 6]
|
66
|
+
elsif opts[:expect_changes]
|
67
|
+
use_detailed_exit_codes = true
|
68
|
+
acceptable_exit_codes = [2]
|
69
|
+
else
|
70
|
+
use_detailed_exit_codes = false
|
71
|
+
acceptable_exit_codes = [0]
|
72
|
+
end
|
81
73
|
|
82
|
-
|
83
|
-
|
74
|
+
manifest_file_location = opts[:manifest_file_location] || create_manifest_file(manifest)
|
75
|
+
inventory_hash = File.exist?('spec/fixtures/litmus_inventory.yaml') ? inventory_hash_from_inventory_file : localhost_inventory_hash
|
84
76
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
77
|
+
target_option = opts['targets'] || opts[:targets]
|
78
|
+
if target_option.nil?
|
79
|
+
raise "Target '#{target_node_name}' not found in spec/fixtures/litmus_inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
|
80
|
+
else
|
81
|
+
target_node_name = search_for_target(target_option, inventory_hash)
|
82
|
+
end
|
91
83
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
span.add_field('litmus.command_to_run', command_to_run)
|
114
|
-
bolt_result = Tempfile.open(['temp', '.ps1']) do |script|
|
115
|
-
script.write(command_to_run)
|
116
|
-
script.close
|
117
|
-
run_script(script.path, target_node_name, [], options: {}, config: nil, inventory: inventory_hash)
|
118
|
-
end
|
119
|
-
else
|
120
|
-
span.add_field('litmus.command_to_run', command_to_run)
|
121
|
-
bolt_result = run_command(command_to_run, target_node_name, config: nil, inventory: inventory_hash)
|
122
|
-
end
|
123
|
-
span.add_field('litmus.bolt_result', bolt_result)
|
124
|
-
result = OpenStruct.new(exit_code: bolt_result.first['value']['exit_code'],
|
125
|
-
stdout: bolt_result.first['value']['stdout'],
|
126
|
-
stderr: bolt_result.first['value']['stderr'])
|
127
|
-
span.add_field('litmus.result', result.to_h)
|
128
|
-
|
129
|
-
status = result.exit_code
|
130
|
-
if opts[:catch_changes] && !acceptable_exit_codes.include?(status)
|
131
|
-
report_puppet_apply_change(command_to_run, bolt_result)
|
132
|
-
elsif !acceptable_exit_codes.include?(status)
|
133
|
-
report_puppet_apply_error(command_to_run, bolt_result, acceptable_exit_codes)
|
84
|
+
# Forcibly set the locale of the command
|
85
|
+
locale = if os[:family] == 'windows'
|
86
|
+
''
|
87
|
+
else
|
88
|
+
'LC_ALL=en_US.UTF-8 '
|
89
|
+
end
|
90
|
+
command_to_run = "#{locale}#{opts[:prefix_command]} puppet apply #{manifest_file_location}"
|
91
|
+
command_to_run += ' --trace' if !opts[:trace].nil? && (opts[:trace] == true)
|
92
|
+
command_to_run += " --modulepath #{Dir.pwd}/spec/fixtures/modules" if target_node_name == 'litmus_localhost'
|
93
|
+
command_to_run += " --hiera_config='#{opts[:hiera_config]}'" unless opts[:hiera_config].nil?
|
94
|
+
command_to_run += ' --debug' if !opts[:debug].nil? && (opts[:debug] == true)
|
95
|
+
command_to_run += ' --noop' if !opts[:noop].nil? && (opts[:noop] == true)
|
96
|
+
command_to_run += ' --detailed-exitcodes' if use_detailed_exit_codes == true
|
97
|
+
|
98
|
+
if os[:family] == 'windows'
|
99
|
+
# IAC-1365 - Workaround for BOLT-1535 and bolt issue #1650
|
100
|
+
command_to_run = "try { #{command_to_run}; exit $LASTEXITCODE } catch { write-error $_ ; exit 1 }"
|
101
|
+
bolt_result = Tempfile.open(['temp', '.ps1']) do |script|
|
102
|
+
script.write(command_to_run)
|
103
|
+
script.close
|
104
|
+
run_script(script.path, target_node_name, [], options: {}, config: nil, inventory: inventory_hash)
|
134
105
|
end
|
106
|
+
else
|
107
|
+
bolt_result = run_command(command_to_run, target_node_name, config: nil, inventory: inventory_hash)
|
108
|
+
end
|
109
|
+
result = OpenStruct.new(exit_code: bolt_result.first['value']['exit_code'],
|
110
|
+
stdout: bolt_result.first['value']['stdout'],
|
111
|
+
stderr: bolt_result.first['value']['stderr'])
|
112
|
+
|
113
|
+
status = result.exit_code
|
114
|
+
if opts[:catch_changes] && !acceptable_exit_codes.include?(status)
|
115
|
+
report_puppet_apply_change(command_to_run, bolt_result)
|
116
|
+
elsif !acceptable_exit_codes.include?(status)
|
117
|
+
report_puppet_apply_error(command_to_run, bolt_result, acceptable_exit_codes)
|
118
|
+
end
|
135
119
|
|
136
|
-
|
120
|
+
yield result if block_given?
|
137
121
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
end
|
143
|
-
result
|
122
|
+
if ENV['RSPEC_DEBUG']
|
123
|
+
puts "apply manifest succeded\n #{command_to_run}\n======\nwith status #{result.exit_code}"
|
124
|
+
puts result.stderr
|
125
|
+
puts result.stdout
|
144
126
|
end
|
127
|
+
result
|
145
128
|
end
|
146
129
|
|
147
130
|
# Creates a manifest file locally in a temp location, if its a remote target copy it to there.
|
@@ -149,36 +132,27 @@ module PuppetLitmus::PuppetHelpers
|
|
149
132
|
# @param manifest [String] puppet manifest code.
|
150
133
|
# @return [String] The path to the location of the manifest.
|
151
134
|
def create_manifest_file(manifest, opts = {})
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
manifest_file.
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
# transfer to TARGET_HOST
|
167
|
-
inventory_hash = inventory_hash_from_inventory_file
|
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)
|
171
|
-
|
172
|
-
manifest_file_location = File.basename(manifest_file)
|
173
|
-
bolt_result = upload_file(manifest_file.path, manifest_file_location, target_node_name, options: {}, config: nil, inventory: inventory_hash)
|
174
|
-
span.add_field('litmus.bolt_result', bolt_result)
|
175
|
-
raise bolt_result.first['value'].to_s unless bolt_result.first['status'] == 'success'
|
176
|
-
end
|
177
|
-
|
178
|
-
span.add_field('litmus.manifest_file_location', manifest_file_location)
|
135
|
+
require 'tmpdir'
|
136
|
+
target_node_name = ENV.fetch('TARGET_HOST', nil)
|
137
|
+
tmp_filename = File.join(Dir.tmpdir, "manifest_#{Time.now.strftime('%Y%m%d')}_#{Process.pid}_#{rand(0x100000000).to_s(36)}.pp")
|
138
|
+
manifest_file = File.open(tmp_filename, 'w')
|
139
|
+
manifest_file.write(manifest)
|
140
|
+
manifest_file.close
|
141
|
+
if target_node_name.nil? || target_node_name == 'localhost'
|
142
|
+
# no need to transfer
|
143
|
+
manifest_file_location = manifest_file.path
|
144
|
+
else
|
145
|
+
# transfer to TARGET_HOST
|
146
|
+
inventory_hash = inventory_hash_from_inventory_file
|
147
|
+
target_option = opts['targets'] || opts[:targets]
|
148
|
+
target_node_name = search_for_target(target_option, inventory_hash) unless target_option.nil?
|
179
149
|
|
180
|
-
manifest_file_location
|
150
|
+
manifest_file_location = File.basename(manifest_file)
|
151
|
+
bolt_result = upload_file(manifest_file.path, manifest_file_location, target_node_name, options: {}, config: nil, inventory: inventory_hash)
|
152
|
+
raise bolt_result.first['value'].to_s unless bolt_result.first['status'] == 'success'
|
181
153
|
end
|
154
|
+
|
155
|
+
manifest_file_location
|
182
156
|
end
|
183
157
|
|
184
158
|
# Writes a string variable to a file on a target node at a specified path.
|
@@ -187,35 +161,27 @@ module PuppetLitmus::PuppetHelpers
|
|
187
161
|
# @param destination [String] The path on the target node to write the file.
|
188
162
|
# @return [Bool] Success. The file was succesfully writtne on the target.
|
189
163
|
def write_file(content, destination, opts = {})
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
tmp_file.
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
else
|
208
|
-
# transfer to TARGET_HOST
|
209
|
-
add_node_fields_to_span(span, target_node_name, inventory_hash)
|
210
|
-
|
211
|
-
bolt_result = upload_file(tmp_file.path, destination, target_node_name, options: {}, config: nil, inventory: inventory_hash)
|
212
|
-
span.add_field('litmus.bolt_result.file_upload', bolt_result)
|
213
|
-
raise bolt_result.first['value'].to_s unless bolt_result.first['status'] == 'success'
|
214
|
-
end
|
164
|
+
require 'tmpdir'
|
165
|
+
inventory_hash = inventory_hash_from_inventory_file
|
166
|
+
target_node_name = ENV.fetch('TARGET_HOST', nil)
|
167
|
+
target_option = opts['targets'] || opts[:targets]
|
168
|
+
target_node_name = search_for_target(target_option, inventory_hash) unless target_option.nil?
|
169
|
+
|
170
|
+
Tempfile.create('litmus') do |tmp_file|
|
171
|
+
tmp_file.write(content)
|
172
|
+
tmp_file.flush
|
173
|
+
if target_node_name.nil? || target_node_name == 'localhost'
|
174
|
+
require 'fileutils'
|
175
|
+
# no need to transfer
|
176
|
+
FileUtils.cp(tmp_file.path, destination)
|
177
|
+
else
|
178
|
+
# transfer to TARGET_HOST
|
179
|
+
bolt_result = upload_file(tmp_file.path, destination, target_node_name, options: {}, config: nil, inventory: inventory_hash)
|
180
|
+
raise bolt_result.first['value'].to_s unless bolt_result.first['status'] == 'success'
|
215
181
|
end
|
216
|
-
|
217
|
-
true
|
218
182
|
end
|
183
|
+
|
184
|
+
true
|
219
185
|
end
|
220
186
|
|
221
187
|
# Runs a command against the target system
|
@@ -225,36 +191,26 @@ module PuppetLitmus::PuppetHelpers
|
|
225
191
|
# @yieldreturn [Block] this method will yield to a block of code passed by the caller; this can be used for additional validation, etc.
|
226
192
|
# @return [Object] A result object from the command.
|
227
193
|
def run_shell(command_to_run, opts = {})
|
228
|
-
|
229
|
-
ENV['HONEYCOMB_TRACE'] = span.to_trace_header
|
230
|
-
span.add_field('litmus.command_to_run', command_to_run)
|
231
|
-
span.add_field('litmus.opts', opts)
|
232
|
-
|
233
|
-
inventory_hash = File.exist?('spec/fixtures/litmus_inventory.yaml') ? inventory_hash_from_inventory_file : localhost_inventory_hash
|
194
|
+
inventory_hash = File.exist?('spec/fixtures/litmus_inventory.yaml') ? inventory_hash_from_inventory_file : localhost_inventory_hash
|
234
195
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
add_node_fields_to_span(span, target_node_name, inventory_hash)
|
196
|
+
target_option = opts['targets'] || opts[:targets]
|
197
|
+
if target_option.nil?
|
198
|
+
target_node_name = targeting_localhost? ? 'litmus_localhost' : ENV.fetch('TARGET_HOST', nil)
|
199
|
+
raise "Target '#{target_node_name}' not found in spec/fixtures/litmus_inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
|
200
|
+
else
|
201
|
+
target_node_name = search_for_target(target_option, inventory_hash)
|
202
|
+
end
|
244
203
|
|
245
|
-
|
246
|
-
span.add_field('litmus.bolt_result', bolt_result)
|
204
|
+
bolt_result = run_command(command_to_run, target_node_name, config: nil, inventory: inventory_hash)
|
247
205
|
|
248
|
-
|
206
|
+
raise "shell failed\n`#{command_to_run}`\n======\n#{bolt_result}" if bolt_result.first['value']['exit_code'] != 0 && opts[:expect_failures] != true
|
249
207
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
result
|
257
|
-
end
|
208
|
+
result = OpenStruct.new(exit_code: bolt_result.first['value']['exit_code'],
|
209
|
+
exit_status: bolt_result.first['value']['exit_code'],
|
210
|
+
stdout: bolt_result.first['value']['stdout'],
|
211
|
+
stderr: bolt_result.first['value']['stderr'])
|
212
|
+
yield result if block_given?
|
213
|
+
result
|
258
214
|
end
|
259
215
|
|
260
216
|
# Copies file to the target, using its respective transport
|
@@ -265,51 +221,36 @@ module PuppetLitmus::PuppetHelpers
|
|
265
221
|
# @yieldreturn [Block] this method will yield to a block of code passed by the caller; this can be used for additional validation, etc.
|
266
222
|
# @return [Object] A result object from the command.
|
267
223
|
def bolt_upload_file(source, destination, opts = {}, options = {})
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
target_option = opts['targets'] || opts[:targets]
|
277
|
-
if target_option.nil?
|
278
|
-
target_node_name = targeting_localhost? ? 'litmus_localhost' : ENV.fetch('TARGET_HOST', nil)
|
279
|
-
raise "Target '#{target_node_name}' not found in spec/fixtures/litmus_inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
|
280
|
-
else
|
281
|
-
target_node_name = search_for_target(target_option, inventory_hash)
|
282
|
-
end
|
283
|
-
|
284
|
-
add_node_fields_to_span(span, target_node_name, inventory_hash)
|
285
|
-
|
286
|
-
bolt_result = upload_file(source, destination, target_node_name, options: options, config: nil, inventory: inventory_hash)
|
287
|
-
span.add_field('litmus.bolt_result', bolt_result)
|
224
|
+
inventory_hash = File.exist?('spec/fixtures/litmus_inventory.yaml') ? inventory_hash_from_inventory_file : localhost_inventory_hash
|
225
|
+
target_option = opts['targets'] || opts[:targets]
|
226
|
+
if target_option.nil?
|
227
|
+
target_node_name = targeting_localhost? ? 'litmus_localhost' : ENV.fetch('TARGET_HOST', nil)
|
228
|
+
raise "Target '#{target_node_name}' not found in spec/fixtures/litmus_inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
|
229
|
+
else
|
230
|
+
target_node_name = search_for_target(target_option, inventory_hash)
|
231
|
+
end
|
288
232
|
|
289
|
-
|
290
|
-
exit_code: 0,
|
291
|
-
stdout: bolt_result.first['value']['_output'],
|
292
|
-
stderr: nil,
|
293
|
-
result: bolt_result.first['value']
|
294
|
-
}
|
233
|
+
bolt_result = upload_file(source, destination, target_node_name, options: options, config: nil, inventory: inventory_hash)
|
295
234
|
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
235
|
+
result_obj = {
|
236
|
+
exit_code: 0,
|
237
|
+
stdout: bolt_result.first['value']['_output'],
|
238
|
+
stderr: nil,
|
239
|
+
result: bolt_result.first['value']
|
240
|
+
}
|
301
241
|
|
302
|
-
|
303
|
-
|
304
|
-
end
|
242
|
+
if bolt_result.first['status'] != 'success'
|
243
|
+
raise "upload file failed\n======\n#{bolt_result}" if opts[:expect_failures] != true
|
305
244
|
|
306
|
-
|
307
|
-
|
308
|
-
stderr: result_obj[:stderr])
|
309
|
-
span.add_field('litmus.result', result.to_h)
|
310
|
-
yield result if block_given?
|
311
|
-
result
|
245
|
+
result_obj[:exit_code] = 255
|
246
|
+
result_obj[:stderr] = bolt_result.first['value']['_error']['msg']
|
312
247
|
end
|
248
|
+
|
249
|
+
result = OpenStruct.new(exit_code: result_obj[:exit_code],
|
250
|
+
stdout: result_obj[:stdout],
|
251
|
+
stderr: result_obj[:stderr])
|
252
|
+
yield result if block_given?
|
253
|
+
result
|
313
254
|
end
|
314
255
|
|
315
256
|
# Runs a task against the target system.
|
@@ -321,69 +262,56 @@ module PuppetLitmus::PuppetHelpers
|
|
321
262
|
# :inventory_file [String] path to the inventory file to use with the task.
|
322
263
|
# @return [Object] A result object from the task.The values available are stdout, stderr and result.
|
323
264
|
def run_bolt_task(task_name, params = {}, opts = {})
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
target_option = opts['targets'] || opts[:targets]
|
341
|
-
if target_option.nil?
|
342
|
-
raise "Target '#{target_node_name}' not found in spec/fixtures/litmus_inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
|
343
|
-
else
|
344
|
-
target_node_name = search_for_target(target_option, inventory_hash)
|
345
|
-
end
|
346
|
-
|
347
|
-
add_node_fields_to_span(span, target_node_name, inventory_hash)
|
348
|
-
|
349
|
-
bolt_result = run_task(task_name, target_node_name, params, config: config_data, inventory: inventory_hash)
|
350
|
-
result_obj = {
|
351
|
-
exit_code: 0,
|
352
|
-
stdout: nil,
|
353
|
-
stderr: nil,
|
354
|
-
result: bolt_result.first['value']
|
355
|
-
}
|
356
|
-
|
357
|
-
if bolt_result.first['status'] == 'success'
|
358
|
-
# stdout returns unstructured data if structured data is not available
|
359
|
-
result_obj[:stdout] = if bolt_result.first['value']['_output'].nil?
|
360
|
-
bolt_result.first['value'].to_s
|
361
|
-
else
|
362
|
-
bolt_result.first['value']['_output']
|
363
|
-
end
|
364
|
-
|
365
|
-
else
|
366
|
-
if opts[:expect_failures] != true
|
367
|
-
span.add_field('litmus_runtaskfailure', bolt_result)
|
368
|
-
raise "task failed\n`#{task_name}`\n======\n#{bolt_result}"
|
369
|
-
end
|
370
|
-
|
371
|
-
result_obj[:exit_code] = if bolt_result.first['value']['_error']['details'].nil?
|
372
|
-
255
|
373
|
-
else
|
374
|
-
bolt_result.first['value']['_error']['details'].fetch('exitcode', 255)
|
375
|
-
end
|
376
|
-
result_obj[:stderr] = bolt_result.first['value']['_error']['msg']
|
377
|
-
end
|
265
|
+
config_data = { 'modulepath' => File.join(Dir.pwd, 'spec', 'fixtures', 'modules') }
|
266
|
+
target_node_name = targeting_localhost? ? 'litmus_localhost' : ENV.fetch('TARGET_HOST', nil)
|
267
|
+
inventory_hash = if !opts[:inventory_file].nil? && File.exist?(opts[:inventory_file])
|
268
|
+
inventory_hash_from_inventory_file(opts[:inventory_file])
|
269
|
+
elsif File.exist?('spec/fixtures/litmus_inventory.yaml')
|
270
|
+
inventory_hash_from_inventory_file('spec/fixtures/litmus_inventory.yaml')
|
271
|
+
else
|
272
|
+
localhost_inventory_hash
|
273
|
+
end
|
274
|
+
|
275
|
+
target_option = opts['targets'] || opts[:targets]
|
276
|
+
if target_option.nil?
|
277
|
+
raise "Target '#{target_node_name}' not found in spec/fixtures/litmus_inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
|
278
|
+
else
|
279
|
+
target_node_name = search_for_target(target_option, inventory_hash)
|
280
|
+
end
|
378
281
|
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
282
|
+
bolt_result = run_task(task_name, target_node_name, params, config: config_data, inventory: inventory_hash)
|
283
|
+
result_obj = {
|
284
|
+
exit_code: 0,
|
285
|
+
stdout: nil,
|
286
|
+
stderr: nil,
|
287
|
+
result: bolt_result.first['value']
|
288
|
+
}
|
289
|
+
|
290
|
+
if bolt_result.first['status'] == 'success'
|
291
|
+
# stdout returns unstructured data if structured data is not available
|
292
|
+
result_obj[:stdout] = if bolt_result.first['value']['_output'].nil?
|
293
|
+
bolt_result.first['value'].to_s
|
294
|
+
else
|
295
|
+
bolt_result.first['value']['_output']
|
296
|
+
end
|
297
|
+
|
298
|
+
else
|
299
|
+
raise "task failed\n`#{task_name}`\n======\n#{bolt_result}" if opts[:expect_failures] != true
|
300
|
+
|
301
|
+
result_obj[:exit_code] = if bolt_result.first['value']['_error']['details'].nil?
|
302
|
+
255
|
303
|
+
else
|
304
|
+
bolt_result.first['value']['_error']['details'].fetch('exitcode', 255)
|
305
|
+
end
|
306
|
+
result_obj[:stderr] = bolt_result.first['value']['_error']['msg']
|
386
307
|
end
|
308
|
+
|
309
|
+
result = OpenStruct.new(exit_code: result_obj[:exit_code],
|
310
|
+
stdout: result_obj[:stdout],
|
311
|
+
stderr: result_obj[:stderr],
|
312
|
+
result: result_obj[:result])
|
313
|
+
yield result if block_given?
|
314
|
+
result
|
387
315
|
end
|
388
316
|
|
389
317
|
# Runs a script against the target system.
|
@@ -394,37 +322,24 @@ module PuppetLitmus::PuppetHelpers
|
|
394
322
|
# @yieldreturn [Block] this method will yield to a block of code passed by the caller; this can be used for additional validation, etc.
|
395
323
|
# @return [Object] A result object from the script run.
|
396
324
|
def bolt_run_script(script, opts = {}, arguments: [])
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
target_node_name =
|
404
|
-
|
405
|
-
target_option = opts['targets'] || opts[:targets]
|
406
|
-
if target_option.nil?
|
407
|
-
raise "Target '#{target_node_name}' not found in spec/fixtures/litmus_inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
|
408
|
-
else
|
409
|
-
target_node_name = search_for_target(target_option, inventory_hash)
|
410
|
-
end
|
325
|
+
target_node_name = targeting_localhost? ? 'litmus_localhost' : ENV.fetch('TARGET_HOST', nil)
|
326
|
+
inventory_hash = File.exist?('spec/fixtures/litmus_inventory.yaml') ? inventory_hash_from_inventory_file : localhost_inventory_hash
|
327
|
+
target_option = opts['targets'] || opts[:targets]
|
328
|
+
if target_option.nil?
|
329
|
+
raise "Target '#{target_node_name}' not found in spec/fixtures/litmus_inventory.yaml" unless target_in_inventory?(inventory_hash, target_node_name)
|
330
|
+
else
|
331
|
+
target_node_name = search_for_target(target_option, inventory_hash)
|
332
|
+
end
|
411
333
|
|
412
|
-
|
334
|
+
bolt_result = run_script(script, target_node_name, arguments, options: opts, config: nil, inventory: inventory_hash)
|
413
335
|
|
414
|
-
|
336
|
+
raise "script run failed\n`#{script}`\n======\n#{bolt_result}" if bolt_result.first['value']['exit_code'] != 0 && opts[:expect_failures] != true
|
415
337
|
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
result = OpenStruct.new(exit_code: bolt_result.first['value']['exit_code'],
|
422
|
-
stdout: bolt_result.first['value']['stdout'],
|
423
|
-
stderr: bolt_result.first['value']['stderr'])
|
424
|
-
yield result if block_given?
|
425
|
-
span.add_field('litmus.result', result.to_h)
|
426
|
-
result
|
427
|
-
end
|
338
|
+
result = OpenStruct.new(exit_code: bolt_result.first['value']['exit_code'],
|
339
|
+
stdout: bolt_result.first['value']['stdout'],
|
340
|
+
stderr: bolt_result.first['value']['stderr'])
|
341
|
+
yield result if block_given?
|
342
|
+
result
|
428
343
|
end
|
429
344
|
|
430
345
|
# Determines if the current execution is targeting localhost or not
|
@@ -1,53 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'bolt_spec/run'
|
4
|
-
require 'honeycomb-beeline'
|
5
4
|
require 'puppet_litmus/version'
|
6
|
-
Honeycomb.configure do |config|
|
7
|
-
# override client if no configuration is provided, so that the pesky libhoney warning about lack of configuration is not shown
|
8
|
-
config.client = Libhoney::NullClient.new unless ENV['HONEYCOMB_WRITEKEY'] && ENV['HONEYCOMB_DATASET']
|
9
|
-
end
|
10
|
-
process_span = Honeycomb.start_span(name: "litmus: #{([$PROGRAM_NAME] + ($ARGV || [])).join(' ')}", serialized_trace: ENV.fetch('HONEYCOMB_TRACE', nil))
|
11
|
-
ENV['HONEYCOMB_TRACE'] = process_span.to_trace_header
|
12
|
-
Honeycomb.add_field_to_trace('litmus.pid', Process.pid)
|
13
|
-
if defined? PuppetLitmus::VERSION
|
14
|
-
Honeycomb.add_field_to_trace('litmus.version', PuppetLitmus::VERSION)
|
15
|
-
else
|
16
|
-
Honeycomb.add_field_to_trace('litmus.version', 'undefined')
|
17
|
-
end
|
18
|
-
if ENV['CI'] == 'true' && ENV['TRAVIS'] == 'true'
|
19
|
-
Honeycomb.add_field_to_trace('module_name', ENV.fetch('TRAVIS_REPO_SLUG', nil))
|
20
|
-
Honeycomb.add_field_to_trace('ci.provider', 'travis')
|
21
|
-
Honeycomb.add_field_to_trace('ci.build_id', ENV.fetch('TRAVIS_BUILD_ID', nil))
|
22
|
-
Honeycomb.add_field_to_trace('ci.build_url', ENV.fetch('TRAVIS_BUILD_WEB_URL', nil))
|
23
|
-
Honeycomb.add_field_to_trace('ci.job_url', ENV.fetch('TRAVIS_JOB_WEB_URL', nil))
|
24
|
-
Honeycomb.add_field_to_trace('ci.commit_message', ENV.fetch('TRAVIS_COMMIT_MESSAGE', nil))
|
25
|
-
Honeycomb.add_field_to_trace('ci.sha', ENV['TRAVIS_PULL_REQUEST_SHA'] || ENV.fetch('TRAVIS_COMMIT', nil))
|
26
|
-
elsif ENV['CI'] == 'True' && ENV['APPVEYOR'] == 'True'
|
27
|
-
Honeycomb.add_field_to_trace('module_name', ENV.fetch('APPVEYOR_PROJECT_SLUG', nil))
|
28
|
-
Honeycomb.add_field_to_trace('ci.provider', 'appveyor')
|
29
|
-
Honeycomb.add_field_to_trace('ci.build_id', ENV.fetch('APPVEYOR_BUILD_ID', nil))
|
30
|
-
Honeycomb.add_field_to_trace('ci.build_url', "https://ci.appveyor.com/project/#{ENV.fetch('APPVEYOR_REPO_NAME', nil)}/builds/#{ENV.fetch('APPVEYOR_BUILD_ID', nil)}")
|
31
|
-
Honeycomb.add_field_to_trace('ci.job_url', "https://ci.appveyor.com/project/#{ENV.fetch('APPVEYOR_REPO_NAME', nil)}/build/job/#{ENV.fetch('APPVEYOR_JOB_ID', nil)}")
|
32
|
-
Honeycomb.add_field_to_trace('ci.commit_message', ENV.fetch('APPVEYOR_REPO_COMMIT_MESSAGE', nil))
|
33
|
-
Honeycomb.add_field_to_trace('ci.sha', ENV['APPVEYOR_PULL_REQUEST_HEAD_COMMIT'] || ENV.fetch('APPVEYOR_REPO_COMMIT', nil))
|
34
|
-
elsif ENV['GITHUB_ACTIONS'] == 'true'
|
35
|
-
Honeycomb.add_field_to_trace('module_name', ENV.fetch('GITHUB_REPOSITORY', nil))
|
36
|
-
Honeycomb.add_field_to_trace('ci.provider', 'github')
|
37
|
-
Honeycomb.add_field_to_trace('ci.build_id', ENV.fetch('GITHUB_RUN_ID', nil))
|
38
|
-
Honeycomb.add_field_to_trace('ci.build_url', "https://github.com/#{ENV.fetch('GITHUB_REPOSITORY', nil)}/actions/runs/#{ENV.fetch('GITHUB_RUN_ID', nil)}")
|
39
|
-
Honeycomb.add_field_to_trace('ci.sha', ENV.fetch('GITHUB_SHA', nil))
|
40
|
-
end
|
41
|
-
at_exit do
|
42
|
-
if $ERROR_INFO.is_a?(SystemExit)
|
43
|
-
process_span.add_field('process.exit_code', $ERROR_INFO.status)
|
44
|
-
elsif $ERROR_INFO
|
45
|
-
process_span.add_field('process.exit_code', $ERROR_INFO.class.name)
|
46
|
-
else
|
47
|
-
process_span.add_field('process.exit_code', 'unknown')
|
48
|
-
end
|
49
|
-
process_span.send
|
50
|
-
end
|
51
5
|
|
52
6
|
# helper methods for the litmus rake tasks
|
53
7
|
module PuppetLitmus::RakeHelper
|
@@ -100,18 +54,13 @@ module PuppetLitmus::RakeHelper
|
|
100
54
|
# @param command [String] command to execute.
|
101
55
|
# @return [Object] the standard out stream.
|
102
56
|
def run_local_command(command)
|
103
|
-
|
104
|
-
|
105
|
-
|
57
|
+
require 'open3'
|
58
|
+
stdout, stderr, status = Open3.capture3(command)
|
59
|
+
error_message = "Attempted to run\ncommand:'#{command}'\nstdout:#{stdout}\nstderr:#{stderr}"
|
106
60
|
|
107
|
-
|
108
|
-
stdout, stderr, status = Open3.capture3(command)
|
109
|
-
error_message = "Attempted to run\ncommand:'#{command}'\nstdout:#{stdout}\nstderr:#{stderr}"
|
61
|
+
raise error_message unless status.to_i.zero?
|
110
62
|
|
111
|
-
|
112
|
-
|
113
|
-
stdout
|
114
|
-
end
|
63
|
+
stdout
|
115
64
|
end
|
116
65
|
|
117
66
|
def provision(provisioner, platform, inventory_vars)
|
@@ -122,24 +71,11 @@ module PuppetLitmus::RakeHelper
|
|
122
71
|
params = { 'action' => 'provision', 'platform' => platform, 'inventory' => Dir.pwd }
|
123
72
|
params['vars'] = inventory_vars unless inventory_vars.nil?
|
124
73
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
span.add_field('litmus.platform', platform)
|
129
|
-
|
130
|
-
task_name = provisioner_task(provisioner)
|
131
|
-
span.add_field('litmus.task_name', task_name)
|
132
|
-
span.add_field('litmus.params', params)
|
133
|
-
span.add_field('litmus.config', DEFAULT_CONFIG_DATA)
|
134
|
-
|
135
|
-
bolt_result = run_task(task_name, 'localhost', params, config: DEFAULT_CONFIG_DATA, inventory: nil)
|
136
|
-
span.add_field('litmus.result', bolt_result)
|
137
|
-
span.add_field('litmus.node_name', bolt_result&.first&.dig('value', 'node_name'))
|
74
|
+
task_name = provisioner_task(provisioner)
|
75
|
+
bolt_result = run_task(task_name, 'localhost', params, config: DEFAULT_CONFIG_DATA, inventory: nil)
|
76
|
+
raise_bolt_errors(bolt_result, "provisioning of #{platform} failed.")
|
138
77
|
|
139
|
-
|
140
|
-
|
141
|
-
bolt_result
|
142
|
-
end
|
78
|
+
bolt_result
|
143
79
|
end
|
144
80
|
|
145
81
|
def provision_list(provision_hash, key)
|
@@ -149,7 +85,6 @@ module PuppetLitmus::RakeHelper
|
|
149
85
|
provision_hash[key]['params']&.each { |k, value| ENV[k.upcase] = value.to_s }
|
150
86
|
results = []
|
151
87
|
|
152
|
-
Honeycomb.current_span.add_field('litmus.images', provision_hash[key]['images'])
|
153
88
|
provision_hash[key]['images'].each do |image|
|
154
89
|
results << provision(provisioner, image, inventory_vars)
|
155
90
|
end
|
@@ -157,73 +92,57 @@ module PuppetLitmus::RakeHelper
|
|
157
92
|
end
|
158
93
|
|
159
94
|
def tear_down_nodes(targets, inventory_hash)
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
targets
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
result[0]['value'].delete('removed')
|
179
|
-
removed_targets.each do |removed_target|
|
180
|
-
targets.delete(removed_target)
|
181
|
-
results[removed_target] = result
|
182
|
-
end
|
95
|
+
include ::BoltSpec::Run
|
96
|
+
config_data = { 'modulepath' => File.join(Dir.pwd, 'spec', 'fixtures', 'modules') }
|
97
|
+
raise "the provision module was not found in #{config_data['modulepath']}, please amend the .fixtures.yml file" unless File.directory?(File.join(config_data['modulepath'], 'provision'))
|
98
|
+
|
99
|
+
results = {}
|
100
|
+
targets.each do |node_name|
|
101
|
+
next if node_name == 'litmus_localhost'
|
102
|
+
|
103
|
+
result = tear_down(node_name, inventory_hash)
|
104
|
+
# Some provisioners tear_down targets that were created as a batch job.
|
105
|
+
# These provisioners should return the list of additional targets
|
106
|
+
# removed so that we do not attempt to process them.
|
107
|
+
if result != [] && result[0]['value'].key?('removed')
|
108
|
+
removed_targets = result[0]['value']['removed']
|
109
|
+
result[0]['value'].delete('removed')
|
110
|
+
removed_targets.each do |removed_target|
|
111
|
+
targets.delete(removed_target)
|
112
|
+
results[removed_target] = result
|
183
113
|
end
|
184
|
-
|
185
|
-
results[node_name] = result unless result == []
|
186
114
|
end
|
187
|
-
|
115
|
+
|
116
|
+
results[node_name] = result unless result == []
|
188
117
|
end
|
118
|
+
results
|
189
119
|
end
|
190
120
|
|
191
121
|
def tear_down(node_name, inventory_hash)
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
node_facts = facts_from_node(inventory_hash, node_name)
|
201
|
-
bolt_result = run_task(provisioner_task(node_facts['provisioner']), 'localhost', params, config: DEFAULT_CONFIG_DATA, inventory: nil)
|
202
|
-
raise_bolt_errors(bolt_result, "tear_down of #{node_name} failed.")
|
203
|
-
bolt_result
|
204
|
-
end
|
122
|
+
# how do we know what provisioner to use
|
123
|
+
add_platform_field(inventory_hash, node_name)
|
124
|
+
|
125
|
+
params = { 'action' => 'tear_down', 'node_name' => node_name, 'inventory' => Dir.pwd }
|
126
|
+
node_facts = facts_from_node(inventory_hash, node_name)
|
127
|
+
bolt_result = run_task(provisioner_task(node_facts['provisioner']), 'localhost', params, config: DEFAULT_CONFIG_DATA, inventory: nil)
|
128
|
+
raise_bolt_errors(bolt_result, "tear_down of #{node_name} failed.")
|
129
|
+
bolt_result
|
205
130
|
end
|
206
131
|
|
207
132
|
def install_agent(collection, targets, inventory_hash)
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
# using boltspec, when the runner is called it changes the inventory_hash dropping the version field. The clone works around this
|
223
|
-
bolt_result = run_task('puppet_agent::install', targets, params, config: DEFAULT_CONFIG_DATA, inventory: inventory_hash.clone)
|
224
|
-
raise_bolt_errors(bolt_result, 'Installation of agent failed.')
|
225
|
-
bolt_result
|
226
|
-
end
|
133
|
+
include ::BoltSpec::Run
|
134
|
+
params = if collection.nil?
|
135
|
+
{}
|
136
|
+
else
|
137
|
+
{ 'collection' => collection }
|
138
|
+
end
|
139
|
+
raise "puppet_agent was not found in #{DEFAULT_CONFIG_DATA['modulepath']}, please amend the .fixtures.yml file" \
|
140
|
+
unless File.directory?(File.join(DEFAULT_CONFIG_DATA['modulepath'], 'puppet_agent'))
|
141
|
+
|
142
|
+
# using boltspec, when the runner is called it changes the inventory_hash dropping the version field. The clone works around this
|
143
|
+
bolt_result = run_task('puppet_agent::install', targets, params, config: DEFAULT_CONFIG_DATA, inventory: inventory_hash.clone)
|
144
|
+
raise_bolt_errors(bolt_result, 'Installation of agent failed.')
|
145
|
+
bolt_result
|
227
146
|
end
|
228
147
|
|
229
148
|
def configure_path(inventory_hash)
|
@@ -297,32 +216,24 @@ module PuppetLitmus::RakeHelper
|
|
297
216
|
# @param ignore_dependencies [Boolean] flag used to ignore module dependencies defaults to false.
|
298
217
|
# @return a bolt result
|
299
218
|
def install_module(inventory_hash, target_node_name, module_tar, module_repository = nil, ignore_dependencies = false) # rubocop:disable Style/OptionalBooleanParameter
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
install_module_command = "puppet module install #{module_repository_opts} #{File.basename(module_tar)}"
|
319
|
-
install_module_command += ' --ignore-dependencies --force' if ignore_dependencies.to_s.casecmp('true').zero?
|
320
|
-
span.add_field('litmus.install_module_command', install_module_command)
|
321
|
-
|
322
|
-
bolt_result = run_command(install_module_command, target_nodes, config: nil, inventory: inventory_hash.clone)
|
323
|
-
raise_bolt_errors(bolt_result, "Installation of package #{File.basename(module_tar)} failed.")
|
324
|
-
bolt_result
|
325
|
-
end
|
219
|
+
# make sure the module to install is not installed
|
220
|
+
# otherwise `puppet module install` might silently skip it
|
221
|
+
module_name = File.basename(module_tar, '.tar.gz').split('-', 3)[0..1].join('-')
|
222
|
+
uninstall_module(inventory_hash.clone, target_node_name, module_name, force: true)
|
223
|
+
|
224
|
+
include ::BoltSpec::Run
|
225
|
+
|
226
|
+
target_nodes = find_targets(inventory_hash, target_node_name)
|
227
|
+
bolt_result = upload_file(module_tar, File.basename(module_tar), target_nodes, options: {}, config: nil, inventory: inventory_hash.clone)
|
228
|
+
raise_bolt_errors(bolt_result, 'Failed to upload module.')
|
229
|
+
|
230
|
+
module_repository_opts = "--module_repository '#{module_repository}'" unless module_repository.nil?
|
231
|
+
install_module_command = "puppet module install #{module_repository_opts} #{File.basename(module_tar)}"
|
232
|
+
install_module_command += ' --ignore-dependencies --force' if ignore_dependencies.to_s.casecmp('true').zero?
|
233
|
+
|
234
|
+
bolt_result = run_command(install_module_command, target_nodes, config: nil, inventory: inventory_hash.clone)
|
235
|
+
raise_bolt_errors(bolt_result, "Installation of package #{File.basename(module_tar)} failed.")
|
236
|
+
bolt_result
|
326
237
|
end
|
327
238
|
|
328
239
|
def metadata_module_name
|
@@ -353,33 +264,23 @@ module PuppetLitmus::RakeHelper
|
|
353
264
|
end
|
354
265
|
|
355
266
|
def check_connectivity?(inventory_hash, target_node_name)
|
356
|
-
|
357
|
-
|
358
|
-
# if we're only checking connectivity for a single node
|
359
|
-
if target_node_name
|
360
|
-
span.add_field('litmus.target_node_name', target_node_name)
|
361
|
-
add_platform_field(inventory_hash, target_node_name)
|
362
|
-
end
|
267
|
+
# if we're only checking connectivity for a single node
|
268
|
+
add_platform_field(inventory_hash, target_node_name) if target_node_name
|
363
269
|
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
span.add_field('litmus.target_nodes', target_nodes)
|
368
|
-
|
369
|
-
results = run_command('cd .', target_nodes, config: nil, inventory: inventory_hash)
|
370
|
-
span.add_field('litmus.bolt_result', results)
|
371
|
-
failed = []
|
372
|
-
results.reject { |r| r['status'] == 'success' }.each do |result|
|
373
|
-
puts "Failure connecting to #{result['target']}:\n#{result.inspect}"
|
374
|
-
failed.push(result['target'])
|
375
|
-
end
|
376
|
-
span.add_field('litmus.connectivity_success', results.select { |r| r['status'] == 'success' })
|
377
|
-
span.add_field('litmus.connectivity_failure', results.reject { |r| r['status'] == 'success' })
|
378
|
-
raise "Connectivity has failed on: #{failed}" unless failed.empty?
|
270
|
+
include ::BoltSpec::Run
|
271
|
+
target_nodes = find_targets(inventory_hash, target_node_name)
|
272
|
+
puts "Checking connectivity for #{target_nodes.inspect}"
|
379
273
|
|
380
|
-
|
381
|
-
|
274
|
+
results = run_command('cd .', target_nodes, config: nil, inventory: inventory_hash)
|
275
|
+
failed = []
|
276
|
+
results.reject { |r| r['status'] == 'success' }.each do |result|
|
277
|
+
puts "Failure connecting to #{result['target']}:\n#{result.inspect}"
|
278
|
+
failed.push(result['target'])
|
382
279
|
end
|
280
|
+
raise "Connectivity has failed on: #{failed}" unless failed.empty?
|
281
|
+
|
282
|
+
puts 'Connectivity check PASSED.'
|
283
|
+
true
|
383
284
|
end
|
384
285
|
|
385
286
|
def provisioner_task(provisioner)
|
@@ -90,11 +90,8 @@ namespace :litmus do
|
|
90
90
|
results.first['value']['target_names'] || [] # provision_service multi-node provisioning
|
91
91
|
end
|
92
92
|
target_names.each do |target|
|
93
|
-
|
94
|
-
|
95
|
-
with_retries do
|
96
|
-
check_connectivity?(inventory_hash_from_inventory_file, target)
|
97
|
-
end
|
93
|
+
with_retries do
|
94
|
+
check_connectivity?(inventory_hash_from_inventory_file, target)
|
98
95
|
end
|
99
96
|
end
|
100
97
|
ensure
|
@@ -355,7 +352,7 @@ namespace :litmus do
|
|
355
352
|
payloads = []
|
356
353
|
# Generate list of targets to provision
|
357
354
|
targets.each do |target|
|
358
|
-
test = "bundle exec rspec ./spec/acceptance #{tag_value} --format progress
|
355
|
+
test = "bundle exec rspec ./spec/acceptance #{tag_value} --format progress"
|
359
356
|
title = "#{target}, #{facts_from_node(inventory_hash, target)['platform']}"
|
360
357
|
options = {
|
361
358
|
env: {
|
@@ -386,7 +383,6 @@ namespace :litmus do
|
|
386
383
|
at_exit { exit! }
|
387
384
|
|
388
385
|
env = options[:env].nil? ? {} : options[:env]
|
389
|
-
env['HONEYCOMB_TRACE'] = Honeycomb.current_span.to_trace_header
|
390
386
|
stdout, stderr, status = Open3.capture3(env, test)
|
391
387
|
["\n================\n#{title}\n", stdout, stderr, status]
|
392
388
|
end
|
@@ -404,7 +400,6 @@ namespace :litmus do
|
|
404
400
|
spinners = TTY::Spinner::Multi.new("[:spinner] Running against #{targets.size} targets.")
|
405
401
|
payloads.each do |title, test, options|
|
406
402
|
env = options[:env].nil? ? {} : options[:env]
|
407
|
-
env['HONEYCOMB_TRACE'] = Honeycomb.current_span.to_trace_header
|
408
403
|
spinners.register("[:spinner] #{title}") do |sp|
|
409
404
|
stdout, stderr, status = Open3.capture3(env, test)
|
410
405
|
if status.to_i.zero?
|
@@ -41,7 +41,6 @@ RSpec.describe PuppetLitmus::PuppetHelpers do
|
|
41
41
|
it 'passes the --hiera_config flag if the :hiera_config opt is specified' do
|
42
42
|
expect(File).to receive(:exist?).with('spec/fixtures/litmus_inventory.yaml').and_return(false)
|
43
43
|
expect(self).to receive(:target_in_inventory?).and_return(true)
|
44
|
-
expect(self).to receive(:target_in_inventory?).and_return(true)
|
45
44
|
expect(self).to receive(:create_manifest_file).with(manifest).and_return('/bla.pp')
|
46
45
|
expect(self).to receive(:run_command).with(command, 'litmus_localhost', config: nil, inventory: localhost_inventory_hash).and_return(result)
|
47
46
|
apply_manifest(manifest, hiera_config: '/hiera.yaml')
|
@@ -61,7 +60,6 @@ RSpec.describe PuppetLitmus::PuppetHelpers do
|
|
61
60
|
it 'uses detailed-exitcodes with expect_failures' do
|
62
61
|
expect(File).to receive(:exist?).with('spec/fixtures/litmus_inventory.yaml').and_return(false)
|
63
62
|
expect(self).to receive(:target_in_inventory?).and_return(true)
|
64
|
-
expect(self).to receive(:target_in_inventory?).and_return(true)
|
65
63
|
expect(self).to receive(:create_manifest_file).with(manifest).and_return('/bla.pp')
|
66
64
|
expect(self).to receive(:run_command).with(command, 'litmus_localhost', config: nil, inventory: localhost_inventory_hash).and_return(result)
|
67
65
|
expect { apply_manifest(manifest, expect_failures: true) }.to raise_error(RuntimeError)
|
@@ -70,7 +68,6 @@ RSpec.describe PuppetLitmus::PuppetHelpers do
|
|
70
68
|
it 'uses detailed-exitcodes with catch_failures' do
|
71
69
|
expect(File).to receive(:exist?).with('spec/fixtures/litmus_inventory.yaml').and_return(false)
|
72
70
|
expect(self).to receive(:target_in_inventory?).and_return(true)
|
73
|
-
expect(self).to receive(:target_in_inventory?).and_return(true)
|
74
71
|
expect(self).to receive(:create_manifest_file).with(manifest).and_return('/bla.pp')
|
75
72
|
expect(self).to receive(:run_command).with(command, 'litmus_localhost', config: nil, inventory: localhost_inventory_hash).and_return(result)
|
76
73
|
apply_manifest(manifest, catch_failures: true)
|
@@ -79,7 +76,6 @@ RSpec.describe PuppetLitmus::PuppetHelpers do
|
|
79
76
|
it 'uses detailed-exitcodes with expect_changes' do
|
80
77
|
expect(File).to receive(:exist?).with('spec/fixtures/litmus_inventory.yaml').and_return(false)
|
81
78
|
expect(self).to receive(:target_in_inventory?).and_return(true)
|
82
|
-
expect(self).to receive(:target_in_inventory?).and_return(true)
|
83
79
|
expect(self).to receive(:create_manifest_file).with(manifest).and_return('/bla.pp')
|
84
80
|
expect(self).to receive(:run_command).with(command, 'litmus_localhost', config: nil, inventory: localhost_inventory_hash).and_return(result)
|
85
81
|
expect { apply_manifest(manifest, expect_changes: true) }.to raise_error(RuntimeError)
|
@@ -88,7 +84,6 @@ RSpec.describe PuppetLitmus::PuppetHelpers do
|
|
88
84
|
it 'uses detailed-exitcodes with catch_changes' do
|
89
85
|
expect(File).to receive(:exist?).with('spec/fixtures/litmus_inventory.yaml').and_return(false)
|
90
86
|
expect(self).to receive(:target_in_inventory?).and_return(true)
|
91
|
-
expect(self).to receive(:target_in_inventory?).and_return(true)
|
92
87
|
expect(self).to receive(:create_manifest_file).with(manifest).and_return('/bla.pp')
|
93
88
|
expect(self).to receive(:run_command).with(command, 'litmus_localhost', config: nil, inventory: localhost_inventory_hash).and_return(result)
|
94
89
|
apply_manifest(manifest, catch_changes: true)
|
@@ -114,7 +109,6 @@ RSpec.describe PuppetLitmus::PuppetHelpers do
|
|
114
109
|
stub_const('ENV', ENV.to_hash.merge('TARGET_HOST' => 'localhost'))
|
115
110
|
expect(File).to receive(:exist?).with('spec/fixtures/litmus_inventory.yaml').and_return(false)
|
116
111
|
expect(self).to receive(:target_in_inventory?).and_return(true)
|
117
|
-
expect(self).to receive(:target_in_inventory?).and_return(true)
|
118
112
|
expect(self).to receive(:run_command).with(command_to_run, 'litmus_localhost', config: nil, inventory: localhost_inventory_hash).and_return(result)
|
119
113
|
expect { run_shell(command_to_run) }.not_to raise_error
|
120
114
|
end
|
@@ -126,7 +120,6 @@ RSpec.describe PuppetLitmus::PuppetHelpers do
|
|
126
120
|
expect(File).to receive(:exist?).with('spec/fixtures/litmus_inventory.yaml').and_return(true)
|
127
121
|
expect(self).to receive(:inventory_hash_from_inventory_file).and_return(inventory_hash)
|
128
122
|
expect(self).to receive(:target_in_inventory?).and_return(true)
|
129
|
-
expect(self).to receive(:target_in_inventory?).and_return(true)
|
130
123
|
expect(self).to receive(:run_command).with(command_to_run, 'some.host', config: nil, inventory: inventory_hash).and_return(result)
|
131
124
|
expect { run_shell(command_to_run) }.not_to raise_error
|
132
125
|
end
|
@@ -152,7 +145,6 @@ RSpec.describe PuppetLitmus::PuppetHelpers do
|
|
152
145
|
expect(File).to receive(:exist?).with('spec/fixtures/litmus_inventory.yaml').and_return(true)
|
153
146
|
expect(self).to receive(:inventory_hash_from_inventory_file).and_return(inventory_hash)
|
154
147
|
expect(self).to receive(:target_in_inventory?).and_return(true)
|
155
|
-
expect(self).to receive(:target_in_inventory?).and_return(true)
|
156
148
|
expect(self).to receive(:upload_file).with(local, remote, 'some.host', options: {}, config: nil, inventory: inventory_hash).and_return(result_success)
|
157
149
|
expect { bolt_upload_file(local, remote) }.not_to raise_error
|
158
150
|
end
|
@@ -162,7 +154,6 @@ RSpec.describe PuppetLitmus::PuppetHelpers do
|
|
162
154
|
expect(File).to receive(:exist?).with('spec/fixtures/litmus_inventory.yaml').and_return(false)
|
163
155
|
expect(self).not_to receive(:inventory_hash_from_inventory_file)
|
164
156
|
expect(self).to receive(:target_in_inventory?).and_return(true)
|
165
|
-
expect(self).to receive(:target_in_inventory?).and_return(true)
|
166
157
|
expect(self).to receive(:upload_file).with(local, remote, 'litmus_localhost', options: {}, config: nil, inventory: localhost_inventory_hash).and_return(result_success)
|
167
158
|
expect { bolt_upload_file(local, remote) }.not_to raise_error
|
168
159
|
end
|
@@ -174,7 +165,6 @@ RSpec.describe PuppetLitmus::PuppetHelpers do
|
|
174
165
|
expect(File).to receive(:exist?).with('spec/fixtures/litmus_inventory.yaml').and_return(true)
|
175
166
|
expect(self).to receive(:inventory_hash_from_inventory_file).and_return(inventory_hash)
|
176
167
|
expect(self).to receive(:target_in_inventory?).and_return(true)
|
177
|
-
expect(self).to receive(:target_in_inventory?).and_return(true)
|
178
168
|
expect(self).to receive(:upload_file).with(local, remote, 'some.host', options: {}, config: nil, inventory: inventory_hash).and_return(result_failure)
|
179
169
|
expect { bolt_upload_file(local, remote) }.to raise_error(RuntimeError, /upload file failed/)
|
180
170
|
end
|
@@ -184,7 +174,6 @@ RSpec.describe PuppetLitmus::PuppetHelpers do
|
|
184
174
|
expect(File).to receive(:exist?).with('spec/fixtures/litmus_inventory.yaml').and_return(true)
|
185
175
|
expect(self).to receive(:inventory_hash_from_inventory_file).and_return(inventory_hash)
|
186
176
|
expect(self).to receive(:target_in_inventory?).and_return(true)
|
187
|
-
expect(self).to receive(:target_in_inventory?).and_return(true)
|
188
177
|
expect(self).to receive(:upload_file).with(local, remote, 'some.host', options: {}, config: nil, inventory: inventory_hash).and_return(result_failure)
|
189
178
|
method_result = bolt_upload_file(local, remote, expect_failures: true)
|
190
179
|
expect(method_result.exit_code).to be(255)
|
@@ -207,7 +196,6 @@ RSpec.describe PuppetLitmus::PuppetHelpers do
|
|
207
196
|
expect(File).to receive(:exist?).with('spec/fixtures/litmus_inventory.yaml').and_return(false)
|
208
197
|
expect(self).not_to receive(:inventory_hash_from_inventory_file)
|
209
198
|
expect(self).to receive(:target_in_inventory?).and_return(true)
|
210
|
-
expect(self).to receive(:target_in_inventory?).and_return(true)
|
211
199
|
expect(self).to receive(:run_script).with(script, 'litmus_localhost', [], options: {}, config: nil, inventory: localhost_inventory_hash).and_return(result)
|
212
200
|
expect { bolt_run_script(script) }.not_to raise_error
|
213
201
|
end
|
@@ -219,7 +207,6 @@ RSpec.describe PuppetLitmus::PuppetHelpers do
|
|
219
207
|
expect(File).to receive(:exist?).with('spec/fixtures/litmus_inventory.yaml').and_return(true)
|
220
208
|
expect(self).to receive(:inventory_hash_from_inventory_file).and_return(inventory_hash)
|
221
209
|
expect(self).to receive(:target_in_inventory?).and_return(true)
|
222
|
-
expect(self).to receive(:target_in_inventory?).and_return(true)
|
223
210
|
expect(self).to receive(:run_script).with(script, 'some.host', [], options: {}, config: nil, inventory: inventory_hash).and_return(result)
|
224
211
|
expect { bolt_run_script(script) }.not_to raise_error
|
225
212
|
end
|
@@ -231,7 +218,6 @@ RSpec.describe PuppetLitmus::PuppetHelpers do
|
|
231
218
|
expect(File).to receive(:exist?).with('spec/fixtures/litmus_inventory.yaml').and_return(false)
|
232
219
|
expect(self).not_to receive(:inventory_hash_from_inventory_file)
|
233
220
|
expect(self).to receive(:target_in_inventory?).and_return(true)
|
234
|
-
expect(self).to receive(:target_in_inventory?).and_return(true)
|
235
221
|
expect(self).to receive(:run_script).with(script, 'litmus_localhost', ['doot'], options: {}, config: nil, inventory: localhost_inventory_hash).and_return(result)
|
236
222
|
expect { bolt_run_script(script, arguments: ['doot']) }.not_to raise_error
|
237
223
|
end
|
@@ -259,7 +245,6 @@ RSpec.describe PuppetLitmus::PuppetHelpers do
|
|
259
245
|
expect(File).to receive(:exist?).with('spec/fixtures/litmus_inventory.yaml').and_return(true)
|
260
246
|
expect(self).to receive(:inventory_hash_from_inventory_file).and_return(inventory_hash)
|
261
247
|
expect(self).to receive(:target_in_inventory?).and_return(true)
|
262
|
-
expect(self).to receive(:target_in_inventory?).and_return(true)
|
263
248
|
expect(self).to receive(:run_task).with(task_name, 'some.host', params, config: config_data, inventory: inventory_hash).and_return(result_unstructured_task_success)
|
264
249
|
expect { run_bolt_task(task_name, params, opts: {}) }.not_to raise_error
|
265
250
|
end
|
@@ -269,7 +254,6 @@ RSpec.describe PuppetLitmus::PuppetHelpers do
|
|
269
254
|
expect(File).to receive(:exist?).with('jim.yaml').and_return(true)
|
270
255
|
expect(self).to receive(:inventory_hash_from_inventory_file).and_return(inventory_hash)
|
271
256
|
expect(self).to receive(:target_in_inventory?).and_return(true)
|
272
|
-
expect(self).to receive(:target_in_inventory?).and_return(true)
|
273
257
|
expect(self).to receive(:run_task).with(task_name, 'some.host', params, config: config_data, inventory: inventory_hash).and_return(result_unstructured_task_success)
|
274
258
|
expect { run_bolt_task(task_name, params, inventory_file: 'jim.yaml') }.not_to raise_error
|
275
259
|
end
|
@@ -279,7 +263,6 @@ RSpec.describe PuppetLitmus::PuppetHelpers do
|
|
279
263
|
expect(File).to receive(:exist?).with('spec/fixtures/litmus_inventory.yaml').and_return(true)
|
280
264
|
expect(self).to receive(:inventory_hash_from_inventory_file).and_return(inventory_hash)
|
281
265
|
expect(self).to receive(:target_in_inventory?).and_return(true)
|
282
|
-
expect(self).to receive(:target_in_inventory?).and_return(true)
|
283
266
|
expect(self).to receive(:run_task).with(task_name, 'some.host', params, config: config_data, inventory: inventory_hash).and_return(result_unstructured_task_success)
|
284
267
|
method_result = run_bolt_task(task_name, params, opts: {})
|
285
268
|
expect(method_result.stdout).to eq('SUCCESS!')
|
@@ -290,7 +273,6 @@ RSpec.describe PuppetLitmus::PuppetHelpers do
|
|
290
273
|
expect(File).to receive(:exist?).with('spec/fixtures/litmus_inventory.yaml').and_return(true)
|
291
274
|
expect(self).to receive(:inventory_hash_from_inventory_file).and_return(inventory_hash)
|
292
275
|
expect(self).to receive(:target_in_inventory?).and_return(true)
|
293
|
-
expect(self).to receive(:target_in_inventory?).and_return(true)
|
294
276
|
expect(self).to receive(:run_task).with(task_name, 'some.host', params, config: config_data, inventory: inventory_hash).and_return(result_structured_task_success)
|
295
277
|
method_result = run_bolt_task(task_name, params, opts: {})
|
296
278
|
expect(method_result.stdout).to eq('{"key1"=>"foo", "key2"=>"bar"}')
|
@@ -305,7 +287,6 @@ RSpec.describe PuppetLitmus::PuppetHelpers do
|
|
305
287
|
expect(File).to receive(:exist?).with('spec/fixtures/litmus_inventory.yaml').and_return(true)
|
306
288
|
expect(self).to receive(:inventory_hash_from_inventory_file).and_return(inventory_hash)
|
307
289
|
expect(self).to receive(:target_in_inventory?).and_return(true)
|
308
|
-
expect(self).to receive(:target_in_inventory?).and_return(true)
|
309
290
|
expect(self).to receive(:run_task).with(task_name, 'some.host', params, config: config_data, inventory: inventory_hash).and_return(result_failure)
|
310
291
|
expect { run_bolt_task(task_name, params, opts: {}) }.to raise_error(RuntimeError, /task failed/)
|
311
292
|
end
|
@@ -315,7 +296,6 @@ RSpec.describe PuppetLitmus::PuppetHelpers do
|
|
315
296
|
expect(File).to receive(:exist?).with('spec/fixtures/litmus_inventory.yaml').and_return(true)
|
316
297
|
expect(self).to receive(:inventory_hash_from_inventory_file).and_return(inventory_hash)
|
317
298
|
expect(self).to receive(:target_in_inventory?).and_return(true)
|
318
|
-
expect(self).to receive(:target_in_inventory?).and_return(true)
|
319
299
|
expect(self).to receive(:run_task).with(task_name, 'some.host', params, config: config_data, inventory: inventory_hash).and_return(result_failure)
|
320
300
|
method_result = run_bolt_task(task_name, params, expect_failures: true)
|
321
301
|
expect(method_result.exit_code).to be(123)
|
@@ -78,7 +78,7 @@ describe 'litmus rake tasks' do
|
|
78
78
|
allow_any_instance_of(PuppetLitmus::InventoryManipulation).to receive(:inventory_hash_from_inventory_file).with(any_args).and_return({})
|
79
79
|
allow_any_instance_of(PuppetLitmus::RakeHelper).to receive(:check_connectivity?).with(any_args).and_return(true)
|
80
80
|
|
81
|
-
expect { Rake::Task['litmus:provision'].invoke('docker', 'centos:7') }.to output(expected_output).to_stdout
|
81
|
+
expect { Rake::Task['litmus:provision'].invoke('docker', 'centos:7') }.to output(/#{expected_output}/).to_stdout
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puppet_litmus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Puppet, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-04
|
11
|
+
date: 2023-05-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bolt
|
@@ -44,20 +44,6 @@ dependencies:
|
|
44
44
|
- - "<"
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: 3.0.0
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: honeycomb-beeline
|
49
|
-
requirement: !ruby/object:Gem::Requirement
|
50
|
-
requirements:
|
51
|
-
- - ">="
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '0'
|
54
|
-
type: :runtime
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
requirements:
|
58
|
-
- - ">="
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
version: '0'
|
61
47
|
- !ruby/object:Gem::Dependency
|
62
48
|
name: parallel
|
63
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,20 +100,6 @@ dependencies:
|
|
114
100
|
- - ">="
|
115
101
|
- !ruby/object:Gem::Version
|
116
102
|
version: '0'
|
117
|
-
- !ruby/object:Gem::Dependency
|
118
|
-
name: rspec_honeycomb_formatter
|
119
|
-
requirement: !ruby/object:Gem::Requirement
|
120
|
-
requirements:
|
121
|
-
- - ">="
|
122
|
-
- !ruby/object:Gem::Version
|
123
|
-
version: '0'
|
124
|
-
type: :runtime
|
125
|
-
prerelease: false
|
126
|
-
version_requirements: !ruby/object:Gem::Requirement
|
127
|
-
requirements:
|
128
|
-
- - ">="
|
129
|
-
- !ruby/object:Gem::Version
|
130
|
-
version: '0'
|
131
103
|
- !ruby/object:Gem::Dependency
|
132
104
|
name: tty-spinner
|
133
105
|
requirement: !ruby/object:Gem::Requirement
|