class Pinject::Docker

Attributes

log[R]

Public Class Methods

new(image_name, log: false) click to toggle source
# File lib/pinject/docker.rb, line 18
def initialize(image_name, log: false)
  @image_name = image_name
  @log = log
end

Public Instance Methods

inject_build(repo) click to toggle source
# File lib/pinject/docker.rb, line 23
def inject_build(repo)
  if r = detect_os
    Pinject.log.info "detect os #{r.inspect}" if log
    upd = update_cmd(r[:dist], r[:version])
    if upd
      df = docker_file(@image_name, upd, r[:user])
      ::Docker::Image.build(
        df,
        't' => repo
      ) do |v|
        Pinject.log.info v if log
      end
    else
      raise UnsupportedDistError, "unsupport os dist:#{r[:dist]} version:#{r[:version]}"
    end
  end
end

Private Instance Methods

container_name() click to toggle source
# File lib/pinject/docker.rb, line 80
def container_name
  Digest::MD5.hexdigest(@image_name)[0..10]
end
detect_os() click to toggle source
# File lib/pinject/docker.rb, line 43
def detect_os
  ::Docker::Container.all(all: true).each do |c|
    c.delete(force: true) if c.info['Names'].first == "/#{container_name}"
  end

  container = ::Docker::Container.create({
                                           'name' => container_name,
                                           'Image' => image.id,
                                           'Entrypoint' => '',
                                           'Cmd' => ['/opt/detector']
                                         })

  result = nil
  container.start
  container.streaming_logs(stdout: true) { |stream, chunk| result = chunk.chomp if stream == :stdout }

  if result
    dist, version, user = result.split(%r{:|/})

    {
      dist: dist,
      version: version,
      user: user
    }
  end
end
detector_code() click to toggle source
# File lib/pinject/docker.rb, line 119
    def detector_code
      <<~EOS
        #!/bin/sh
        if [ -f /etc/lsb-release ]; then
            . /etc/lsb-release
            OS=$DISTRIB_ID
            VER=`echo $DISTRIB_RELEASE | awk -F. '{ print $1 }'`
        elif [ -f /etc/debian_version ]; then
            OS=debian
            VER=`cat /etc/debian_version | awk -F. '{ print $1 }'`
        elif [ -f /etc/redhat-release ]; then
            OS=centos
            VER=`cat /etc/redhat-release | sed -e 's/.*\\s\\([0-9]\\)\\..*/\\1/'`
        elif [ -f /etc/alpine-release ]; then
            OS=alpine
            VER=`cat /etc/alpine-release | awk -F. '{ print $1 }'`
        elif [ -f /etc/os-release]; then
            . /etc/os-release
            OS=$ID
            VER=`echo $VERSION_ID | sed -e 's/"//g'`
        else
            OS="other"
            VER="unknown"
        fi
        echo $OS/$VER:`whoami` | tr '[:upper:]' '[:lower:]'
      EOS
    end
docker_file(image, cmd, user) click to toggle source
# File lib/pinject/docker.rb, line 70
    def docker_file(image, cmd, user)
      t = <<~EOS
        FROM %s
        USER root
        RUN %s
        USER %s
      EOS
      format(t, image, cmd, user)
    end
image() click to toggle source
# File lib/pinject/docker.rb, line 84
def image
  Pinject.log.info 'start detect os' if log
  ::Docker.options[:read_timeout] = 300
  begin
    i = ::Docker::Image.create('fromImage' => @image_name)
  rescue StandardError => e
    Pinject.log.error "failed create container #{e.inspect}" if log
    raise e
  end

  t = Tempfile.open('detector') do |f|
    f.puts detector_code
    f
  end
  FileUtils.chmod(0o755, t.path)
  i.insert_local('localPath' => t.path, 'outputPath' => '/opt/detector')
end
update_cmd(dist, version) click to toggle source
# File lib/pinject/docker.rb, line 102
def update_cmd(dist, version)
  r = case dist
      when 'ubuntu', 'debian'
        ['apt-get update -qqy', 'apt-get upgrade -qqy', 'apt-get clean', 'rm -rf /var/lib/apt/lists/*']
      when 'alpine'
        ['apk update', 'apk upgrade --no-cache']
      when 'centos'
        case version
        when '5', '6'
          nil
        else
          ['yum update -y']
        end
  end
  r&.join(' && ')
end