providers/docker: use a custom communicator to go through host VM
This commit is contained in:
parent
bdade7d5a6
commit
e947960c09
|
@ -23,7 +23,7 @@ module Vagrant
|
||||||
#
|
#
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
def self.match?(machine)
|
def self.match?(machine)
|
||||||
false
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
# Initializes the communicator with the machine that we will be
|
# Initializes the communicator with the machine that we will be
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
module VagrantPlugins
|
||||||
|
module DockerProvider
|
||||||
|
# This communicator uses the host VM as proxy to communicate to the
|
||||||
|
# actual Docker container via SSH.
|
||||||
|
class Communicator < Vagrant.plugin("2", :communicator)
|
||||||
|
def initialize(machine)
|
||||||
|
@machine = machine
|
||||||
|
@host_vm = machine.provider.host_vm
|
||||||
|
|
||||||
|
# We only work on the Docker provider
|
||||||
|
if machine.provider_name != :docker
|
||||||
|
raise Errors::CommunicatorNotDocker
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
# Communicator Methods
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
def ready?
|
||||||
|
# We can't be ready if we can't talk to the host VM
|
||||||
|
return false if !@host_vm.communicate.ready?
|
||||||
|
|
||||||
|
# We're ready if we can establish an SSH connection to the container
|
||||||
|
@host_vm.communicate.test("#{container_ssh_command} exit")
|
||||||
|
end
|
||||||
|
|
||||||
|
def download(from, to)
|
||||||
|
raise "NOT IMPLEMENTED YET"
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute(command, opts=nil, &block)
|
||||||
|
@host_vm.communicate.execute(
|
||||||
|
"#{container_ssh_command} #{command}", opts, &block)
|
||||||
|
end
|
||||||
|
|
||||||
|
def sudo(command, opts=nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test(command, **opts)
|
||||||
|
opts = { error_check: false }.merge(opts)
|
||||||
|
execute(command, opts) == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
def upload(from, to)
|
||||||
|
# First, we upload this to the host VM to some temporary directory.
|
||||||
|
to_temp = "/tmp/docker_#{Time.now.to_i}_#{rand(100000)}"
|
||||||
|
@host_vm.communicate.upload(from, to_temp)
|
||||||
|
|
||||||
|
# Then, we use `cat` to get that file into the Docker container.
|
||||||
|
@host_vm.communicate.execute(
|
||||||
|
"#{container_ssh_command} 'cat >#{to}' <#{to_temp}")
|
||||||
|
|
||||||
|
# Remove the temporary file
|
||||||
|
@host_vm.communicate.execute("rm #{to_temp}", error_check: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
# Other Methods
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
|
||||||
|
# This returns the raw SSH command string that can be used to
|
||||||
|
# connect via SSH to the container if you're on the same machine
|
||||||
|
# as the container.
|
||||||
|
#
|
||||||
|
# @return [String]
|
||||||
|
def container_ssh_command
|
||||||
|
# Get the container's SSH info
|
||||||
|
info = @machine.ssh_info
|
||||||
|
info[:port] ||= 22
|
||||||
|
|
||||||
|
# Build the SSH command
|
||||||
|
"ssh -i /home/vagrant/insecure " +
|
||||||
|
"-o Compression=yes " +
|
||||||
|
"-o ConnectTimeout=5 " +
|
||||||
|
"-o StrictHostKeyChecking=no " +
|
||||||
|
"-o UserKnownHostsFile=/dev/null " +
|
||||||
|
"-p#{info[:port]} " +
|
||||||
|
"#{info[:username]}@#{info[:host]}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -5,6 +5,10 @@ module VagrantPlugins
|
||||||
error_namespace("docker_provider.errors")
|
error_namespace("docker_provider.errors")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class CommunicatorNonDocker < DockerError
|
||||||
|
error_key(:communicator_non_docker)
|
||||||
|
end
|
||||||
|
|
||||||
class ExecuteError < DockerError
|
class ExecuteError < DockerError
|
||||||
error_key(:execute_error)
|
error_key(:execute_error)
|
||||||
end
|
end
|
||||||
|
|
|
@ -28,6 +28,12 @@ module VagrantPlugins
|
||||||
Command::Logs
|
Command::Logs
|
||||||
end
|
end
|
||||||
|
|
||||||
|
communicator(:docker_hostvm) do
|
||||||
|
require_relative "communicator"
|
||||||
|
init!
|
||||||
|
Communicator
|
||||||
|
end
|
||||||
|
|
||||||
config(:docker, :provider) do
|
config(:docker, :provider) do
|
||||||
require_relative 'config'
|
require_relative 'config'
|
||||||
init!
|
init!
|
||||||
|
|
|
@ -11,6 +11,12 @@ module VagrantPlugins
|
||||||
def initialize(machine)
|
def initialize(machine)
|
||||||
@logger = Log4r::Logger.new("vagrant::provider::docker")
|
@logger = Log4r::Logger.new("vagrant::provider::docker")
|
||||||
@machine = machine
|
@machine = machine
|
||||||
|
|
||||||
|
if host_vm?
|
||||||
|
# We need to use a special communicator that proxies our
|
||||||
|
# SSH requests over our host VM to the container itself.
|
||||||
|
@machine.config.vm.communicator = :docker_hostvm
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# @see Vagrant::Plugin::V2::Provider#action
|
# @see Vagrant::Plugin::V2::Provider#action
|
||||||
|
|
|
@ -63,6 +63,12 @@ en:
|
||||||
run exits and doesn't keep running.
|
run exits and doesn't keep running.
|
||||||
|
|
||||||
errors:
|
errors:
|
||||||
|
communicator_non_docker: |-
|
||||||
|
The "docker_hostvm" communicator was specified on a machine that
|
||||||
|
is not provided by the Docker provider. This is a bug with your
|
||||||
|
Vagrantfile. Please contact the creator of your Vagrant environment
|
||||||
|
and notify them to not use this communicator for anything except the
|
||||||
|
"docker" provider.
|
||||||
config:
|
config:
|
||||||
cmd_not_set: |-
|
cmd_not_set: |-
|
||||||
The Docker command has not been set!
|
The Docker command has not been set!
|
||||||
|
|
Loading…
Reference in New Issue