class Dockerspec::DockerExceptionParser

A class to parse `Docker::Error` exceptions.

Public Class Methods

new(e) click to toggle source

Parses Docker exceptions.

Raises the same exception if the format is unknown.

@example

rescue ::Docker::Error::DockerError => e
  DockerExceptionParser.new(e)
end

@param e [Exception] The exception object to parse.

@raise [Dockerspec::DockerError] When the exception format is known. @raise [Exception] When the exception format is unknown.

@api public

# File lib/dockerspec/docker_exception_parser.rb, line 45
def initialize(e)
  e_ary = parse_exception(e)
  raise_docker_error_exception(e_ary)
  raise e
end

Protected Instance Methods

generate_error_message(error, output) click to toggle source

Generates a formated error message.

@param error [String] The error message. @param output [String] The generated stdout output.

@return [String] The resulting error message.

@api private

# File lib/dockerspec/docker_exception_parser.rb, line 130
def generate_error_message(error, output)
  [
    "#{error}\n",
    "OUTPUT: \n#{output.gsub(/^/, ' ' * 8)}",
    "ERROR:  #{error}\n\n"
  ].join("\n")
end
parse_error_detail(e_ary) click to toggle source

Gets the error message from the errorDetail field.

@param e_ary [Array<Hash>] The list of JSON messages already parsed.

@return [String] The error message string.

@api private

# File lib/dockerspec/docker_exception_parser.rb, line 100
def parse_error_detail(e_ary)
  e_detail = e_ary.select { |x| x.is_a?(Hash) && x.key?('errorDetail') }[0]
  return nil unless e_detail.is_a?(Hash)
  return e_detail['message'] if e_detail.key?('message')
  return e_detail['error'] if e_detail.key?('error')
end
parse_exception(e) click to toggle source

Parses the exception JSON message.

The message must be a list of JSON messages merged by a new line.

A valid exception message example:

“` {“stream”:“Step 1 : FROM alpine:3.2n”} {“stream”:“ —u003e d6ead20d5571n”} {“stream”:“Step 2 : RUN apk add –update wrong-package-namen”} {“stream”:“ —u003e Running in 290a46fa8bf4n”} {“stream”:“fetch dl-4.alpinelinux.org/alpine/v3.2/main/…n”} {“stream”:“ERROR: unsatisfiable constraints:n”} {“stream”:“ wrong-package-name (missing):n required by: world…n”} {“errorDetail”:{“message”:“The command …”},“error”:“The command …”} “`

@example

self.parse_exception(e)
#=> [{ "stream" => "Step 1 : FROM alpine:3.2\n" }, "errorDetail" => ...

@param e [Exception] The exception object to parse.

@return [Array<Hash>] The list of JSON messages parsed.

@return

@api private

# File lib/dockerspec/docker_exception_parser.rb, line 83
def parse_exception(e)
  msg = e.to_s
  json = msg.to_s.sub(/^Couldn't find id: /, '').split("\n").map(&:chomp)
  json.map { |str| JSON.parse(str) }
rescue JSON::ParserError
  raise e
end
parse_streams(e_ary) click to toggle source

Gets all the console output from the stream logs.

@param e_ary [Array<Hash>] The list of JSON messages already parsed.

@return [String] The generated stdout output.

@api private

# File lib/dockerspec/docker_exception_parser.rb, line 116
def parse_streams(e_ary)
  e_ary.map { |x| x.is_a?(Hash) && x['stream'] }.compact.join
end
raise_docker_error_exception(e_ary) click to toggle source

Raises the right {Dockerspec::DockerError} exception.

Nothing is raised if the exception format is unknown.

@param e_ary [Array<Hash>] The list of JSON messages already parsed.

@return void

@raise [Dockerspec::DockerError] When the exception format is known.

@api private

# File lib/dockerspec/docker_exception_parser.rb, line 151
def raise_docker_error_exception(e_ary)
  e_ary.select { |x| x.is_a?(Hash) && x.key?('errorDetail') }[0]
  output = parse_streams(e_ary)
  error_msg = parse_error_detail(e_ary)
  return if error_msg.nil?
  raise DockerError, generate_error_message(error_msg, output)
end