lib/kitchen/transport/ssh.rb in test-kitchen-1.19.2 vs lib/kitchen/transport/ssh.rb in test-kitchen-1.20.0
- old
+ new
@@ -16,12 +16,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
require "kitchen"
+require "fileutils"
require "net/ssh"
require "net/ssh/gateway"
+require "net/ssh/proxy/http"
require "net/scp"
require "timeout"
require "benchmark"
module Kitchen
@@ -52,10 +54,15 @@
default_config :max_wait_until_ready, 600
default_config :ssh_gateway, nil
default_config :ssh_gateway_username, nil
+ default_config :ssh_http_proxy, nil
+ default_config :ssh_http_proxy_port, nil
+ default_config :ssh_http_proxy_user, nil
+ default_config :ssh_http_proxy_password, nil
+
default_config :ssh_key, nil
expand_path_for :ssh_key
# compression disabled by default for speed
default_config :compression, false
@@ -179,10 +186,34 @@
logger.debug("TIMING: scp async upload (Kitchen::Transport::Ssh) took #{delta}")
rescue Net::SSH::Exception => ex
raise SshFailed, "SCP upload failed (#{ex.message})"
end
+ # (see Base::Connection#download)
+ def download(remotes, local)
+ # ensure the parent dir of the local target exists
+ FileUtils.mkdir_p(File.dirname(local))
+
+ Array(remotes).each do |file|
+ begin
+ logger.debug("Attempting to download '#{file}' as file")
+ session.scp.download!(file, local)
+ rescue Net::SCP::Error
+ begin
+ logger.debug("Attempting to download '#{file}' as directory")
+ session.scp.download!(file, local, recursive: true)
+ rescue Net::SCP::Error
+ logger.warn(
+ "SCP download failed for file or directory '#{file}', perhaps it does not exist?"
+ )
+ end
+ end
+ end
+ rescue Net::SSH::Exception => ex
+ raise SshFailed, "SCP download failed (#{ex.message})"
+ end
+
# (see Base::Connection#wait_until_ready)
def wait_until_ready
delay = 3
session(
retries: max_wait_until_ready / delay,
@@ -244,10 +275,30 @@
# @return [String] The username to use when using an ssh gateway
# @api private
attr_reader :ssh_gateway_username
+ # @return [String] The kitchen ssh proxy to use when connecting to the
+ # remote SSH host via http proxy
+ # @api private
+ attr_reader :ssh_http_proxy
+
+ # @return [Integer] The port to use when using an kitchen ssh proxy
+ # remote SSH host via http proxy
+ # @api private
+ attr_reader :ssh_http_proxy_port
+
+ # @return [String] The username to use when using an kitchen ssh proxy
+ # remote SSH host via http proxy
+ # @api private
+ attr_reader :ssh_http_proxy_user
+
+ # @return [String] The password to use when using an kitchen ssh proxy
+ # remote SSH host via http proxy
+ # @api private
+ attr_reader :ssh_http_proxy_password
+
# Establish an SSH session on the remote host using a gateway host.
#
# @param opts [Hash] retry options
# @option opts [Integer] :retries the number of times to retry before
# failing
@@ -344,19 +395,23 @@
end
# (see Base::Connection#init_options)
def init_options(options)
super
- @username = @options.delete(:username)
- @hostname = @options.delete(:hostname)
- @port = @options[:port] # don't delete from options
- @connection_retries = @options.delete(:connection_retries)
- @connection_retry_sleep = @options.delete(:connection_retry_sleep)
- @max_ssh_sessions = @options.delete(:max_ssh_sessions)
- @max_wait_until_ready = @options.delete(:max_wait_until_ready)
- @ssh_gateway = @options.delete(:ssh_gateway)
- @ssh_gateway_username = @options.delete(:ssh_gateway_username)
+ @username = @options.delete(:username)
+ @hostname = @options.delete(:hostname)
+ @port = @options[:port] # don't delete from options
+ @connection_retries = @options.delete(:connection_retries)
+ @connection_retry_sleep = @options.delete(:connection_retry_sleep)
+ @max_ssh_sessions = @options.delete(:max_ssh_sessions)
+ @max_wait_until_ready = @options.delete(:max_wait_until_ready)
+ @ssh_gateway = @options.delete(:ssh_gateway)
+ @ssh_gateway_username = @options.delete(:ssh_gateway_username)
+ @ssh_http_proxy = @options.delete(:ssh_http_proxy)
+ @ssh_http_proxy_user = @options.delete(:ssh_http_proxy_user)
+ @ssh_http_proxy_password = @options.delete(:ssh_http_proxy_password)
+ @ssh_http_proxy_port = @options.delete(:ssh_http_proxy_port)
end
# Returns a connection session, or establishes one when invoked the
# first time.
#
@@ -417,9 +472,16 @@
if data[:ssh_key] && !data[:password]
opts[:keys_only] = true
opts[:keys] = Array(data[:ssh_key])
opts[:auth_methods] = ["publickey"]
+ end
+
+ if data[:ssh_http_proxy]
+ options_http_proxy = {}
+ options_http_proxy[:user] = data[:ssh_http_proxy_user]
+ options_http_proxy[:password] = data[:ssh_http_proxy_password]
+ opts[:proxy] = Net::SSH::Proxy::HTTP.new(data[:ssh_http_proxy], data[:ssh_http_proxy_port], options_http_proxy)
end
if data[:ssh_key_only]
opts[:auth_methods] = ["publickey"]
end