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.

Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/lib/bolt/cli.rb +31 -21
  3. data/lib/bolt/config.rb +1 -0
  4. data/lib/bolt/error.rb +28 -0
  5. data/lib/bolt/executor.rb +10 -6
  6. data/lib/bolt/node.rb +7 -5
  7. data/lib/bolt/node/errors.rb +25 -3
  8. data/lib/bolt/node/orch.rb +7 -16
  9. data/lib/bolt/node/output.rb +17 -0
  10. data/lib/bolt/node/ssh.rb +101 -44
  11. data/lib/bolt/node/winrm.rb +86 -40
  12. data/lib/bolt/outputter/human.rb +65 -8
  13. data/lib/bolt/outputter/json.rb +8 -1
  14. data/lib/bolt/result.rb +74 -124
  15. data/lib/bolt/version.rb +1 -1
  16. data/{vendored/puppet → modules/boltlib}/lib/puppet/functions/file_upload.rb +9 -7
  17. data/{vendored/puppet → modules/boltlib}/lib/puppet/functions/run_command.rb +8 -9
  18. data/{vendored/puppet → modules/boltlib}/lib/puppet/functions/run_plan.rb +8 -12
  19. data/{vendored/puppet → modules/boltlib}/lib/puppet/functions/run_script.rb +12 -8
  20. data/{vendored/puppet → modules/boltlib}/lib/puppet/functions/run_task.rb +10 -10
  21. data/vendored/puppet/lib/puppet/agent.rb +1 -1
  22. data/vendored/puppet/lib/puppet/application/lookup.rb +1 -3
  23. data/vendored/puppet/lib/puppet/configurer.rb +2 -3
  24. data/vendored/puppet/lib/puppet/configurer/plugin_handler.rb +25 -7
  25. data/vendored/puppet/lib/puppet/defaults.rb +9 -1
  26. data/vendored/puppet/lib/puppet/face/epp.rb +4 -2
  27. data/vendored/puppet/lib/puppet/face/module/build.rb +1 -1
  28. data/vendored/puppet/lib/puppet/face/module/list.rb +5 -16
  29. data/vendored/puppet/lib/puppet/face/module/uninstall.rb +14 -3
  30. data/vendored/puppet/lib/puppet/face/plugin.rb +1 -3
  31. data/vendored/puppet/lib/puppet/forge/errors.rb +17 -7
  32. data/vendored/puppet/lib/puppet/functions.rb +8 -6
  33. data/vendored/puppet/lib/puppet/functions/each.rb +10 -4
  34. data/vendored/puppet/lib/puppet/functions/lookup.rb +2 -2
  35. data/vendored/puppet/lib/puppet/functions/map.rb +12 -2
  36. data/vendored/puppet/lib/puppet/functions/slice.rb +2 -3
  37. data/vendored/puppet/lib/puppet/graph/simple_graph.rb +9 -5
  38. data/vendored/puppet/lib/puppet/interface.rb +1 -0
  39. data/vendored/puppet/lib/puppet/module_tool/errors/installer.rb +27 -17
  40. data/vendored/puppet/lib/puppet/module_tool/errors/shared.rb +143 -63
  41. data/vendored/puppet/lib/puppet/module_tool/errors/uninstaller.rb +37 -14
  42. data/vendored/puppet/lib/puppet/module_tool/errors/upgrader.rb +30 -18
  43. data/vendored/puppet/lib/puppet/network/auth_config_parser.rb +8 -8
  44. data/vendored/puppet/lib/puppet/network/http/error.rb +7 -7
  45. data/vendored/puppet/lib/puppet/network/http/rack.rb +2 -2
  46. data/vendored/puppet/lib/puppet/network/http/webrick.rb +1 -1
  47. data/vendored/puppet/lib/puppet/node.rb +10 -0
  48. data/vendored/puppet/lib/puppet/node/facts.rb +9 -0
  49. data/vendored/puppet/lib/puppet/parameter/value_collection.rb +16 -6
  50. data/vendored/puppet/lib/puppet/parser/resource.rb +103 -31
  51. data/vendored/puppet/lib/puppet/pops/evaluator/access_operator.rb +13 -0
  52. data/vendored/puppet/lib/puppet/pops/evaluator/evaluator_impl.rb +22 -6
  53. data/vendored/puppet/lib/puppet/pops/loader/static_loader.rb +1 -1
  54. data/vendored/puppet/lib/puppet/pops/lookup/lookup_adapter.rb +13 -4
  55. data/vendored/puppet/lib/puppet/pops/model/ast_transformer.rb +1 -1
  56. data/vendored/puppet/lib/puppet/pops/parser/eparser.rb +527 -529
  57. data/vendored/puppet/lib/puppet/pops/serialization/abstract_reader.rb +4 -0
  58. data/vendored/puppet/lib/puppet/pops/serialization/abstract_writer.rb +6 -0
  59. data/vendored/puppet/lib/puppet/pops/serialization/extension.rb +1 -0
  60. data/vendored/puppet/lib/puppet/pops/serialization/serializer.rb +2 -1
  61. data/vendored/puppet/lib/puppet/pops/types/execution_result.rb +8 -0
  62. data/vendored/puppet/lib/puppet/pops/types/iterable.rb +2 -0
  63. data/vendored/puppet/lib/puppet/pops/types/p_object_type.rb +3 -0
  64. data/vendored/puppet/lib/puppet/pops/types/p_object_type_extension.rb +6 -0
  65. data/vendored/puppet/lib/puppet/pops/types/p_uri_type.rb +191 -0
  66. data/vendored/puppet/lib/puppet/pops/types/string_converter.rb +17 -0
  67. data/vendored/puppet/lib/puppet/pops/types/type_calculator.rb +5 -0
  68. data/vendored/puppet/lib/puppet/pops/types/type_factory.rb +7 -0
  69. data/vendored/puppet/lib/puppet/pops/types/type_formatter.rb +16 -18
  70. data/vendored/puppet/lib/puppet/pops/types/type_mismatch_describer.rb +15 -5
  71. data/vendored/puppet/lib/puppet/pops/types/type_parser.rb +6 -0
  72. data/vendored/puppet/lib/puppet/pops/types/type_with_members.rb +43 -0
  73. data/vendored/puppet/lib/puppet/pops/types/types.rb +3 -0
  74. data/vendored/puppet/lib/puppet/provider/package/gem.rb +1 -1
  75. data/vendored/puppet/lib/puppet/provider/package/nim.rb +7 -8
  76. data/vendored/puppet/lib/puppet/provider/package/opkg.rb +1 -1
  77. data/vendored/puppet/lib/puppet/provider/package/pkg.rb +6 -4
  78. data/vendored/puppet/lib/puppet/provider/package/pkgutil.rb +3 -3
  79. data/vendored/puppet/lib/puppet/provider/service/init.rb +1 -1
  80. data/vendored/puppet/lib/puppet/syntax_checkers/base64.rb +5 -6
  81. data/vendored/puppet/lib/puppet/transaction.rb +1 -1
  82. data/vendored/puppet/lib/puppet/type.rb +1 -9
  83. data/vendored/puppet/lib/puppet/type/schedule.rb +1 -1
  84. data/vendored/puppet/lib/puppet/util/log.rb +2 -3
  85. data/vendored/puppet/lib/puppet/util/plist.rb +1 -1
  86. data/vendored/puppet/lib/puppet/util/reference.rb +2 -3
  87. data/vendored/puppet/lib/puppet_pal.rb +326 -53
  88. metadata +28 -12
  89. data/lib/bolt/node/result.rb +0 -115
  90. data/vendored/puppet/lib/puppet/configurer/downloader_factory.rb +0 -44
