provisioners: Import Docker provisioner code from Vocker
This commit is contained in:
parent
cfb258a55b
commit
0536817e90
|
@ -0,0 +1,15 @@
|
||||||
|
module VagrantPlugins
|
||||||
|
module Docker
|
||||||
|
module Cap
|
||||||
|
module Debian
|
||||||
|
module DockerConfigureAutoStart
|
||||||
|
def self.docker_configure_auto_start(machine)
|
||||||
|
if ! machine.communicate.test('grep -q \'\-r=true\' /etc/init/docker.conf')
|
||||||
|
machine.communicate.sudo("sed -i.bak 's/docker -d/docker -d -r=true/' /etc/init/docker.conf ")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,13 @@
|
||||||
|
module VagrantPlugins
|
||||||
|
module Docker
|
||||||
|
module Cap
|
||||||
|
module Debian
|
||||||
|
module DockerConfigureVagrantUser
|
||||||
|
def self.docker_configure_vagrant_user(machine)
|
||||||
|
machine.communicate.sudo("usermod -a -G docker #{machine.config.ssh.username || "vagrant"}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,26 @@
|
||||||
|
module VagrantPlugins
|
||||||
|
module Docker
|
||||||
|
module Cap
|
||||||
|
module Debian
|
||||||
|
module DockerInstall
|
||||||
|
def self.docker_install(machine, version)
|
||||||
|
package = 'lxc-docker'
|
||||||
|
package << "-#{version}" if version != :latest
|
||||||
|
|
||||||
|
machine.communicate.tap do |comm|
|
||||||
|
# TODO: Perform check on the host machine if aufs is installed and using LXC
|
||||||
|
if machine.provider_name != :lxc
|
||||||
|
comm.sudo("lsmod | grep aufs || modprobe aufs || apt-get install -y linux-image-extra-`uname -r`")
|
||||||
|
end
|
||||||
|
comm.sudo("apt-get install -y --force-yes -q curl")
|
||||||
|
comm.sudo("curl http://get.docker.io/gpg | apt-key add -")
|
||||||
|
comm.sudo("echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list")
|
||||||
|
comm.sudo("apt-get update")
|
||||||
|
comm.sudo("apt-get install -y --force-yes -q xz-utils #{package} -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confold'")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,13 @@
|
||||||
|
module VagrantPlugins
|
||||||
|
module Docker
|
||||||
|
module Cap
|
||||||
|
module Debian
|
||||||
|
module DockerStartService
|
||||||
|
def self.docker_start_service(machine)
|
||||||
|
machine.communicate.sudo("service docker start")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,13 @@
|
||||||
|
module VagrantPlugins
|
||||||
|
module Docker
|
||||||
|
module Cap
|
||||||
|
module Linux
|
||||||
|
module DockerInstalled
|
||||||
|
def self.docker_installed(machine)
|
||||||
|
machine.communicate.test("test -f /usr/bin/docker", sudo: true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,44 @@
|
||||||
|
require 'set'
|
||||||
|
|
||||||
|
module VagrantPlugins
|
||||||
|
module Docker
|
||||||
|
class Config < Vagrant.plugin("2", :config)
|
||||||
|
attr_reader :images, :containers
|
||||||
|
attr_accessor :version
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@images = Set.new
|
||||||
|
@containers = Hash.new
|
||||||
|
@version = :latest
|
||||||
|
end
|
||||||
|
|
||||||
|
def pull_images(*images)
|
||||||
|
@images += images.map(&:to_s)
|
||||||
|
end
|
||||||
|
|
||||||
|
def run(*args)
|
||||||
|
container_name = args.shift
|
||||||
|
params = {}
|
||||||
|
|
||||||
|
if args.empty?
|
||||||
|
params[:image] = container_name
|
||||||
|
elsif args.first.is_a?(String)
|
||||||
|
params[:image] = args.shift
|
||||||
|
params[:cmd] = container_name
|
||||||
|
else
|
||||||
|
params = args.shift
|
||||||
|
params[:cmd] ||= container_name
|
||||||
|
end
|
||||||
|
|
||||||
|
# TODO: Validate provided parameters before assignment
|
||||||
|
@containers[container_name.to_s] = params
|
||||||
|
end
|
||||||
|
|
||||||
|
def merge(other)
|
||||||
|
super.tap do |result|
|
||||||
|
result.pull_images *(other.images + self.images)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,102 @@
|
||||||
|
require 'digest/sha1'
|
||||||
|
|
||||||
|
module VagrantPlugins
|
||||||
|
module Docker
|
||||||
|
class DockerClient
|
||||||
|
def initialize(machine)
|
||||||
|
@machine = machine
|
||||||
|
end
|
||||||
|
|
||||||
|
def pull_images(*images)
|
||||||
|
@machine.communicate.tap do |comm|
|
||||||
|
images.each do |image|
|
||||||
|
comm.sudo("docker images | grep -q #{image} || docker pull #{image}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def start_service
|
||||||
|
if !daemon_running? && @machine.guest.capability?(:docker_start_service)
|
||||||
|
@machine.guest.capability(:docker_start_service)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def daemon_running?
|
||||||
|
@machine.communicate.test('test -f /var/run/docker.pid')
|
||||||
|
end
|
||||||
|
|
||||||
|
def run(containers)
|
||||||
|
containers.each do |name, config|
|
||||||
|
cids_dir = "/var/lib/vocker/cids"
|
||||||
|
config[:cidfile] ||= "#{cids_dir}/#{Digest::SHA1.hexdigest name}"
|
||||||
|
|
||||||
|
@machine.communicate.sudo("mkdir -p #{cids_dir}")
|
||||||
|
run_container({name: name}.merge config)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_container(config)
|
||||||
|
raise "Container's cidfile was not provided!" unless config[:cidfile]
|
||||||
|
|
||||||
|
id = "$(cat #{config[:cidfile]})"
|
||||||
|
|
||||||
|
if container_exist?(id)
|
||||||
|
start_container(id)
|
||||||
|
else
|
||||||
|
create_container(config)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def container_exist?(id)
|
||||||
|
@machine.communicate.test("sudo docker ps -a -q | grep -q #{id}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def start_container(id)
|
||||||
|
unless container_running?(id)
|
||||||
|
@machine.communicate.sudo("docker start #{id}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def container_running?(id)
|
||||||
|
@machine.communicate.test("sudo docker ps -q | grep #{id}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_container(config)
|
||||||
|
# DISCUSS: Does this really belong here?
|
||||||
|
ensure_bind_mounts_exist(config)
|
||||||
|
|
||||||
|
args = "-cidfile=#{config[:cidfile]} -d "
|
||||||
|
args << prepare_run_arguments(config)
|
||||||
|
@machine.communicate.sudo %[
|
||||||
|
rm -f #{config[:cidfile]}
|
||||||
|
docker run #{args} #{config[:image]} #{config[:cmd]}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def ensure_bind_mounts_exist(config)
|
||||||
|
Array(config[:volumes]).each do |volume|
|
||||||
|
if volume =~ /(.+):.+/
|
||||||
|
guest_vm_path = $1
|
||||||
|
@machine.communicate.sudo "mkdir -p #{guest_vm_path}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def prepare_run_arguments(config)
|
||||||
|
args = []
|
||||||
|
|
||||||
|
args << "-dns=#{config[:dns]}" if config[:dns]
|
||||||
|
args << "-name=#{config[:name]}" if config[:name]
|
||||||
|
args << "#{config[:additional_run_args]}" if config[:additional_run_args]
|
||||||
|
|
||||||
|
args += Array(config[:volumes]).map { |volume| "-v #{volume}" }
|
||||||
|
args += Array(config[:ports]).map { |port| "-p #{port}" }
|
||||||
|
args += Array(config[:links]).map { |link| "-link #{link}" }
|
||||||
|
|
||||||
|
args.compact.flatten.join ' '
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,41 @@
|
||||||
|
require_relative "errors"
|
||||||
|
|
||||||
|
module VagrantPlugins
|
||||||
|
module Docker
|
||||||
|
class DockerInstaller
|
||||||
|
def initialize(machine, version)
|
||||||
|
@machine = machine
|
||||||
|
@version = version
|
||||||
|
end
|
||||||
|
|
||||||
|
# This handles verifying the Docker installation, installing it if it was
|
||||||
|
# requested, and so on. This method will raise exceptions if things are
|
||||||
|
# wrong.
|
||||||
|
def ensure_installed
|
||||||
|
if !@machine.guest.capability?(:docker_installed)
|
||||||
|
@machine.ui.warn(I18n.t("vagrant.docker_cant_detect"))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if !@machine.guest.capability(:docker_installed)
|
||||||
|
@machine.ui.info(I18n.t("vagrant.docker_installing"))
|
||||||
|
@machine.guest.capability(:docker_install, @version)
|
||||||
|
|
||||||
|
if !@machine.guest.capability(:docker_installed)
|
||||||
|
raise Errors::DockerInstallFailed
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if @machine.guest.capability?(:docker_configure_auto_start)
|
||||||
|
@machine.guest.capability(:docker_configure_auto_start)
|
||||||
|
else
|
||||||
|
@machine.env.ui.warn I18n.t('vagrant.docker_auto_start_not_available')
|
||||||
|
end
|
||||||
|
|
||||||
|
if @machine.guest.capability?(:docker_configure_vagrant_user)
|
||||||
|
@machine.guest.capability(:docker_configure_vagrant_user)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,11 @@
|
||||||
|
module VagrantPlugins
|
||||||
|
module Docker
|
||||||
|
module Errors
|
||||||
|
class DockerInstallFailed < ::Vagrant::Errors::VagrantError
|
||||||
|
end
|
||||||
|
|
||||||
|
class DockerNotRunning < ::Vagrant::Errors::VagrantError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,48 @@
|
||||||
|
require "vagrant"
|
||||||
|
|
||||||
|
module VagrantPlugins
|
||||||
|
module Docker
|
||||||
|
class Plugin < Vagrant.plugin("2")
|
||||||
|
name "docker"
|
||||||
|
description <<-DESC
|
||||||
|
Provides support for provisioning your virtual machines with
|
||||||
|
Docker images and containers.
|
||||||
|
DESC
|
||||||
|
|
||||||
|
config(:docker, :provisioner) do
|
||||||
|
require_relative "config"
|
||||||
|
Config
|
||||||
|
end
|
||||||
|
|
||||||
|
guest_capability("debian", "docker_install") do
|
||||||
|
require_relative "cap/debian/docker_install"
|
||||||
|
Cap::Debian::DockerInstall
|
||||||
|
end
|
||||||
|
|
||||||
|
guest_capability("debian", "docker_configure_auto_start") do
|
||||||
|
require_relative "cap/debian/docker_configure_auto_start"
|
||||||
|
Cap::Debian::DockerConfigureAutoStart
|
||||||
|
end
|
||||||
|
|
||||||
|
guest_capability("debian", "docker_configure_vagrant_user") do
|
||||||
|
require_relative "cap/debian/docker_configure_vagrant_user"
|
||||||
|
Cap::Debian::DockerConfigureVagrantUser
|
||||||
|
end
|
||||||
|
|
||||||
|
guest_capability("debian", "docker_start_service") do
|
||||||
|
require_relative "cap/debian/docker_start_service"
|
||||||
|
Cap::Debian::DockerStartService
|
||||||
|
end
|
||||||
|
|
||||||
|
guest_capability("linux", "docker_installed") do
|
||||||
|
require_relative "cap/linux/docker_installed"
|
||||||
|
Cap::Linux::DockerInstalled
|
||||||
|
end
|
||||||
|
|
||||||
|
provisioner(:docker) do
|
||||||
|
require_relative "provisioner"
|
||||||
|
Provisioner
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,41 @@
|
||||||
|
require_relative "errors"
|
||||||
|
require_relative "docker_client"
|
||||||
|
require_relative "docker_installer"
|
||||||
|
|
||||||
|
module VagrantPlugins
|
||||||
|
module Docker
|
||||||
|
# TODO: Improve handling of vagrant-lxc specifics (like checking for apparmor
|
||||||
|
# profile stuff + autocorrection)
|
||||||
|
class Provisioner < Vagrant.plugin("2", :provisioner)
|
||||||
|
def initialize(machine, config, installer = nil, client = nil)
|
||||||
|
super(machine, config)
|
||||||
|
# TODO: Rename to installer / client (drop docker suffix)
|
||||||
|
@installer = installer || DockerInstaller.new(@machine, config.version)
|
||||||
|
@client = client || DockerClient.new(@machine)
|
||||||
|
end
|
||||||
|
|
||||||
|
def provision
|
||||||
|
@logger = Log4r::Logger.new("vagrant::provisioners::vocker")
|
||||||
|
|
||||||
|
@logger.info("Checking for Docker installation...")
|
||||||
|
@installer.ensure_installed
|
||||||
|
|
||||||
|
# Attempt to start service if not running
|
||||||
|
@client.start_service
|
||||||
|
unless @client.daemon_running?
|
||||||
|
raise Errors::DockerNotRunning
|
||||||
|
end
|
||||||
|
|
||||||
|
if config.images.any?
|
||||||
|
@machine.ui.info(I18n.t("vagrant.docker_pulling_images"))
|
||||||
|
@client.pull_images(*config.images)
|
||||||
|
end
|
||||||
|
|
||||||
|
if config.containers.any?
|
||||||
|
@machine.ui.info(I18n.t("vagrant.docker_starting_containers"))
|
||||||
|
@client.run(config.containers)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue