From e90e45a8fb27d7c28771017cfdfc173cf43ab421 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 29 Apr 2014 15:51:32 -0700 Subject: [PATCH 1/3] providers/docker: pty flag, not functional yet --- plugins/providers/docker/action/create.rb | 4 ++++ plugins/providers/docker/command/run.rb | 9 ++++++++- plugins/providers/docker/driver.rb | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/plugins/providers/docker/action/create.rb b/plugins/providers/docker/action/create.rb index fe747e52d..3068d3b58 100644 --- a/plugins/providers/docker/action/create.rb +++ b/plugins/providers/docker/action/create.rb @@ -26,6 +26,9 @@ module VagrantPlugins # No ports should be shared to the host params[:ports] = [] + # Allocate a pty if it was requested + params[:pty] = true if env[:run_pty] + # We link to our original container # TODO end @@ -94,6 +97,7 @@ module VagrantPlugins name: container_name, ports: forwarded_ports, privileged: @provider_config.privileged, + pty: false, volumes: @provider_config.volumes, } end diff --git a/plugins/providers/docker/command/run.rb b/plugins/providers/docker/command/run.rb index 4de85dd76..25a5d786e 100644 --- a/plugins/providers/docker/command/run.rb +++ b/plugins/providers/docker/command/run.rb @@ -9,6 +9,7 @@ module VagrantPlugins def execute options = {} options[:detach] = false + options[:pty] = false opts = OptionParser.new do |o| o.banner = "Usage: vagrant docker-run [command...]" @@ -19,6 +20,10 @@ module VagrantPlugins o.on("--[no-]detach", "Run in the background") do |d| options[:detach] = d end + + o.on("-t", "--[no-]tty", "Allocate a pty") do |t| + options[:pty] = t + end end # Parse out the extra args to send to SSH, which is everything @@ -41,7 +46,9 @@ module VagrantPlugins machine.action( :run_command, run_command: command, - run_detach: options[:detach]) + run_detach: options[:detach], + run_pty: options[:pty], + ) end 0 diff --git a/plugins/providers/docker/driver.rb b/plugins/providers/docker/driver.rb index a85f3e559..3661b5522 100644 --- a/plugins/providers/docker/driver.rb +++ b/plugins/providers/docker/driver.rb @@ -44,6 +44,7 @@ module VagrantPlugins run_cmd += volumes.map { |v| ['-v', v.to_s] } run_cmd += %W(--privileged) if params[:privileged] run_cmd += %W(-h #{params[:hostname]}) if params[:hostname] + run_cmd << "-t" if params[:pty] run_cmd += params[:extra_args] if params[:extra_args] run_cmd += [image, cmd] From 0bb523ebb0d1528ca6cbad29dfadd81dd2942794 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 29 Apr 2014 16:27:22 -0700 Subject: [PATCH 2/3] providers/docker: use ssh_run if asking for stdin on execute --- lib/vagrant/util/ssh.rb | 5 ----- plugins/providers/docker/action/create.rb | 14 ++++++++++++-- plugins/providers/docker/driver.rb | 10 +++++----- plugins/providers/docker/executor/local.rb | 2 +- plugins/providers/docker/executor/vagrant.rb | 16 +++++++++++++++- 5 files changed, 33 insertions(+), 14 deletions(-) diff --git a/lib/vagrant/util/ssh.rb b/lib/vagrant/util/ssh.rb index 487b972b0..681c8ad20 100644 --- a/lib/vagrant/util/ssh.rb +++ b/lib/vagrant/util/ssh.rb @@ -165,11 +165,6 @@ module Vagrant # If we're still here, it means we're supposed to subprocess # out to ssh rather than exec it. - # - # There is a lot of special-case code for Windows below. Windows - # has a bug with creating a TTY file handle for stdin so SSH doesn't - # work well. We simulate it by copying stdin over. It isn't ideal, - # but it kind of works. LOGGER.info("Executing SSH in subprocess: #{command_options.inspect}") process = ChildProcess.build("ssh", *command_options) process.io.inherit! diff --git a/plugins/providers/docker/action/create.rb b/plugins/providers/docker/action/create.rb index 3068d3b58..c65ebdf18 100644 --- a/plugins/providers/docker/action/create.rb +++ b/plugins/providers/docker/action/create.rb @@ -58,10 +58,20 @@ module VagrantPlugins elsif params[:detach] env[:ui].detail(" \n"+I18n.t("docker_provider.running_detached")) else + ui_opts = {} + + # If we're running with a pty, we want the output to look as + # authentic as possible. We don't prefix things and we don't + # output a newline. + if env[:run_pty] + ui_opts[:prefix] = false + ui_opts[:new_line] = false + end + # For run commands, we run it and stream back the output env[:ui].detail(" \n"+I18n.t("docker_provider.running")+"\n ") - @driver.create(params) do |type, data| - env[:ui].detail(data.chomp) + @driver.create(params, stdin: env[:run_pty]) do |type, data| + env[:ui].detail(data.chomp, **ui_opts) end end diff --git a/plugins/providers/docker/driver.rb b/plugins/providers/docker/driver.rb index 3661b5522..4f4a4e7fc 100644 --- a/plugins/providers/docker/driver.rb +++ b/plugins/providers/docker/driver.rb @@ -25,7 +25,7 @@ module VagrantPlugins match[1] end - def create(params, &block) + def create(params, **opts, &block) image = params.fetch(:image) links = params.fetch(:links) ports = Array(params[:ports]) @@ -44,11 +44,11 @@ module VagrantPlugins run_cmd += volumes.map { |v| ['-v', v.to_s] } run_cmd += %W(--privileged) if params[:privileged] run_cmd += %W(-h #{params[:hostname]}) if params[:hostname] - run_cmd << "-t" if params[:pty] + run_cmd << "-i" << "-t" if params[:pty] run_cmd += params[:extra_args] if params[:extra_args] run_cmd += [image, cmd] - execute(*run_cmd.flatten, &block).chomp + execute(*run_cmd.flatten, **opts, &block).chomp end def state(cid) @@ -131,8 +131,8 @@ module VagrantPlugins end end - def execute(*cmd, &block) - @executor.execute(*cmd, &block) + def execute(*cmd, **opts, &block) + @executor.execute(*cmd, **opts, &block) end end end diff --git a/plugins/providers/docker/executor/local.rb b/plugins/providers/docker/executor/local.rb index 5393a868a..61b633bc5 100644 --- a/plugins/providers/docker/executor/local.rb +++ b/plugins/providers/docker/executor/local.rb @@ -7,7 +7,7 @@ module VagrantPlugins # The Local executor executes a Docker client that is running # locally. class Local - def execute(*cmd, &block) + def execute(*cmd, **opts, &block) # Append in the options for subprocess cmd << { :notify => [:stdout, :stderr] } diff --git a/plugins/providers/docker/executor/vagrant.rb b/plugins/providers/docker/executor/vagrant.rb index 85f274614..c25af2006 100644 --- a/plugins/providers/docker/executor/vagrant.rb +++ b/plugins/providers/docker/executor/vagrant.rb @@ -10,12 +10,15 @@ module VagrantPlugins @host_machine = host_machine end - def execute(*cmd, &block) + def execute(*cmd, **opts, &block) quote = '"' cmd = cmd.map do |a| "#{quote}#{::Vagrant::Util::ShellQuote.escape(a, quote)}#{quote}" end.join(" ") + # If we want stdin, we just run in a full subprocess + return ssh_run(cmd) if opts[:stdin] + # Add a start fence so we know when to start reading output. # We have to do this because boot2docker outputs a login shell # boot2docker version that we get otherwise and messes up output. @@ -61,6 +64,17 @@ module VagrantPlugins stdout.chomp end + + protected + + def ssh_run(cmd) + @host_machine.action( + :ssh_run, + ssh_run_command: cmd, + ) + + "" + end end end end From 19af4b70e6f4552ccb036a186d5be3be1589b66e Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 29 Apr 2014 16:31:43 -0700 Subject: [PATCH 3/3] providers/docker: with a pty, single target the docker-run cmd --- plugins/providers/docker/command/run.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/providers/docker/command/run.rb b/plugins/providers/docker/command/run.rb index 25a5d786e..b130ca346 100644 --- a/plugins/providers/docker/command/run.rb +++ b/plugins/providers/docker/command/run.rb @@ -41,7 +41,10 @@ module VagrantPlugins argv = parse_options(opts) return if !argv - with_target_vms(argv, provider: :docker) do |machine| + target_opts = { provider: :docker } + target_opts[:single_target] = options[:pty] + + with_target_vms(argv, target_opts) do |machine| # Run it! machine.action( :run_command,