class Kitchen::Driver::DockerAdv

DockerAdv driver for Kitchen.

@author Gattsu <Gattsu@gmail.com>

Public Instance Methods

build_applications_list() click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 71
def build_applications_list()
  applications=config[:applications]
  apps = Array.new
  applications.each do | application |
    code   = application[:code]
    branch = application[:branch]
    apps << "#{code}=#{branch}"
  end

  return "#{apps.join(':')}"
end
create(state) click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 95
def create(state)
  state[:image_id] = build_image(state) unless state[:image_id]
  state[:container_id] = run_container(state) unless state[:container_id]
  state[:hostname] = remote_socket? ? socket_uri.host : 'localhost'
  state[:port] = container_ssh_port(state)
  wait_for_sshd(state[:hostname], nil, :port => state[:port])
end
default_image() click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 83
def default_image
  platform, release = instance.platform.name.split('-')
  if platform == "centos" && release
    release = "centos" + release.split('.').first
  end
  release ? [platform, release].join(':') : platform
end
default_platform() click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 91
def default_platform
  instance.platform.name.split('-').first
end
destroy(state) click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 103
def destroy(state)
  rm_container(state) if container_exists?(state)
  if config[:remove_images] && state[:image_id]
    rm_image(state)
  end
end
remote_socket?() click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 110
def remote_socket?
  config[:socket] ? socket_uri.scheme == 'tcp' : false
end
verify_dependencies() click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 64
def verify_dependencies
  run_command("#{config[:binary]} > /dev/null", :quiet => true)
  rescue
    raise UserError,
    'You must first install the Docker CLI tool http://www.docker.io/gettingstarted/'
end

Protected Instance Methods

build_dockerfile() click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 131
      def build_dockerfile
        from = "FROM #{config[:image]}"
        platform = case config[:platform]
        when 'debian', 'ubuntu'
          disable_upstart = <<-eos
            RUN dpkg-divert --local --rename --add /sbin/initctl
            RUN ln -sf /bin/true /sbin/initctl
          eos
          packages = <<-eos
            ENV DEBIAN_FRONTEND noninteractive
            RUN apt-get update
            RUN apt-get install -y sudo openssh-server curl lsb-release
          eos
          config[:disable_upstart] ? disable_upstart + packages : packages
        when 'rhel', 'centos'
          <<-eos
            RUN yum clean all
            RUN yum install -y sudo openssh-server openssh-clients which curl
            RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key -N ''
            RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key -N ''
          eos
        when 'arch'
          <<-eos
            RUN pacman -Syu --noconfirm
            RUN pacman -S --noconfirm openssh sudo curl
            RUN ssh-keygen -A -t rsa -f /etc/ssh/ssh_host_rsa_key
            RUN ssh-keygen -A -t dsa -f /etc/ssh/ssh_host_dsa_key
          eos
        else
          raise ActionFailed,
          "Unknown platform '#{config[:platform]}'"
        end
        username = config[:username]
        password = config[:password]
        base = <<-eos
          RUN useradd -d /home/#{username} -m -s /bin/bash #{username}
          RUN echo #{username}:#{password} | chpasswd
          RUN echo '#{username} ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
        eos
        custom = ''
        Array(config[:provision_command]).each do |cmd|
          custom << "RUN #{cmd}\n"
        end
        [from, platform, base, custom].join("\n")
      end
build_image(state) click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 197
def build_image(state)
  cmd = "build"
  cmd << " --no-cache" unless config[:use_cache]
  cmd << " --build-arg applications=#{build_applications_list()}"
  cmd << " --build-arg environment=#{config[:environment]}" if config[:environment]
  cmd << " --build-arg svn_base=#{config[:svn_base]}" if config[:svn_base]
  cmd << " --build-arg svn_user=#{config[:svn_user]}" if config[:svn_user]
  cmd << " --build-arg svn_pwd=#{config[:svn_pwd]}" if config[:svn_pwd]
  cmd << " --build-arg proxy_user=#{config[:proxy_user]}" if config[:proxy_user]
  cmd << " --build-arg proxy_pwd=#{config[:proxy_pwd]}" if config[:proxy_pwd]
  output = docker_command("#{cmd} -", :input => dockerfile)
  parse_image_id(output)
