Enable WinSSH shell for `vagrant ssh -c` (#11258)
This commit changes the behavior of the builtin SSHRun action to use a Windows
shell if the WinSSH communicator is active. This allows for running one-off SSH
commands with Windows Command Prompt or PowerShell. By default, this will not
allocate a TTY for any SSH commands.
Example usage:
```
vagrant ssh -c 'dir "c:\program files"'
```
Updates docs to reflect a change made in
a55a53e6a4
.
This commit is contained in:
parent
f0b8c0737f
commit
7fb7dd8608
|
@ -36,17 +36,35 @@ module Vagrant
|
|||
|
||||
# Get the command and wrap it in a login shell
|
||||
command = ShellQuote.escape(env[:ssh_run_command], "'")
|
||||
command = "#{env[:machine].config.ssh.shell} -c '#{command}'"
|
||||
|
||||
if env[:machine].config.vm.communicator == :winssh
|
||||
shell = env[:machine].config.winssh.shell
|
||||
else
|
||||
shell = env[:machine].config.ssh.shell
|
||||
end
|
||||
|
||||
if shell == "cmd"
|
||||
# Add an extra space to the command so cmd.exe quoting works
|
||||
# properly
|
||||
command = "#{shell} /C #{command} "
|
||||
elsif shell == "powershell"
|
||||
command = "$ProgressPreference = \"SilentlyContinue\"; #{command}"
|
||||
command = Base64.strict_encode64(command.encode("UTF-16LE", "UTF-8"))
|
||||
command = "#{shell} -encodedCommand #{command}"
|
||||
else
|
||||
command = "#{shell} -c '#{command}'"
|
||||
end
|
||||
|
||||
# Execute!
|
||||
opts = env[:ssh_opts] || {}
|
||||
opts[:extra_args] ||= []
|
||||
|
||||
# Allow the user to specify a tty or non-tty manually, but if they
|
||||
# don't then we default to a TTY
|
||||
# don't then we default to a TTY unless they are using WinSSH
|
||||
if !opts[:extra_args].include?("-t") &&
|
||||
!opts[:extra_args].include?("-T") &&
|
||||
env[:tty]
|
||||
env[:tty] &&
|
||||
env[:machine].config.vm.communicator != :winssh
|
||||
opts[:extra_args] << "-t"
|
||||
end
|
||||
|
||||
|
|
|
@ -18,8 +18,14 @@ describe Vagrant::Action::Builtin::SSHRun do
|
|||
)
|
||||
end
|
||||
|
||||
let(:vm) do
|
||||
double("vm",
|
||||
communicator: nil
|
||||
)
|
||||
end
|
||||
|
||||
# Configuration mock
|
||||
let(:config) { double("config", ssh: ssh) }
|
||||
let(:config) { double("config", ssh: ssh, vm: vm) }
|
||||
|
||||
let(:machine) do
|
||||
double("machine",
|
||||
|
@ -80,4 +86,63 @@ describe Vagrant::Action::Builtin::SSHRun do
|
|||
env[:ssh_run_command] = "echo test"
|
||||
described_class.new(app, env).call(env)
|
||||
end
|
||||
|
||||
context "when using the WinSSH communicator" do
|
||||
let(:winssh) { double("winssh", shell: "foo") }
|
||||
|
||||
before do
|
||||
expect(vm).to receive(:communicator).and_return(:winssh)
|
||||
expect(config).to receive(:winssh).and_return(winssh)
|
||||
env[:tty] = nil
|
||||
end
|
||||
|
||||
it "should use the WinSSH shell for running ssh commands" do
|
||||
ssh_info = { foo: :bar }
|
||||
opts = {:extra_args=>["foo -c 'dir'"], :subprocess=>true}
|
||||
|
||||
expect(ssh_klass).to receive(:exec).
|
||||
with(ssh_info, opts)
|
||||
|
||||
env[:ssh_info] = ssh_info
|
||||
env[:ssh_run_command] = "dir"
|
||||
described_class.new(app, env).call(env)
|
||||
end
|
||||
|
||||
context "when shell is cmd" do
|
||||
before do
|
||||
expect(winssh).to receive(:shell).and_return('cmd')
|
||||
end
|
||||
|
||||
it "should use appropriate options for cmd" do
|
||||
ssh_info = { foo: :bar }
|
||||
opts = {:extra_args=>["cmd /C dir "], :subprocess=>true}
|
||||
|
||||
expect(ssh_klass).to receive(:exec).
|
||||
with(ssh_info, opts)
|
||||
|
||||
env[:ssh_info] = ssh_info
|
||||
env[:ssh_run_command] = "dir"
|
||||
described_class.new(app, env).call(env)
|
||||
end
|
||||
end
|
||||
|
||||
context "when shell is powershell" do
|
||||
before do
|
||||
expect(winssh).to receive(:shell).and_return('powershell')
|
||||
end
|
||||
|
||||
it "should base64 encode the command" do
|
||||
ssh_info = { foo: :bar }
|
||||
encoded_command = "JABQAHIAbwBnAHIAZQBzAHMAUAByAGUAZgBlAHIAZQBuAGMAZQAgAD0AIAAiAFMAaQBsAGUAbgB0AGwAeQBDAG8AbgB0AGkAbgB1AGUAIgA7ACAAZABpAHIA"
|
||||
opts = {:extra_args=>["powershell -encodedCommand #{encoded_command}"], :subprocess=>true}
|
||||
|
||||
expect(ssh_klass).to receive(:exec).
|
||||
with(ssh_info, opts)
|
||||
|
||||
env[:ssh_info] = ssh_info
|
||||
env[:ssh_run_command] = "dir"
|
||||
described_class.new(app, env).call(env)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -126,9 +126,7 @@ net-ssh library (ignored by the `ssh` executable) and should not be used in gene
|
|||
This defaults to the value of `config.ssh.username`.
|
||||
|
||||
* `config.ssh.shell` (string) - The shell to use when executing SSH commands from
|
||||
Vagrant. By default this is `bash -l`. Note that this has no effect on
|
||||
the shell you get when you run `vagrant ssh`. This configuration option
|
||||
only affects the shell to use when executing commands internally in Vagrant.
|
||||
Vagrant. By default this is `bash -l`.
|
||||
|
||||
* `config.ssh.sudo_command` (string) - The command to use when executing a command
|
||||
with `sudo`. This defaults to `sudo -E -H %c`. The `%c` will be replaced by
|
||||
|
|
|
@ -48,9 +48,7 @@ packets every 5 seconds by default to keep connections alive.
|
|||
|
||||
* `config.winssh.shell` (string) - The shell to use when executing SSH commands from
|
||||
Vagrant. By default this is `cmd`. Valid values are `"cmd"` or `"powershell"`.
|
||||
Note that this has no effect on the shell you get when you run `vagrant ssh`.
|
||||
This configuration option only affects the shell to use when executing commands
|
||||
internally in Vagrant.
|
||||
When the WinSSH provider is enabled, this shell will be used when you run `vagrant ssh`.
|
||||
|
||||
* `config.winssh.export_command_template` (string) - The template used to generate
|
||||
exported environment variables in the active session. This can be useful
|
||||
|
|
Loading…
Reference in New Issue