class Docker::Template::Logger

Attributes

stderr[W]
stdout[W]

Public Class Methods

new(repo = nil, stdout = nil, stderr = nil) click to toggle source

# File lib/docker/template/logger.rb, line 27
def initialize(repo = nil, stdout = nil, stderr = nil)
  @stdout = stdout || self.class.stdout
  @stderr = stderr || self.class.stderr
  @repo   = repo
  @lines  = {
    0 => 0
  }
end
stderr() click to toggle source

# File lib/docker/template/logger.rb, line 20
def stderr
  return @stderr || $stderr
end
stdout() click to toggle source

# File lib/docker/template/logger.rb, line 14
def stdout
  return @stdout || $stdout
end

Public Instance Methods

api(part, *args) click to toggle source

– A more complex streamer designed for the actual output of the Docker. – This method will save parts into a buffer until it can either parse that buffer or it parses the actual part itself, if it can parse the part itself, it will first dump the buffer as errors and then parse. – This method has to buffer because Docker-API (or Excon, it's depend) gives us no indication of whether or not this is part of a larger chunk it just dumps it on us, so we have to blindly work around that. –

# File lib/docker/template/logger.rb, line 84
def api(part, *args)
  part = encode_str(part).each_line.to_a
  if part.one? && part = part.first
    chunked_part = @chunks.push(part).join if @chunks && !@chunks.empty?
    chunked_part = part if !@chunks
    stream = JSON.parse(
      chunked_part
    )

    if chunked_part == part && @chunks && !@chunks.empty?
      then @chunks.each do |chunk|
        @stderr.puts format("Unparsable JSON: %s",
          chunk
        )
      end
    end

    @chunks = nil
    return progress_bar(stream) if stream.any_key?("progress", "progressDetail")
    return output(stream["status"] || stream["stream"]) if stream.any_key?("status", "stream")
    return progress_error(stream) if stream.any_key?("errorDetail", "error")
    warn Simple::Ansi.red("Unhandled Stream.")
    @stdout.puts(part)
    @output = true
  else
    part.each do |v|
      api(v, *args)
    end
  end
# --
# Sometimes we get undetectable chunks.
# When we do, we try to keep them passed along.
# That way we can throw them out later.
# --
rescue JSON::ParserError => e
  (@chunks ||= []).push(
    part
  )
end
increment() click to toggle source

# File lib/docker/template/logger.rb, line 44
def increment
  @lines.update({
    @lines.size => @lines.size
  })
end
output(msg) click to toggle source

# File lib/docker/template/logger.rb, line 126
def output(msg)
  unless filter_matches?(msg)
    @stdout.puts msg
    increment
  end

  @output = true
end
output?() click to toggle source

# File lib/docker/template/logger.rb, line 38
def output?
  return !!@output
end
progress_error(stream) click to toggle source

# File lib/docker/template/logger.rb, line 137
def progress_error(stream)
  abort Object::Simple::Ansi.red(
    stream["errorDetail"]["message"]
  )
end
simple(type, str) click to toggle source

– A simple logger that accepts a multi-type stream. –

# File lib/docker/template/logger.rb, line 66
def simple(type, str)
  str = encode_str(str ||= "")
  type == :stderr ? @stderr.print(str) : \
    @stdout.print(str)
end
tty(stream) click to toggle source

– A simple TTY stream that just prints out the data that it is given. This is the logger that most will use for most of their building. –

# File lib/docker/template/logger.rb, line 55
def tty(stream)
  @output = true
  @stdout.print(encode_str(
    stream
  ))
end

Private Instance Methods

encode_str(str) click to toggle source

– Some applications return some invalid ASCII so we need to work around that so that no errors happen. This mostly happens with Node.js NPM. –

# File lib/docker/template/logger.rb, line 150
def encode_str(str)
  str.encode("utf-8", {
    :invalid => :replace, :undef => :replace, :replace => ""
  })
end
filter_matches?(msg) click to toggle source

# File lib/docker/template/logger.rb, line 191
def filter_matches?(msg)
  return false unless @repo

  @repo.meta["log_filters"].any? do |filter|
    filter.is_a?(Regexp) && msg =~ filter || msg == filter
  end
end
progress_bar(stream) click to toggle source

# File lib/docker/template/logger.rb, line 159
def progress_bar(stream)
  if ENV["CI"] != "true"
    id = stream["id"]

    return unless id
    before, diff = progress_diff(id)
    @stderr.print before if before
    str = stream["progress"] || stream["status"]
    str = "#{id}: #{str}\r"

    @stderr.print(Object::Simple::Ansi.jump(
      str, diff
    ))
  end
end
progress_diff(id) click to toggle source

# File lib/docker/template/logger.rb, line 178
def progress_diff(id)
  if @lines.key?(id)
    return nil, @lines.size - @lines[id]
  end

  @lines[id] = @lines.size
  before = "\n" unless @lines.one?
  return before, 0
end