providers/docker: execute the proxied SSH in a shell

This commit is contained in:
Mitchell Hashimoto 2014-04-15 21:18:04 -07:00
parent e947960c09
commit 4477545d3f
1 changed files with 67 additions and 4 deletions

View File

@ -1,3 +1,5 @@
require "tempfile"
module VagrantPlugins
module DockerProvider
# This communicator uses the host VM as proxy to communicate to the
@ -29,12 +31,73 @@ module VagrantPlugins
raise "NOT IMPLEMENTED YET"
end
def execute(command, opts=nil, &block)
@host_vm.communicate.execute(
"#{container_ssh_command} #{command}", opts, &block)
def execute(command, **opts, &block)
fence = {}
fence[:stderr] = "VAGRANT FENCE: #{Time.now.to_i} #{rand(100000)}"
fence[:stdout] = "VAGRANT FENCE: #{Time.now.to_i} #{rand(100000)}"
# We want to emulate how the SSH communicator actually executes
# things, so we build up the list of commands to execute in a
# giant shell script.
tf = Tempfile.new("vagrant")
tf.binmode
tf.write("export TERM=vt100\n")
tf.write("echo #{fence[:stdout]}\n")
tf.write("echo #{fence[:stderr]} >&2\n")
tf.write("#{command}\n")
tf.write("exit\n")
tf.close
# Upload the temp file to the remote machine
remote_temp = "/tmp/docker_#{Time.now.to_i}_#{rand(100000)}"
@host_vm.communicate.upload(tf.path, remote_temp)
# Determine the shell to execute. Prefer the explicitly passed in shell
# over the default configured shell. If we are using `sudo` then we
# need to wrap the shell in a `sudo` call.
shell_cmd = @machine.config.ssh.shell
shell_cmd = shell if opts[:shell]
shell_cmd = "sudo -E -H #{shell_cmd}" if opts[:sudo]
acc = {}
fenced = {}
result = @host_vm.communicate.execute(
"#{container_ssh_command} '#{shell_cmd}' <#{remote_temp}",
opts) do |type, data|
# If we don't have a block, we don't care about the data
next if !block
# We only care about stdout and stderr output
next if ![:stdout, :stderr].include?(type)
# If we reached our fence, then just output
if fenced[type]
block.call(type, data)
next
end
# Otherwise, accumulate
acc[type] = data
# Look for the fence
index = acc[type].index(fence[type])
next if !index
fenced[type] = true
index += fence[type].length
data = acc[type][index..-1].chomp
acc[type] = ""
block.call(type, data)
end
@host_vm.communicate.execute("rm #{remote_temp}", error_check: false)
return result
end
def sudo(command, opts=nil)
def sudo(command, **opts, &block)
opts = { sudo: true }.merge(opts)
execute(command, opts, &block)
end
def test(command, **opts)