bolt 0.8.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of bolt might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/bolt/cli.rb +31 -21
- data/lib/bolt/config.rb +1 -0
- data/lib/bolt/error.rb +28 -0
- data/lib/bolt/executor.rb +10 -6
- data/lib/bolt/node.rb +7 -5
- data/lib/bolt/node/errors.rb +25 -3
- data/lib/bolt/node/orch.rb +7 -16
- data/lib/bolt/node/output.rb +17 -0
- data/lib/bolt/node/ssh.rb +101 -44
- data/lib/bolt/node/winrm.rb +86 -40
- data/lib/bolt/outputter/human.rb +65 -8
- data/lib/bolt/outputter/json.rb +8 -1
- data/lib/bolt/result.rb +74 -124
- data/lib/bolt/version.rb +1 -1
- data/{vendored/puppet → modules/boltlib}/lib/puppet/functions/file_upload.rb +9 -7
- data/{vendored/puppet → modules/boltlib}/lib/puppet/functions/run_command.rb +8 -9
- data/{vendored/puppet → modules/boltlib}/lib/puppet/functions/run_plan.rb +8 -12
- data/{vendored/puppet → modules/boltlib}/lib/puppet/functions/run_script.rb +12 -8
- data/{vendored/puppet → modules/boltlib}/lib/puppet/functions/run_task.rb +10 -10
- data/vendored/puppet/lib/puppet/agent.rb +1 -1
- data/vendored/puppet/lib/puppet/application/lookup.rb +1 -3
- data/vendored/puppet/lib/puppet/configurer.rb +2 -3
- data/vendored/puppet/lib/puppet/configurer/plugin_handler.rb +25 -7
- data/vendored/puppet/lib/puppet/defaults.rb +9 -1
- data/vendored/puppet/lib/puppet/face/epp.rb +4 -2
- data/vendored/puppet/lib/puppet/face/module/build.rb +1 -1
- data/vendored/puppet/lib/puppet/face/module/list.rb +5 -16
- data/vendored/puppet/lib/puppet/face/module/uninstall.rb +14 -3
- data/vendored/puppet/lib/puppet/face/plugin.rb +1 -3
- data/vendored/puppet/lib/puppet/forge/errors.rb +17 -7
- data/vendored/puppet/lib/puppet/functions.rb +8 -6
- data/vendored/puppet/lib/puppet/functions/each.rb +10 -4
- data/vendored/puppet/lib/puppet/functions/lookup.rb +2 -2
- data/vendored/puppet/lib/puppet/functions/map.rb +12 -2
- data/vendored/puppet/lib/puppet/functions/slice.rb +2 -3
- data/vendored/puppet/lib/puppet/graph/simple_graph.rb +9 -5
- data/vendored/puppet/lib/puppet/interface.rb +1 -0
- data/vendored/puppet/lib/puppet/module_tool/errors/installer.rb +27 -17
- data/vendored/puppet/lib/puppet/module_tool/errors/shared.rb +143 -63
- data/vendored/puppet/lib/puppet/module_tool/errors/uninstaller.rb +37 -14
- data/vendored/puppet/lib/puppet/module_tool/errors/upgrader.rb +30 -18
- data/vendored/puppet/lib/puppet/network/auth_config_parser.rb +8 -8
- data/vendored/puppet/lib/puppet/network/http/error.rb +7 -7
- data/vendored/puppet/lib/puppet/network/http/rack.rb +2 -2
- data/vendored/puppet/lib/puppet/network/http/webrick.rb +1 -1
- data/vendored/puppet/lib/puppet/node.rb +10 -0
- data/vendored/puppet/lib/puppet/node/facts.rb +9 -0
- data/vendored/puppet/lib/puppet/parameter/value_collection.rb +16 -6
- data/vendored/puppet/lib/puppet/parser/resource.rb +103 -31
- data/vendored/puppet/lib/puppet/pops/evaluator/access_operator.rb +13 -0
- data/vendored/puppet/lib/puppet/pops/evaluator/evaluator_impl.rb +22 -6
- data/vendored/puppet/lib/puppet/pops/loader/static_loader.rb +1 -1
- data/vendored/puppet/lib/puppet/pops/lookup/lookup_adapter.rb +13 -4
- data/vendored/puppet/lib/puppet/pops/model/ast_transformer.rb +1 -1
- data/vendored/puppet/lib/puppet/pops/parser/eparser.rb +527 -529
- data/vendored/puppet/lib/puppet/pops/serialization/abstract_reader.rb +4 -0
- data/vendored/puppet/lib/puppet/pops/serialization/abstract_writer.rb +6 -0
- data/vendored/puppet/lib/puppet/pops/serialization/extension.rb +1 -0
- data/vendored/puppet/lib/puppet/pops/serialization/serializer.rb +2 -1
- data/vendored/puppet/lib/puppet/pops/types/execution_result.rb +8 -0
- data/vendored/puppet/lib/puppet/pops/types/iterable.rb +2 -0
- data/vendored/puppet/lib/puppet/pops/types/p_object_type.rb +3 -0
- data/vendored/puppet/lib/puppet/pops/types/p_object_type_extension.rb +6 -0
- data/vendored/puppet/lib/puppet/pops/types/p_uri_type.rb +191 -0
- data/vendored/puppet/lib/puppet/pops/types/string_converter.rb +17 -0
- data/vendored/puppet/lib/puppet/pops/types/type_calculator.rb +5 -0
- data/vendored/puppet/lib/puppet/pops/types/type_factory.rb +7 -0
- data/vendored/puppet/lib/puppet/pops/types/type_formatter.rb +16 -18
- data/vendored/puppet/lib/puppet/pops/types/type_mismatch_describer.rb +15 -5
- data/vendored/puppet/lib/puppet/pops/types/type_parser.rb +6 -0
- data/vendored/puppet/lib/puppet/pops/types/type_with_members.rb +43 -0
- data/vendored/puppet/lib/puppet/pops/types/types.rb +3 -0
- data/vendored/puppet/lib/puppet/provider/package/gem.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/package/nim.rb +7 -8
- data/vendored/puppet/lib/puppet/provider/package/opkg.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/package/pkg.rb +6 -4
- data/vendored/puppet/lib/puppet/provider/package/pkgutil.rb +3 -3
- data/vendored/puppet/lib/puppet/provider/service/init.rb +1 -1
- data/vendored/puppet/lib/puppet/syntax_checkers/base64.rb +5 -6
- data/vendored/puppet/lib/puppet/transaction.rb +1 -1
- data/vendored/puppet/lib/puppet/type.rb +1 -9
- data/vendored/puppet/lib/puppet/type/schedule.rb +1 -1
- data/vendored/puppet/lib/puppet/util/log.rb +2 -3
- data/vendored/puppet/lib/puppet/util/plist.rb +1 -1
- data/vendored/puppet/lib/puppet/util/reference.rb +2 -3
- data/vendored/puppet/lib/puppet_pal.rb +326 -53
- metadata +28 -12
- data/lib/bolt/node/result.rb +0 -115
- data/vendored/puppet/lib/puppet/configurer/downloader_factory.rb +0 -44
data/lib/bolt/node/winrm.rb
CHANGED
@@ -38,7 +38,7 @@ module Bolt
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def shell_init
|
41
|
-
return
|
41
|
+
return nil if @shell_initialized
|
42
42
|
result = execute(<<-PS)
|
43
43
|
|
44
44
|
$ENV:PATH += ";${ENV:ProgramFiles}\\Puppet Labs\\Puppet\\bin\\;" +
|
@@ -141,13 +141,14 @@ function Invoke-Interpreter
|
|
141
141
|
}
|
142
142
|
}
|
143
143
|
PS
|
144
|
+
if result.exit_code != 0
|
145
|
+
raise BaseError.new("Could not initialize shell: #{result.stderr.string}", "SHELL_INIT_ERROR")
|
146
|
+
end
|
144
147
|
@shell_initialized = true
|
145
|
-
|
146
|
-
result
|
147
148
|
end
|
148
149
|
|
149
150
|
def execute(command, _ = {})
|
150
|
-
result_output = Bolt::Node::
|
151
|
+
result_output = Bolt::Node::Output.new
|
151
152
|
|
152
153
|
@logger.debug { "Executing command: #{command}" }
|
153
154
|
|
@@ -157,13 +158,13 @@ PS
|
|
157
158
|
result_output.stderr << stderr
|
158
159
|
@logger.debug { "stderr: #{stderr}" }
|
159
160
|
end
|
161
|
+
result_output.exit_code = output.exitcode
|
160
162
|
if output.exitcode.zero?
|
161
163
|
@logger.debug { "Command returned successfully" }
|
162
|
-
Bolt::Node::Success.new(result_output.stdout.string, result_output)
|
163
164
|
else
|
164
165
|
@logger.info { "Command failed with exit code #{output.exitcode}" }
|
165
|
-
Bolt::Node::Failure.new(output.exitcode, result_output)
|
166
166
|
end
|
167
|
+
result_output
|
167
168
|
end
|
168
169
|
|
169
170
|
# 10 minutes in seconds
|
@@ -199,6 +200,10 @@ PS
|
|
199
200
|
-NoProfile -NonInteractive -NoLogo -ExecutionPolicy Bypass
|
200
201
|
].freeze
|
201
202
|
|
203
|
+
def powershell_file?(path)
|
204
|
+
Pathname(path).extname.casecmp('.ps1').zero?
|
205
|
+
end
|
206
|
+
|
202
207
|
def process_from_extension(path)
|
203
208
|
case Pathname(path).extname.downcase
|
204
209
|
when '.rb'
|
@@ -220,12 +225,18 @@ PS
|
|
220
225
|
end
|
221
226
|
|
222
227
|
def _upload(source, destination)
|
228
|
+
write_remote_file(source, destination)
|
229
|
+
Bolt::Result.new
|
230
|
+
# TODO: we should rely on the executor for this
|
231
|
+
rescue StandardError => ex
|
232
|
+
Bolt::Result.from_exception(ex)
|
233
|
+
end
|
234
|
+
|
235
|
+
def write_remote_file(source, destination)
|
223
236
|
@logger.debug { "Uploading #{source} to #{destination}" }
|
224
237
|
fs = ::WinRM::FS::FileManager.new(@connection)
|
238
|
+
# TODO: raise FileError here if this fails
|
225
239
|
fs.upload(source, destination)
|
226
|
-
Bolt::Node::Success.new
|
227
|
-
rescue StandardError => ex
|
228
|
-
Bolt::Node::ExceptionFailure.new(ex)
|
229
240
|
end
|
230
241
|
|
231
242
|
def make_tempdir
|
@@ -236,46 +247,71 @@ $path = Join-Path $parent $name
|
|
236
247
|
New-Item -ItemType Directory -Path $path | Out-Null
|
237
248
|
$path
|
238
249
|
PS
|
239
|
-
result.
|
250
|
+
if result.exit_code != 0
|
251
|
+
raise FileError.new("Could not make tempdir: #{result.stderr}", 'TEMPDIR_ERROR')
|
252
|
+
end
|
253
|
+
result.stdout.string.chomp
|
240
254
|
end
|
241
255
|
|
242
256
|
def with_remote_file(file)
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
ext = VALID_EXTENSIONS.include?(ext) ? ext : '.ps1'
|
251
|
-
dest = "#{dir}\\#{File.basename(file, '.*')}#{ext}"
|
252
|
-
Bolt::Node::Success.new
|
253
|
-
end.then do
|
254
|
-
_upload(file, dest)
|
255
|
-
end.then do
|
257
|
+
ext = File.extname(file)
|
258
|
+
ext = VALID_EXTENSIONS.include?(ext) ? ext : '.ps1'
|
259
|
+
file_base = File.basename(file, '.*')
|
260
|
+
dir = make_tempdir
|
261
|
+
dest = "#{dir}\\#{file_base}#{ext}"
|
262
|
+
begin
|
263
|
+
write_remote_file(file, dest)
|
256
264
|
shell_init
|
257
|
-
|
258
|
-
|
259
|
-
end.then do
|
265
|
+
yield dest
|
266
|
+
ensure
|
260
267
|
execute(<<-PS)
|
261
268
|
Remove-Item -Force "#{dest}"
|
262
269
|
Remove-Item -Force "#{dir}"
|
263
270
|
PS
|
264
|
-
result
|
265
271
|
end
|
266
272
|
end
|
267
273
|
|
268
274
|
def _run_command(command)
|
269
|
-
execute(command)
|
275
|
+
output = execute(command)
|
276
|
+
Bolt::CommandResult.from_output(output)
|
277
|
+
# TODO: we should rely on the executor for this
|
278
|
+
rescue StandardError => e
|
279
|
+
Bolt::Result.from_exception(e)
|
270
280
|
end
|
271
281
|
|
272
282
|
def _run_script(script, arguments)
|
273
283
|
@logger.info { "Running script '#{script}'" }
|
274
284
|
with_remote_file(script) do |remote_path|
|
275
|
-
|
276
|
-
|
277
|
-
|
285
|
+
if powershell_file?(remote_path)
|
286
|
+
mapped_args = arguments.map do |a|
|
287
|
+
"$invokeArgs.ArgumentList += @'\n#{a}\n'@"
|
288
|
+
end.join("\n")
|
289
|
+
output = execute(<<-PS)
|
290
|
+
$invokeArgs = @{
|
291
|
+
ScriptBlock = (Get-Command "#{remote_path}").ScriptBlock
|
292
|
+
ArgumentList = @()
|
293
|
+
}
|
294
|
+
#{mapped_args}
|
295
|
+
|
296
|
+
try
|
297
|
+
{
|
298
|
+
Invoke-Command @invokeArgs
|
299
|
+
}
|
300
|
+
catch
|
301
|
+
{
|
302
|
+
exit 1
|
303
|
+
}
|
304
|
+
PS
|
305
|
+
else
|
306
|
+
path, args = *process_from_extension(remote_path)
|
307
|
+
args += escape_arguments(arguments)
|
308
|
+
output = execute_process(path, args)
|
309
|
+
end
|
310
|
+
Bolt::CommandResult.from_output(output)
|
278
311
|
end
|
312
|
+
# TODO: we should rely on the executor for this
|
313
|
+
rescue StandardError => e
|
314
|
+
Bolt::Result.from_exception(e)
|
279
315
|
end
|
280
316
|
|
281
317
|
def _run_task(task, input_method, arguments)
|
@@ -287,20 +323,30 @@ PS
|
|
287
323
|
end
|
288
324
|
|
289
325
|
if ENVIRONMENT_METHODS.include?(input_method)
|
290
|
-
arguments.
|
291
|
-
|
292
|
-
|
293
|
-
|
326
|
+
arguments.each do |(arg, val)|
|
327
|
+
cmd = "[Environment]::SetEnvironmentVariable('PT_#{arg}', '#{val}')"
|
328
|
+
result = execute(cmd)
|
329
|
+
if result.exit_code != 0
|
330
|
+
raise EnvironmentVarError(var, value)
|
294
331
|
end
|
295
332
|
end
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
333
|
+
end
|
334
|
+
|
335
|
+
with_remote_file(task) do |remote_path|
|
336
|
+
if powershell_file?(remote_path) && stdin.nil?
|
337
|
+
# NOTE: cannot redirect STDIN to a .ps1 script inside of PowerShell
|
338
|
+
# must create new powershell.exe process like other interpreters
|
339
|
+
# fortunately, using PS with stdin input_method should never happen
|
340
|
+
output = execute("try { &""#{remote_path}"" } catch { exit 1 }")
|
341
|
+
else
|
300
342
|
path, args = *process_from_extension(remote_path)
|
301
|
-
execute_process(path, args, stdin)
|
343
|
+
output = execute_process(path, args, stdin)
|
302
344
|
end
|
345
|
+
Bolt::TaskResult.from_output(output)
|
303
346
|
end
|
347
|
+
# TODO: we should rely on the executor for this
|
348
|
+
rescue StandardError => e
|
349
|
+
Bolt::Result.from_exception(e)
|
304
350
|
end
|
305
351
|
|
306
352
|
def escape_arguments(arguments)
|
data/lib/bolt/outputter/human.rb
CHANGED
@@ -1,22 +1,79 @@
|
|
1
1
|
module Bolt
|
2
2
|
class Outputter
|
3
3
|
class Human < Bolt::Outputter
|
4
|
+
COLORS = { red: "31",
|
5
|
+
green: "32",
|
6
|
+
yellow: "33" }.freeze
|
7
|
+
|
4
8
|
def print_head; end
|
5
9
|
|
10
|
+
def colorize(color, string)
|
11
|
+
if @stream.isatty
|
12
|
+
"\033[#{COLORS[color]}m#{string}\033[0m"
|
13
|
+
else
|
14
|
+
string
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def indent(indent, string)
|
19
|
+
indent = ' ' * indent
|
20
|
+
string.gsub(/^/, indent.to_s)
|
21
|
+
end
|
22
|
+
|
23
|
+
def remove_trail(string)
|
24
|
+
string.sub(/\s\z/, '')
|
25
|
+
end
|
26
|
+
|
27
|
+
def print_event(node, event)
|
28
|
+
case event[:type]
|
29
|
+
when :node_start
|
30
|
+
print_start(node)
|
31
|
+
when :node_result
|
32
|
+
print_result(node, event[:result])
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def print_start(node)
|
37
|
+
@stream.puts(colorize(:green, "Started on #{node.host}..."))
|
38
|
+
end
|
39
|
+
|
6
40
|
def print_result(node, result)
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
41
|
+
if result.success?
|
42
|
+
@stream.puts(colorize(:green, "Finished on #{node.host}:"))
|
43
|
+
else
|
44
|
+
@stream.puts(colorize(:red, "Failed on #{node.host}:"))
|
45
|
+
end
|
46
|
+
|
47
|
+
if result.error
|
48
|
+
if result.error['msg']
|
49
|
+
@stream.puts(colorize(:red, remove_trail(indent(2, result.error['msg']))))
|
50
|
+
else
|
51
|
+
@stream.puts(colorize(:red, remove_trail(indent(2, result.error))))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
if result.message
|
56
|
+
@stream.puts(remove_trail(indent(2, result.message)))
|
57
|
+
end
|
58
|
+
|
59
|
+
if result.instance_of? Bolt::TaskResult
|
60
|
+
@stream.puts(indent(2, ::JSON.pretty_generate(result.value)))
|
61
|
+
elsif result.instance_of? Bolt::CommandResult
|
62
|
+
unless result.stdout.strip.empty?
|
63
|
+
@stream.puts(indent(2, "STDOUT:"))
|
64
|
+
@stream.puts(indent(4, result.stdout))
|
65
|
+
end
|
66
|
+
unless result.stderr.strip.empty?
|
67
|
+
@stream.puts(indent(2, "STDERR:"))
|
68
|
+
@stream.puts(indent(4, result.stderr))
|
69
|
+
end
|
70
|
+
end
|
14
71
|
end
|
15
72
|
|
16
73
|
def print_summary(results, elapsed_time)
|
17
74
|
@stream.puts format("Ran on %d node%s in %.2f seconds",
|
18
75
|
results.size,
|
19
|
-
results.size
|
76
|
+
results.size == 1 ? '' : 's',
|
20
77
|
elapsed_time)
|
21
78
|
end
|
22
79
|
|
data/lib/bolt/outputter/json.rb
CHANGED
@@ -15,10 +15,17 @@ module Bolt
|
|
15
15
|
@object_open = true
|
16
16
|
end
|
17
17
|
|
18
|
+
def print_event(node, event)
|
19
|
+
case event[:type]
|
20
|
+
when :node_result
|
21
|
+
print_result(node, event[:result])
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
18
25
|
def print_result(node, result)
|
19
26
|
item = {
|
20
27
|
name: node.uri,
|
21
|
-
status: result.
|
28
|
+
status: result.success? ? 'success' : 'failure',
|
22
29
|
result: result.to_result
|
23
30
|
}
|
24
31
|
|
data/lib/bolt/result.rb
CHANGED
@@ -1,72 +1,74 @@
|
|
1
1
|
require 'json'
|
2
|
+
require 'bolt/error'
|
2
3
|
|
3
4
|
module Bolt
|
4
5
|
class Result
|
5
|
-
attr_reader :message
|
6
|
+
attr_reader :message, :error
|
6
7
|
|
7
|
-
def
|
8
|
-
@
|
8
|
+
def self.from_exception(exception)
|
9
|
+
@exception = exception
|
10
|
+
if @exception.is_a?(Bolt::Error)
|
11
|
+
error = @exception.to_h
|
12
|
+
else
|
13
|
+
error = {
|
14
|
+
'kind' => 'puppetlabs.tasks/exception-error',
|
15
|
+
'issue_code' => 'EXCEPTION',
|
16
|
+
'msg' => exception.message,
|
17
|
+
'details' => { 'class' => exception.class.to_s }
|
18
|
+
}
|
19
|
+
error['details']['stack_trace'] = exception.backtrace.join('\n') if exception.backtrace
|
20
|
+
end
|
21
|
+
Result.new(error)
|
9
22
|
end
|
10
23
|
|
11
|
-
def
|
12
|
-
|
24
|
+
def initialize(error = nil, message = nil)
|
25
|
+
@error = error
|
26
|
+
@message = message
|
13
27
|
end
|
14
28
|
|
15
|
-
def
|
29
|
+
def value
|
16
30
|
nil
|
17
31
|
end
|
18
32
|
|
19
33
|
def to_h
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
class ErrorResult < Result
|
33
|
-
def initialize(message, issue_code, kind)
|
34
|
-
super(message)
|
35
|
-
@issue_code = issue_code
|
36
|
-
@kind = kind
|
37
|
-
end
|
38
|
-
|
39
|
-
def to_h
|
40
|
-
{
|
41
|
-
'error' => {
|
42
|
-
'issue_code' => @issue_code,
|
43
|
-
'kind' => @kind,
|
44
|
-
'msg' => @message
|
45
|
-
}
|
46
|
-
}
|
34
|
+
h = {}
|
35
|
+
if value
|
36
|
+
h['value'] = value
|
37
|
+
h['value']['_output'] = message if message
|
38
|
+
elsif message
|
39
|
+
h['value'] = { '_output' => message }
|
40
|
+
end
|
41
|
+
h['error'] = error if error
|
42
|
+
h
|
47
43
|
end
|
48
44
|
|
49
45
|
def to_result
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
46
|
+
# TODO: This should be to_h but we need to update the plan functions to
|
47
|
+
# use this hash instead
|
48
|
+
special_keys = {}
|
49
|
+
special_keys['_error'] = error if error
|
50
|
+
special_keys['_output'] = message if message
|
51
|
+
val = value || {}
|
52
|
+
val.merge(special_keys)
|
57
53
|
end
|
58
54
|
|
59
55
|
def success?
|
60
|
-
|
56
|
+
error.nil?
|
61
57
|
end
|
62
58
|
end
|
63
59
|
|
64
60
|
class CommandResult < Result
|
65
61
|
attr_reader :stdout, :stderr, :exit_code
|
66
62
|
|
63
|
+
def self.from_output(output)
|
64
|
+
new(output.stdout.string,
|
65
|
+
output.stderr.string,
|
66
|
+
output.exit_code)
|
67
|
+
end
|
68
|
+
|
67
69
|
def initialize(stdout, stderr, exit_code)
|
68
|
-
@stdout = stdout
|
69
|
-
@stderr = stderr
|
70
|
+
@stdout = stdout || ""
|
71
|
+
@stderr = stderr || ""
|
70
72
|
@exit_code = exit_code
|
71
73
|
end
|
72
74
|
|
@@ -78,111 +80,59 @@ module Bolt
|
|
78
80
|
}
|
79
81
|
end
|
80
82
|
|
81
|
-
def to_result
|
82
|
-
value
|
83
|
-
end
|
84
|
-
|
85
83
|
def success?
|
86
|
-
@exit_code
|
84
|
+
@exit_code == 0
|
87
85
|
end
|
88
86
|
|
89
|
-
def
|
90
|
-
|
87
|
+
def error
|
88
|
+
unless success?
|
89
|
+
{
|
90
|
+
'kind' => 'puppetlabs.tasks/command-error',
|
91
|
+
'issue_code' => 'COMMAND_ERROR',
|
92
|
+
'msg' => "The command failed with exit code #{@exit_code}",
|
93
|
+
'details' => { 'exit_code' => @exit_code }
|
94
|
+
}
|
95
|
+
end
|
91
96
|
end
|
92
97
|
end
|
93
98
|
|
94
99
|
class TaskResult < CommandResult
|
95
|
-
attr_reader :
|
100
|
+
attr_reader :value
|
96
101
|
|
97
102
|
def initialize(stdout, stderr, exit_code)
|
98
103
|
super(stdout, stderr, exit_code)
|
99
|
-
@
|
100
|
-
@
|
101
|
-
|
102
|
-
|
103
|
-
def value
|
104
|
-
@object || @stdout
|
105
|
-
end
|
106
|
-
|
107
|
-
def to_result
|
108
|
-
result = @object
|
109
|
-
result['_error'] = @error if @error
|
110
|
-
result
|
104
|
+
@value = parse_output(stdout)
|
105
|
+
@message = @value.delete('_output')
|
106
|
+
@error = @value.delete('_error')
|
111
107
|
end
|
112
108
|
|
113
|
-
def
|
114
|
-
|
115
|
-
|
116
|
-
|
109
|
+
def error
|
110
|
+
unless success?
|
111
|
+
return @error if @error
|
112
|
+
msg = if !@stdout.empty?
|
113
|
+
"The task failed with exit code #{@exit_code}"
|
114
|
+
else
|
115
|
+
"The task failed with exit code #{@exit_code}:\n#{@stderr}"
|
116
|
+
end
|
117
|
+
{ 'kind' => 'puppetlabs.tasks/task-error',
|
118
|
+
'issue_code' => 'TASK_ERROR',
|
119
|
+
'msg' => msg,
|
120
|
+
'details' => { 'exit_code' => @exit_code } }
|
121
|
+
end
|
117
122
|
end
|
118
123
|
|
119
124
|
private
|
120
125
|
|
121
|
-
def
|
126
|
+
def parse_output(output)
|
122
127
|
begin
|
123
128
|
obj = JSON.parse(output)
|
124
129
|
unless obj.is_a? Hash
|
125
130
|
obj = nil
|
126
131
|
end
|
127
132
|
rescue JSON::ParserError
|
128
|
-
nil
|
133
|
+
obj = nil
|
129
134
|
end
|
130
135
|
obj || { '_output' => output }
|
131
136
|
end
|
132
137
|
end
|
133
|
-
|
134
|
-
class TaskSuccess < TaskResult
|
135
|
-
def success?
|
136
|
-
true
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
class TaskFailure < TaskResult
|
141
|
-
def initialize(stdout, stderr, exit_code)
|
142
|
-
super(stdout, stderr, exit_code)
|
143
|
-
@error ||= generate_error
|
144
|
-
end
|
145
|
-
|
146
|
-
def success?
|
147
|
-
false
|
148
|
-
end
|
149
|
-
|
150
|
-
private
|
151
|
-
|
152
|
-
def generate_error
|
153
|
-
{
|
154
|
-
'kind' => 'puppetlabs.tasks/task-error',
|
155
|
-
'issue_code' => 'TASK_ERROR',
|
156
|
-
'msg' => "The task failed with exit code #{@exit_code}",
|
157
|
-
'details' => { 'exit_code' => @exit_code }
|
158
|
-
}
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
class ExceptionResult < Result
|
163
|
-
def initialize(exception)
|
164
|
-
@exception = exception
|
165
|
-
end
|
166
|
-
|
167
|
-
def error
|
168
|
-
{
|
169
|
-
'kind' => 'puppetlabs.tasks/exception-error',
|
170
|
-
'issue_code' => 'EXCEPTION',
|
171
|
-
'msg' => @exception.message,
|
172
|
-
'details' => { 'stack_trace' => @exception.backtrace.join('\n') }
|
173
|
-
}
|
174
|
-
end
|
175
|
-
|
176
|
-
def to_h
|
177
|
-
{ 'error' => error }
|
178
|
-
end
|
179
|
-
|
180
|
-
def message
|
181
|
-
@exception.message
|
182
|
-
end
|
183
|
-
|
184
|
-
def success?
|
185
|
-
false
|
186
|
-
end
|
187
|
-
end
|
188
138
|
end
|