lib/bolt/result.rb in bolt-0.14.0 vs lib/bolt/result.rb in bolt-0.15.0

- old
+ new

@@ -1,13 +1,13 @@ require 'json' require 'bolt/error' module Bolt class Result - attr_reader :message, :error + attr_reader :target, :value - def self.from_exception(exception) + def self.from_exception(target, exception) @exception = exception if @exception.is_a?(Bolt::Error) error = @exception.to_h else error = { @@ -16,123 +16,126 @@ 'msg' => exception.message, 'details' => { 'class' => exception.class.to_s } } error['details']['stack_trace'] = exception.backtrace.join('\n') if exception.backtrace end - Result.new(error) + Result.new(target, error: error) end - def initialize(error = nil, message = nil) - @error = error - @message = message + def self.for_command(target, stdout, stderr, exit_code) + value = { + 'stdout' => stdout, + 'stderr' => stderr, + 'exit_code' => exit_code + } + unless exit_code == 0 + value['_error'] = { + 'kind' => 'puppetlabs.tasks/command-error', + 'issue_code' => 'COMMAND_ERROR', + 'msg' => "The command failed with exit code #{exit_code}", + 'details' => { 'exit_code' => exit_code } + } + end + new(target, value: value) end - def value - nil + def self.for_task(target, stdout, stderr, exit_code) + begin + value = JSON.parse(stdout) + unless value.is_a? Hash + value = nil + end + rescue JSON::ParserError + value = nil + end + value ||= { '_output' => stdout } + if exit_code != 0 && value['_error'].nil? + msg = if stdout.empty? + "The task failed with exit code #{exit_code}:\n#{stderr}" + else + "The task failed with exit code #{exit_code}" + end + value['_error'] = { 'kind' => 'puppetlabs.tasks/task-error', + 'issue_code' => 'TASK_ERROR', + 'msg' => msg, + 'details' => { 'exit_code' => exit_code } } + end + new(target, value: value) end - def to_h - h = {} - if value - h['value'] = value - h['value']['_output'] = message if message - elsif message - h['value'] = { '_output' => message } + def self.for_upload(target, source, destination) + new(target, message: "Uploaded '#{source}' to '#{target.host}:#{destination}'") + end + + def initialize(target, error: nil, message: nil, value: nil) + @target = target + @value = value || {} + @value_set = !value.nil? + if error && !error.is_a?(Hash) + raise "TODO: how did we get a string error" end - h['error'] = error if error - h + @value['_error'] = error if error + @value['_output'] = message if message end - def to_result - # TODO: This should be to_h but we need to update the plan functions to - # use this hash instead - special_keys = {} - special_keys['_error'] = error if error - special_keys['_output'] = message if message - val = value || {} - val.merge(special_keys) + def message + @value['_output'] end - def success? - error.nil? + def status_hash + { node: @target.name, + status: ok? ? 'success' : 'failure', + result: @value } end - end - class CommandResult < Result - attr_reader :stdout, :stderr, :exit_code + # TODO: what to call this it's the value minus special keys + # This should be {} if a value was set otherwise it's nil + def generic_value + if @value_set + value.reject { |k, _| %w[_error _output].include? k } + end + end - def self.from_output(output) - new(output.stdout.string, - output.stderr.string, - output.exit_code) + def eql?(other) + self.class == other.class && + target == other.target && + value == other.value end - def initialize(stdout, stderr, exit_code) - @stdout = stdout || "" - @stderr = stderr || "" - @exit_code = exit_code + def [](key) + value[key] end - def value - { - 'stdout' => @stdout, - 'stderr' => @stderr, - 'exit_code' => @exit_code - } + def ==(other) + eql?(other) end + # TODO: remove in favor of ok? def success? - @exit_code == 0 + ok? end - def error - unless success? - { - 'kind' => 'puppetlabs.tasks/command-error', - 'issue_code' => 'COMMAND_ERROR', - 'msg' => "The command failed with exit code #{@exit_code}", - 'details' => { 'exit_code' => @exit_code } - } - end + def ok? + error_hash.nil? end - end + alias ok ok? - class TaskResult < CommandResult - attr_reader :value - - def initialize(stdout, stderr, exit_code) - super(stdout, stderr, exit_code) - @value = parse_output(stdout) - @message = @value.delete('_output') - @error = @value.delete('_error') + # This allows access to errors outside puppet compilation + # it should be prefered over error in bolt code + def error_hash + value['_error'] end + # Warning: This will fail outside of a compilation. + # Use error_hash inside bolt. + # Is it crazy for this to behave differently outside a compiler? def error - unless success? - return @error if @error - msg = if !@stdout.empty? - "The task failed with exit code #{@exit_code}" - else - "The task failed with exit code #{@exit_code}:\n#{@stderr}" - end - { 'kind' => 'puppetlabs.tasks/task-error', - 'issue_code' => 'TASK_ERROR', - 'msg' => msg, - 'details' => { 'exit_code' => @exit_code } } - end - end + if error_hash + Puppet::DataTypes::Error.new(error_hash['msg'], + error_hash['kind'], + nil, nil, + error_hash['details']) - private - - def parse_output(output) - begin - obj = JSON.parse(output) - unless obj.is_a? Hash - obj = nil - end - rescue JSON::ParserError - obj = nil end - obj || { '_output' => output } end end end