lib/chef/provisioning/transport/ssh.rb in chef-provisioning-0.17 vs lib/chef/provisioning/transport/ssh.rb in chef-provisioning-0.18
- old
+ new
@@ -22,11 +22,13 @@
# - options: a hash of options for the transport itself, including:
# - :prefix: a prefix to send before each command (e.g. "sudo ")
# - :ssh_pty_enable: set to false to disable pty (some instances don't
# support this, most do)
# - :ssh_gateway: the gateway to use, e.g. "jkeiser@145.14.51.45:222".
- # nil (the default) means no gateway.
+ # nil (the default) means no gateway. If the username is omitted,
+ # then the default username is used instead (i.e. the user running
+ # chef, or the username configured in .ssh/config).
# - global_config: an options hash that looks suspiciously similar to
# Chef::Config, containing at least the key :log_level.
#
# The options are used in
# Net::SSH.start(host, username, ssh_options)
@@ -278,12 +280,14 @@
options.key?(:ssh_gateway) and ! options[:ssh_gateway].nil?
end
def gateway
gw_user, gw_host = options[:ssh_gateway].split('@')
+ # If we didn't have an '@' in the above, then the value is actually
+ # the hostname, not the username.
+ gw_host, gw_user = gw_user, gw_host if gw_host.nil?
gw_host, gw_port = gw_host.split(':')
- gw_user = ssh_options[:ssh_username] unless gw_user
ssh_start_opts = { timeout:10 }.merge(ssh_options)
ssh_start_opts[:port] = gw_port || 22
Chef::Log.debug("Opening SSH gateway to #{gw_user}@#{gw_host} with options #{ssh_start_opts.dup.tap {
@@ -308,25 +312,37 @@
# Forwards a port over the connection, and returns the
def forward_port(local_port, local_host, remote_port, remote_host)
# This bit is from the documentation.
if session.forward.respond_to?(:active_remote_destinations)
- got_remote_port, remote_host = session.forward.active_remote_destinations[[local_port, local_host]]
- if !got_remote_port
+ # active_remote_destinations tells us exactly what remotes the current
+ # ssh session is *actually* tracking. If multiple people share this
+ # session and set up their own remotes, this will prevent us from
+ # overwriting them.
+
+ actual_remote_port, actual_remote_host = session.forward.active_remote_destinations[[local_port, local_host]]
+ if !actual_remote_port
Chef::Log.debug("Forwarding local server #{local_host}:#{local_port} to #{username}@#{self.host}")
- session.forward.remote(local_port, local_host, remote_port, remote_host) do |actual_remote_port|
- got_remote_port = actual_remote_port || :error
+ session.forward.remote(local_port, local_host, remote_port, remote_host) do |new_remote_port, new_remote_host|
+ actual_remote_host = new_remote_host
+ actual_remote_port = new_remote_port || :error
:no_exception # I'll take care of it myself, thanks
end
# Kick SSH until we get a response
- session.loop { !got_remote_port }
- if got_remote_port == :error
+ session.loop { !actual_remote_port }
+ if actual_remote_port == :error
return nil
end
end
- [ got_remote_port, remote_host ]
+ [ actual_remote_port, actual_remote_host ]
else
+ # If active_remote_destinations isn't on net-ssh, we stash our own list
+ # of ports *we* have forwarded on the connection, and hope that we are
+ # right.
+ # TODO let's remove this when net-ssh 2.9.2 is old enough, and
+ # bump the required net-ssh version.
+
@forwarded_ports ||= {}
remote_port, remote_host = @forwarded_ports[[local_port, local_host]]
if !remote_port
Chef::Log.debug("Forwarding local server #{local_host}:#{local_port} to #{username}@#{self.host}")
old_active_remotes = session.forward.active_remotes