end
build_run_command(image_id) click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 220
def build_run_command(image_id)
  cmd = "run -d -p 22"
  Array(config[:forward]).each {|port| cmd << " -p #{port}"}
  Array(config[:dns]).each {|dns| cmd << " -dns #{dns}"}
  Array(config[:volume]).each {|volume| cmd << " -v #{volume}"}
  Array(config[:volumes_from]).each {|container| cmd << " --volumes-from #{container}"}
  cmd << " -h #{config[:hostname]}" if config[:hostname]
  cmd << " -m #{config[:memory]}" if config[:memory]
  cmd << " -c #{config[:cpu]}" if config[:cpu]
  cmd << " --privileged"
  cmd << " --cap-add ALL"
  cmd << " -e http_proxy='#{config[:http_proxy]}'" if config[:http_proxy]
  cmd << " -p 3000:3000" if config[:rails]
  cmd << " -e https_proxy='#{config[:https_proxy]}'" if config[:https_proxy]
  cmd << " -e environment=#{config[:environment]}" 
  cmd << " -e svn_base=#{config[:svn_base]}"
  cmd << " -e svn_user=#{config[:svn_user]}"
  cmd << " -e svn_pwd=#{config[:svn_pwd]}"
  cmd << " -e proxy_user=#{config[:proxy_user]}"
  cmd << " -e proxy_pwd=#{config[:proxy_pwd]}"
  cmd << " #{image_id} #{config[:run_command]}"
  cmd
end
container_exists?(state) click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 257
def container_exists?(state)
  !!inspect_container(state) rescue false
end
container_ssh_port(state) click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 273
def container_ssh_port(state)
  output = inspect_container(state)
  parse_container_ssh_port(output)
end
docker_command(cmd, options={}) click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 120
def docker_command(cmd, options={})
  docker = config[:binary].dup
  docker << " -H #{config[:socket]}" if config[:socket]
  docker << " --tls" if config[:tls]
  docker << " --tlsverify" if config[:tls_verify]
  docker << " --tlscacert=#{config[:tls_cacert]}" if config[:tls_cacert]
  docker << " --tlscert=#{config[:tls_cert]}" if config[:tls_cert]
  docker << " --tlskey=#{config[:tls_key]}" if config[:tls_key]
  run_command("#{docker} #{cmd}", options.merge(:quiet => !logger.debug?))
end
dockerfile() click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 177
def dockerfile
  if config[:dockerfile]
    template = IO.read(File.expand_path(config[:dockerfile]))
    context = DockerERBContext.new(config.to_hash)
    ERB.new(template).result(context.get_binding)
  else
    build_dockerfile
  end
end
inspect_container(state) click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 250
def inspect_container(state)
  container_id = state[:container_id]
  if container_id
    docker_command("inspect #{container_id} " + %q[| awk -F"=" '$1 !~ /svn_user|svn_pwd|proxy_user|proxy_pwd|http_proxy|https_proxy/ {print $0}; $1 ~ /svn_user|svn_pwd|proxy_user|proxy_pwd|http_proxy|https_proxy/ {print $1 "=*****\","}'])
  end
end
parse_container_id(output) click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 211
def parse_container_id(output)
  container_id = output.chomp
  unless [12, 64].include?(container_id.size)
    raise ActionFailed,
    'Could not parse Docker run output for container ID'
  end
  container_id
end
parse_container_ssh_port(output) click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 261
def parse_container_ssh_port(output)
  begin
    info = Array(::JSON.parse(output)).first
    ports = info['NetworkSettings']['Ports'] || info['HostConfig']['PortBindings']
    ssh_port = ports['22/tcp'].detect {|port| port['HostIp'] == '0.0.0.0'}
    ssh_port['HostPort'].to_i
  rescue
    raise ActionFailed,
    'Could not parse Docker inspect output for container SSH port'
  end
end
parse_image_id(output) click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 187
def parse_image_id(output)
  output.each_line do |line|
    if line =~ /image id|build successful|successfully built/i
      return line.split(/\s+/).last
    end
  end
  raise ActionFailed,
  'Could not parse Docker build output for image ID'
end
rm_container(state) click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 278
def rm_container(state)
  container_id = state[:container_id]
  docker_command("stop #{container_id}")
  docker_command("rm -f #{container_id}")
end
rm_image(state) click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 284
def rm_image(state)
  image_id = state[:image_id]
  docker_command("rmi #{image_id}")
end
run_container(state) click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 244
def run_container(state)
  cmd = build_run_command(state[:image_id])
  output = docker_command(cmd)
  parse_container_id(output)
end
socket_uri() click to toggle source
# File lib/kitchen/driver/docker_adv.rb, line 116
def socket_uri
  URI.parse(config[:socket])
end