Merge pull request #8722 from briancain/add-post-setup-proc-for-docker

Add post-install provisioner to docker provisioner
This commit is contained in:
Brian Cain 2017-06-28 08:32:23 -07:00 committed by GitHub
commit 0225d63055
7 changed files with 153 additions and 5 deletions

View File

@ -4,9 +4,11 @@ module VagrantPlugins
module DockerProvisioner module DockerProvisioner
class Config < Vagrant.plugin("2", :config) class Config < Vagrant.plugin("2", :config)
attr_reader :images attr_reader :images
attr_accessor :post_install_provisioner
def initialize def initialize
@images = Set.new @images = Set.new
@post_install_provisioner = nil
@__build_images = [] @__build_images = []
@__containers = Hash.new { |h, k| h[k] = {} } @__containers = Hash.new { |h, k| h[k] = {} }
@ -38,6 +40,15 @@ module VagrantPlugins
@images += images.map(&:to_s) @images += images.map(&:to_s)
end end
def post_install_provision(name, **options, &block)
# Abort
raise DockerError, :wrong_provisioner if options[:type] == "docker"
proxy = VagrantPlugins::Kernel_V2::VMConfig.new
proxy.provision(name, **options, &block)
@post_install_provisioner = proxy.provisioners.first
end
def run(name, **options) def run(name, **options)
@__containers[name.to_s] = options.dup @__containers[name.to_s] = options.dup
end end

View File

@ -8,10 +8,12 @@ module VagrantPlugins
# This handles verifying the Docker installation, installing it if it was # This handles verifying the Docker installation, installing it if it was
# requested, and so on. This method will raise exceptions if things are # requested, and so on. This method will raise exceptions if things are
# wrong. # wrong.
# @return [Boolean] - false if docker cannot be detected on machine, else
# true if docker installs correctly or is installed
def ensure_installed def ensure_installed
if !@machine.guest.capability?(:docker_installed) if !@machine.guest.capability?(:docker_installed)
@machine.ui.warn(I18n.t("vagrant.docker_cant_detect")) @machine.ui.warn(I18n.t("vagrant.docker_cant_detect"))
return return false
end end
if !@machine.guest.capability(:docker_installed) if !@machine.guest.capability(:docker_installed)
@ -26,6 +28,8 @@ module VagrantPlugins
if @machine.guest.capability?(:docker_configure_vagrant_user) if @machine.guest.capability?(:docker_configure_vagrant_user)
@machine.guest.capability(:docker_configure_vagrant_user) @machine.guest.capability(:docker_configure_vagrant_user)
end end
true
end end
end end
end end

View File

@ -19,7 +19,16 @@ module VagrantPlugins
@logger = Log4r::Logger.new("vagrant::provisioners::docker") @logger = Log4r::Logger.new("vagrant::provisioners::docker")
@logger.info("Checking for Docker installation...") @logger.info("Checking for Docker installation...")
@installer.ensure_installed if @installer.ensure_installed
if !config.post_install_provisioner.nil?
@logger.info("Running post setup provision script...")
env = {
callable: method(:run_provisioner),
provisioner: config.post_install_provisioner,
machine: machine}
machine.env.hook(:run_provisioner, env)
end
end
# Attempt to start service if not running # Attempt to start service if not running
@client.start_service @client.start_service
@ -40,6 +49,14 @@ module VagrantPlugins
@client.run(config.containers) @client.run(config.containers)
end end
end end
def run_provisioner(env)
klass = Vagrant.plugin("2").manager.provisioners[env[:provisioner].type]
result = klass.new(env[:machine], env[:provisioner].config)
result.config.finalize!
result.provision
end
end end
end end
end end

View File

@ -2361,6 +2361,9 @@ en:
Please check https://docs.ansible.com/intro_installation.html#control-machine-requirements Please check https://docs.ansible.com/intro_installation.html#control-machine-requirements
docker: docker:
wrong_provisioner: |-
The Docker post-install provisioner cannot also take a Docker post-install
provisioner
not_running: "Docker is not running on the guest VM." not_running: "Docker is not running on the guest VM."
install_failed: "Docker installation failed." install_failed: "Docker installation failed."

View File

