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