@@ -38,7 +38,7 @@ module Bolt
38
38
  end
39
39
 
40
40
  def shell_init
41
- return Bolt::Node::Success.new if @shell_initialized
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::ResultOutput.new
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.then { |stdout| Bolt::Node::Success.new(stdout.chomp) }
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
- dest = ''
244
- dir = ''
245
- result = nil
246
-
247
- make_tempdir.then do |value|
248
- dir = value
249
- ext = File.extname(file)
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
- end.then do
258
- result = yield dest
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
- path, args = *process_from_extension(remote_path)
276
- args += escape_arguments(arguments)
277
- execute_process(path, args)
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.reduce(Bolt::Node::Success.new) do |result, (arg, val)|
291
- result.then do
292
- cmd = "[Environment]::SetEnvironmentVariable('PT_#{arg}', '#{val}')"
293
- execute(cmd)
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
- else
297
- Bolt::Node::Success.new
298
- end.then do
299
- with_remote_file(task) do |remote_path|
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)
@@ -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
- color = result.success? ? "\033[32m" : "\033[31m"
8
- @stream.print color if @stream.isatty
9
- @stream.puts "#{node.host}:"
10
- @stream.print "\033[0m" if @stream.isatty
11
- @stream.puts
12
- @stream.puts result.message
13
- @stream.puts
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 > 1 ? 's' : '',
76
+ results.size == 1 ? '' : 's',
20
77
  elapsed_time)
21
78
  end
22
79
 
@@ -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.is_a?(Bolt::ErrorResult) ? 'failure' : 'success',
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 initialize(message)
8
- @message = message
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 value
12
- nil
24
+ def initialize(error = nil, message = nil)
25
+ @error = error
26
+ @message = message
13
27
  end
14
28
 
15
- def error
29
+ def value
16
30
  nil
17
31
  end
18
32
 
19
33
  def to_h
20
- { 'value' => value }
21
- end
22
-
23
- def to_result
24
- value
25
- end
26
-
27
- def success?
28
- true
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
- '_error' => {
52
- 'issue_code' => @issue_code,
53
- 'kind' => @kind,
54
- 'msg' => @message
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
- false
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.zero?
84
+ @exit_code == 0
87
85
  end
88
86
 
89
- def message
90
- [stdout, stderr].join("\n")
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 :error
100
+ attr_reader :value
96
101
 
97
102
  def initialize(stdout, stderr, exit_code)
98
103
  super(stdout, stderr, exit_code)
99
- @object = output_to_json_hash(stdout)
100
- @error = @object.delete('_error') if @object
101
- end
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 to_h
114
- hash = super
115
- hash['error'] = error if error
116
- hash
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 output_to_json_hash(output)
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