@ -1,6 +1,7 @@
require File.expand_path("../../../../base", __FILE__) require File.expand_path("../../../../base", __FILE__)
require Vagrant.source_root.join("plugins/provisioners/docker/config") require Vagrant.source_root.join("plugins/provisioners/docker/config")
require Vagrant.source_root.join("plugins/kernel_v2/config/vm")
describe VagrantPlugins::DockerProvisioner::Config do describe VagrantPlugins::DockerProvisioner::Config do
subject { described_class.new } subject { described_class.new }
@ -137,4 +138,25 @@ describe VagrantPlugins::DockerProvisioner::Config do
}) })
end end
end end
describe "#post_install_provision" do
it "raises an error if 'docker' provisioner was provided" do
expect {subject.post_install_provision("myprov", :type=>"docker", :inline=>"echo 'hello'")}
.to raise_error()
end
it "setups a basic provisioner" do
prov = double()
mock_provisioner = "mock"
mock_provisioners = [mock_provisioner]
allow(VagrantPlugins::Kernel_V2::VMConfig).to receive(:new).
and_return(prov)
allow(prov).to receive(:provision).and_return(mock_provisioners)
allow(prov).to receive(:provisioners).and_return(mock_provisioners)
subject.post_install_provision("myprov", :inline=>"echo 'hello'")
expect(subject.post_install_provisioner).to eq(mock_provisioner)
end
end
end end

View File

@ -0,0 +1,79 @@
require File.expand_path("../../../../base", __FILE__)
require Vagrant.source_root.join("plugins/provisioners/docker/provisioner")
describe VagrantPlugins::DockerProvisioner::Provisioner do
include_context "unit"
subject { described_class.new(machine, config, installer, client) }
let(:iso_env) do
# We have to create a Vagrantfile so there is a root path
env = isolated_environment
env.vagrantfile("")
env.create_vagrant_env
end
let(:machine) { iso_env.machine(iso_env.machine_names[0], :dummy) }
let(:config) { double("config") }
let(:communicator) { double("comm") }
let(:guest) { double("guest") }
let(:client) { double("client") }
let(:installer) { double("installer") }
let(:hook) { double("hook") }
before do
machine.stub(communicate: communicator)
machine.stub(guest: guest)
communicator.stub(execute: true)
communicator.stub(upload: true)
guest.stub(capability?: false)
guest.stub(capability: false)
client.stub(start_service: true)
client.stub(daemon_running?: true)
config.stub(images: Set.new)
config.stub(build_images: Set.new)
config.stub(containers: Hash.new)
end
describe "#provision" do
let(:provisioner) do
prov = VagrantPlugins::Kernel_V2::VagrantConfigProvisioner.new("spec-test", :shell)
prov.config = {}
prov
end
it "invokes a post_install_provisioner if defined and docker is installed" do
installer.stub(ensure_installed: true)
allow(config).to receive(:post_install_provisioner).and_return(provisioner)
allow(machine).to receive(:env).and_return(iso_env)
allow(machine.env).to receive(:hook).and_return(true)
expect(machine.env).to receive(:hook).with(:run_provisioner, anything)
subject.provision()
end
it "does not invoke post_install_provisioner if not defined" do
installer.stub(ensure_installed: true)
allow(config).to receive(:post_install_provisioner).and_return(nil)
allow(machine).to receive(:env).and_return(iso_env)
allow(machine.env).to receive(:hook).and_return(true)
expect(machine.env).not_to receive(:hook).with(:run_provisioner, anything)
subject.provision()
end
it "raises an error if docker daemon isn't running" do
allow(installer).to receive(:ensure_installed).and_return(false)
allow(client).to receive(:start_service).and_return(false)
allow(client).to receive(:daemon_running?).and_return(false)
expect { subject.provision() }.
to raise_error(VagrantPlugins::DockerProvisioner::DockerError)
end
end
end

View File

@ -53,6 +53,9 @@ of these functions have examples in more detailed sections below.
* `pull_images` - Pull the given images. This does not start these images. * `pull_images` - Pull the given images. This does not start these images.
* `post_install_provisioner` - A [provisioner block](/docs/provisioning) that runs post docker
installation.
* `run` - Run a container and configure it to start on boot. This can * `run` - Run a container and configure it to start on boot. This can
only be specified once. only be specified once.
@ -191,6 +194,15 @@ that are generally useful to know if you are using this provisioner.
### Customize `/etc/default/docker` ### Customize `/etc/default/docker`
To customize this file, use a shell provisioner before the Docker provisioner To customize this file, use the `post_install_provisioner` shell provisioner.
that sets this file up. The Docker provisioner will not modify this file
in a destructive way. ```ruby
Vagrant.configure("2") do |config|
config.vm.provision "docker" do |d|
d.post_install_provision "shell", inline:"echo export http_proxy='http://127.0.0.1:3128/' >> /etc/default/docker"
d.run "ubuntu",
cmd: "bash -l",
args: "-v '/vagrant:/var/www'"
end
end
```