This works by now calling the `:ssh` action on the provider. This action is allowed to do whatever it pleases, but should at some point probably call the `SSHExec` built-in middleware. The `SSHExec` built-in middleware was added. This uses the information returned by `Machine#ssh_info` and uses the `Vagrant::Util::SSH` helper to exec into the remote machine. The provider should do any work upfront in verifying that the machine is ready to be SSHed into.
91 lines
2.9 KiB
Ruby
91 lines
2.9 KiB
Ruby
require 'optparse'
|
|
|
|
module VagrantPlugins
|
|
module CommandSSH
|
|
class Command < Vagrant.plugin("1", :command)
|
|
def execute
|
|
options = {}
|
|
|
|
opts = OptionParser.new do |opts|
|
|
opts.banner = "Usage: vagrant ssh [vm-name] [-c command] [-- extra ssh args]"
|
|
|
|
opts.separator ""
|
|
|
|
opts.on("-c", "--command COMMAND", "Execute an SSH command directly.") do |c|
|
|
options[:command] = c
|
|
end
|
|
opts.on("-p", "--plain", "Plain mode, leaves authentication up to user.") do |p|
|
|
options[:plain_mode] = p
|
|
end
|
|
end
|
|
|
|
# Parse the options and return if we don't have any target.
|
|
argv = parse_options(opts)
|
|
return if !argv
|
|
|
|
# Parse out the extra args to send to SSH, which is everything
|
|
# after the "--"
|
|
ssh_args = ARGV.drop_while { |i| i != "--" }
|
|
ssh_args = ssh_args[1..-1]
|
|
options[:ssh_args] = ssh_args
|
|
|
|
# If the remaining arguments ARE the SSH arguments, then just
|
|
# clear it out. This happens because optparse returns what is
|
|
# after the "--" as remaining ARGV, and Vagrant can think it is
|
|
# a multi-vm name (wrong!)
|
|
argv = [] if argv == ssh_args
|
|
|
|
# Execute the actual SSH
|
|
with_target_vms(argv, :single_target => true) do |vm|
|
|
# Basic checks that are required for proper SSH
|
|
# raise Vagrant::Errors::VMNotCreatedError if !vm.created?
|
|
# raise Vagrant::Errors::VMInaccessible if !vm.state == :inaccessible
|
|
# raise Vagrant::Errors::VMNotRunningError if vm.state != :running
|
|
|
|
if options[:command]
|
|
ssh_execute(vm, options[:command])
|
|
else
|
|
opts = {
|
|
:plain_mode => options[:plain_mode],
|
|
:extra_args => options[:ssh_args]
|
|
}
|
|
|
|
vm.action(:ssh, :ssh_opts => opts)
|
|
end
|
|
end
|
|
|
|
# Success, exit status 0
|
|
0
|
|
end
|
|
|
|
protected
|
|
|
|
def ssh_execute(vm, command=nil)
|
|
exit_status = 0
|
|
|
|
@logger.debug("Executing command: #{command}")
|
|
exit_status = vm.channel.execute(command, :error_check => false) do |type, data|
|
|
# Determine the proper channel to send the output onto depending
|
|
# on the type of data we are receiving.
|
|
channel = type == :stdout ? :out : :error
|
|
|
|
# Print the SSH output as it comes in, but don't prefix it and don't
|
|
# force a new line so that the output is properly preserved
|
|
vm.ui.info(data.to_s,
|
|
:prefix => false,
|
|
:new_line => false,
|
|
:channel => channel)
|
|
end
|
|
|
|
# Exit with the exit status we got from executing the command
|
|
exit exit_status
|
|
end
|
|
|
|
def ssh_connect(vm, opts)
|
|
@logger.debug("`exec` into ssh prompt")
|
|
vm.ssh.exec(opts)
|
|
end
|
|
end
|
|
end
|
|
end
|