ztk 1.9.1 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/ztk/ansi.rb +0 -1
- data/lib/ztk/ssh.rb +8 -2
- data/lib/ztk/ssh/command.rb +2 -0
- data/lib/ztk/ssh/core.rb +60 -6
- data/lib/ztk/ssh/download.rb +50 -25
- data/lib/ztk/ssh/private.rb +64 -24
- data/lib/ztk/ssh/upload.rb +45 -17
- data/lib/ztk/version.rb +1 -1
- data/spec/ztk/ssh_spec.rb +97 -88
- data/ztk.gemspec +2 -0
- metadata +36 -4
data/lib/ztk/ansi.rb
CHANGED
@@ -97,7 +97,6 @@ module ZTK
|
|
97
97
|
# @return [String] The colored string.
|
98
98
|
|
99
99
|
# Defines a RegEx for stripping ANSI codes from strings
|
100
|
-
#ANSI_REGEX = /\e\[(?:(?:[349]|10)[0-7]|[0-9]|[34]8;5;\d{1,3})?m/
|
101
100
|
ANSI_REGEX = /\e\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]/
|
102
101
|
|
103
102
|
# Build ANSI Methods
|
data/lib/ztk/ssh.rb
CHANGED
@@ -61,9 +61,12 @@ module ZTK
|
|
61
61
|
# @author Zachary Patten <zachary AT jovelabs DOT com>
|
62
62
|
class SSH < ZTK::Base
|
63
63
|
require 'ostruct'
|
64
|
+
require 'tempfile'
|
64
65
|
require 'net/ssh'
|
66
|
+
require 'net/ssh/gateway'
|
65
67
|
require 'net/ssh/proxy/command'
|
66
68
|
require 'net/sftp'
|
69
|
+
require 'net/scp'
|
67
70
|
|
68
71
|
# Exit Signal Mappings
|
69
72
|
EXIT_SIGNALS = {
|
@@ -121,7 +124,8 @@ module ZTK
|
|
121
124
|
# @option configuration [String] :host_name Server hostname to connect to.
|
122
125
|
# @option configuration [String] :user Username to use for authentication.
|
123
126
|
# @option configuration [String, Array<String>] :keys A single or series of
|
124
|
-
# identity files to use for authentication.
|
127
|
+
# identity files to use for authentication. You can also supply keys as
|
128
|
+
# String blobs which will be rendered to temporary files automatically.
|
125
129
|
# @option configuration [String] :password Password to use for authentication.
|
126
130
|
# @option configuration [Integer] :timeout (60) SSH connection timeout in
|
127
131
|
# seconds to use.
|
@@ -160,7 +164,9 @@ module ZTK
|
|
160
164
|
:ignore_exit_status => false,
|
161
165
|
:request_pty => true,
|
162
166
|
:exit_code => 0,
|
163
|
-
:silence => false
|
167
|
+
:silence => false,
|
168
|
+
:keys => Array.new,
|
169
|
+
:proxy_keys => Array.new
|
164
170
|
}.merge(configuration))
|
165
171
|
|
166
172
|
config.ui.logger.debug { "config=#{config.send(:table).inspect}" }
|
data/lib/ztk/ssh/command.rb
CHANGED
@@ -6,6 +6,7 @@ module ZTK
|
|
6
6
|
|
7
7
|
# Builds our SSH console command.
|
8
8
|
def console_command
|
9
|
+
process_keys
|
9
10
|
verbosity = ((ENV['LOG_LEVEL'] == "DEBUG") ? '-vv' : '-q')
|
10
11
|
|
11
12
|
command = Array.new
|
@@ -34,6 +35,7 @@ module ZTK
|
|
34
35
|
!config.proxy_user and log_and_raise(SSHError, "You must specify an proxy user in order to SSH proxy.")
|
35
36
|
!config.proxy_host_name and log_and_raise(SSHError, "You must specify an proxy host_name in order to SSH proxy.")
|
36
37
|
|
38
|
+
process_keys
|
37
39
|
verbosity = ((ENV['LOG_LEVEL'] == "DEBUG") ? '-vv' : '-q')
|
38
40
|
|
39
41
|
command = Array.new
|
data/lib/ztk/ssh/core.rb
CHANGED
@@ -8,7 +8,11 @@ module ZTK
|
|
8
8
|
#
|
9
9
|
# Primarily used internally.
|
10
10
|
def ssh
|
11
|
-
|
11
|
+
if do_proxy?
|
12
|
+
@ssh ||= self.gateway.ssh(config.host_name, config.user, ssh_options)
|
13
|
+
else
|
14
|
+
@ssh ||= Net::SSH.start(config.host_name, config.user, ssh_options)
|
15
|
+
end
|
12
16
|
@ssh
|
13
17
|
end
|
14
18
|
|
@@ -20,10 +24,30 @@ module ZTK
|
|
20
24
|
@sftp
|
21
25
|
end
|
22
26
|
|
23
|
-
#
|
24
|
-
|
25
|
-
|
27
|
+
# Starts an SCP session. Can also be used to get the Net::SCP object.
|
28
|
+
#
|
29
|
+
# Primarily used internally.
|
30
|
+
def scp
|
31
|
+
@scp ||= self.ssh.scp
|
32
|
+
@scp
|
33
|
+
end
|
26
34
|
|
35
|
+
# Starts an SSH gateway session. Can also be used to get the
|
36
|
+
# Net::SSH::Gateway object.
|
37
|
+
#
|
38
|
+
# Primarily used internally.
|
39
|
+
def gateway
|
40
|
+
@gateway ||= Net::SSH::Gateway.new(config.proxy_host_name, config.proxy_user, gateway_options)
|
41
|
+
@gateway
|
42
|
+
end
|
43
|
+
|
44
|
+
# Should we run a proxy?
|
45
|
+
def do_proxy?
|
46
|
+
((!config.proxy_host_name.nil? && !config.proxy_host_name.empty?) && (!config.proxy_user.nil? && !config.proxy_user.empty?))
|
47
|
+
end
|
48
|
+
|
49
|
+
# Attempts to close the SSH session if it is valid.
|
50
|
+
def close_ssh
|
27
51
|
if (!@ssh.nil? && !@ssh.closed?)
|
28
52
|
config.ui.logger.debug { "SSH object is valid and not closed" }
|
29
53
|
|
@@ -39,11 +63,41 @@ module ZTK
|
|
39
63
|
else
|
40
64
|
config.ui.logger.debug { "SSH object is NIL!" }
|
41
65
|
end
|
66
|
+
end
|
42
67
|
|
43
|
-
|
44
|
-
|
68
|
+
# Attempts to close the gateway session if it is valid.
|
69
|
+
def close_gateway
|
70
|
+
if (!@gateway.nil? && !@gateway.closed?)
|
71
|
+
config.ui.logger.debug { "gateway object is valid and not shutdown" }
|
72
|
+
|
73
|
+
begin
|
74
|
+
config.ui.logger.debug { "attempting to shutdown" }
|
75
|
+
@gateway.shutdown!
|
76
|
+
config.ui.logger.debug { "shutdown" }
|
77
|
+
|
78
|
+
rescue Exception => e
|
79
|
+
config.ui.logger.fatal { "EXCEPTION: #{e.inspect}" }
|
80
|
+
end
|
81
|
+
|
82
|
+
else
|
83
|
+
config.ui.logger.debug { "gateway object is NIL!" }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Close our session gracefully.
|
88
|
+
def close
|
89
|
+
config.ui.logger.debug { "close" }
|
90
|
+
|
91
|
+
close_ssh
|
92
|
+
close_gateway
|
45
93
|
|
46
94
|
true
|
95
|
+
|
96
|
+
ensure
|
97
|
+
@ssh = nil
|
98
|
+
@gateway = nil
|
99
|
+
@sftp = nil
|
100
|
+
@scp = nil
|
47
101
|
end
|
48
102
|
|
49
103
|
# The on_retry method we'll use with the RescueRetry class.
|
data/lib/ztk/ssh/download.rb
CHANGED
@@ -6,14 +6,6 @@ module ZTK
|
|
6
6
|
|
7
7
|
# Downloads a remote file to the local host.
|
8
8
|
#
|
9
|
-
# @param [String] remote The remote file/path you with to download from.
|
10
|
-
# @param [String] local The local file/path you wish to download to.
|
11
|
-
# @param [Hash] options An optional hash of options.
|
12
|
-
# @option options [Boolean] :recursive Whether or not to recursively
|
13
|
-
# download files and directories. By default this looks at the local
|
14
|
-
# target and if it is a directory this is set to *true* otherwise it
|
15
|
-
# will default to *false*.
|
16
|
-
#
|
17
9
|
# @example Download a file:
|
18
10
|
# $logger = ZTK::Logger.new(STDOUT)
|
19
11
|
# ssh = ZTK::SSH.new
|
@@ -24,8 +16,24 @@ module ZTK
|
|
24
16
|
# local = File.expand_path(File.join(ZTK::Locator.root, "tmp", "id_rsa.pub"))
|
25
17
|
# remote = File.expand_path(File.join(ENV['HOME'], ".ssh", "id_rsa.pub"))
|
26
18
|
# ssh.download(remote, local)
|
19
|
+
#
|
20
|
+
# @param [String] remote The remote file/path you with to download from.
|
21
|
+
# @param [String] local The local file/path you wish to download to.
|
22
|
+
# @param [Hash] options An optional hash of options.
|
23
|
+
# @option options [Boolean] :recursive (false) Whether or not to
|
24
|
+
# recursively download files and directories. By default this looks at
|
25
|
+
# the local target and if it is a directory this is set to *true*
|
26
|
+
# otherwise it will default to *false*.
|
27
|
+
# @option options [Boolean] :use_scp (false) If set to true, the file will
|
28
|
+
# be transfered using SCP instead of SFTP. The default behaviour is to
|
29
|
+
# use SFTP. *WARNING: Recursive downloads are handled in differing
|
30
|
+
# manners between SCP and SFTP!*
|
31
|
+
# @return [Boolean] True if successful.
|
27
32
|
def download(remote, local, options={})
|
28
|
-
options = {
|
33
|
+
options = {
|
34
|
+
:recursive => ::File.directory?(local),
|
35
|
+
:use_scp => false
|
36
|
+
}.merge(options)
|
29
37
|
options = OpenStruct.new(config.send(:table).merge(options))
|
30
38
|
|
31
39
|
options.ui.logger.debug { "config=#{config.send(:table).inspect}" }
|
@@ -33,24 +41,41 @@ module ZTK
|
|
33
41
|
options.ui.logger.info { "download(#{remote.inspect}, #{local.inspect})" }
|
34
42
|
|
35
43
|
ZTK::RescueRetry.try(:ui => config.ui, :tries => ZTK::SSH::RESCUE_RETRY_ATTEMPTS, :on_retry => method(:on_retry)) do
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
44
|
+
if (options.use_scp == false)
|
45
|
+
sftp.download!(remote.to_s, local.to_s, options.send(:table)) do |event, downloader, *args|
|
46
|
+
case event
|
47
|
+
when :open
|
48
|
+
options.ui.logger.debug { "download(#{args[0].remote} -> #{args[0].local})" }
|
49
|
+
options.on_progress.nil? or options.on_progress.call(:open, args)
|
50
|
+
when :close
|
51
|
+
options.ui.logger.debug { "close(#{args[0].local})" }
|
52
|
+
options.on_progress.nil? or options.on_progress.call(:close, args)
|
53
|
+
when :mkdir
|
54
|
+
options.ui.logger.debug { "mkdir(#{args[0]})" }
|
55
|
+
options.on_progress.nil? or options.on_progress.call(:mkdir, args)
|
56
|
+
when :get
|
57
|
+
options.ui.logger.debug { "get(#{args[0].remote}, size #{args[2].size} bytes, offset #{args[1]})" }
|
58
|
+
options.on_progress.nil? or options.on_progress.call(:get, args)
|
59
|
+
when :finish
|
60
|
+
options.ui.logger.debug { "finish" }
|
61
|
+
options.on_progress.nil? or options.on_progress.call(:finish, args)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
else
|
65
|
+
opened = false
|
66
|
+
args = []
|
67
|
+
|
68
|
+
scp.download!(remote.to_s, local.to_s, options.send(:table)) do |ch, name, sent, total|
|
69
|
+
args = [ OpenStruct.new(:size => total, :local => name, :remote => name), sent, '' ]
|
70
|
+
|
71
|
+
opened or (options.on_progress.nil? or options.on_progress.call(:open, args) and (opened = true))
|
72
|
+
|
73
|
+
options.ui.logger.debug { "get(#{args[0].remote}, sent #{args[1]}, total #{args[0].size})" }
|
49
74
|
options.on_progress.nil? or options.on_progress.call(:get, args)
|
50
|
-
when :finish
|
51
|
-
options.ui.logger.debug { "finish" }
|
52
|
-
options.on_progress.nil? or options.on_progress.call(:finish, args)
|
53
75
|
end
|
76
|
+
|
77
|
+
options.ui.logger.debug { "finish" }
|
78
|
+
options.on_progress.nil? or options.on_progress.call(:finish, args)
|
54
79
|
end
|
55
80
|
end
|
56
81
|
|
data/lib/ztk/ssh/private.rb
CHANGED
@@ -4,37 +4,77 @@ module ZTK
|
|
4
4
|
# SSH Private Functionality
|
5
5
|
module Private
|
6
6
|
|
7
|
+
# Builds our core options
|
8
|
+
def base_options
|
9
|
+
options = Hash.new
|
10
|
+
|
11
|
+
config.encryption.nil? or options.merge!(:encryption => config.encryption)
|
12
|
+
config.compression.nil? or options.merge!(:compression => config.compression)
|
13
|
+
config.compression_level.nil? or options.merge!(:compression_level => config.compression_level)
|
14
|
+
config.timeout.nil? or options.merge!(:timeout => config.timeout)
|
15
|
+
config.forward_agent.nil? or options.merge!(:forward_agent => config.forward_agent)
|
16
|
+
config.global_known_hosts_file.nil? or options.merge!(:global_known_hosts_file => config.global_known_hosts_file)
|
17
|
+
config.auth_methods.nil? or options.merge!(:auth_methods => config.auth_methods)
|
18
|
+
config.host_key.nil? or options.merge!(:host_key => config.host_key)
|
19
|
+
config.host_key_alias.nil? or options.merge!(:host_key_alias => config.host_key_alias)
|
20
|
+
config.keys_only.nil? or options.merge!(:keys_only => config.keys_only)
|
21
|
+
config.hmac.nil? or options.merge!(:hmac => config.hmac)
|
22
|
+
config.rekey_limit.nil? or options.merge!(:rekey_limit => config.rekey_limit)
|
23
|
+
config.user_known_hosts_file.nil? or options.merge!(:user_known_hosts_file => config.user_known_hosts_file)
|
24
|
+
|
25
|
+
options
|
26
|
+
end
|
27
|
+
|
7
28
|
# Builds our SSH options hash.
|
8
29
|
def ssh_options
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
options.merge!(:
|
13
|
-
options.merge!(:
|
14
|
-
options.merge!(:
|
15
|
-
options.merge!(:timeout => config.timeout) if config.timeout
|
16
|
-
options.merge!(:forward_agent => config.forward_agent) if config.forward_agent
|
17
|
-
options.merge!(:global_known_hosts_file => config.global_known_hosts_file) if config.global_known_hosts_file
|
18
|
-
options.merge!(:auth_methods => config.auth_methods) if config.auth_methods
|
19
|
-
options.merge!(:host_key => config.host_key) if config.host_key
|
20
|
-
options.merge!(:host_key_alias => config.host_key_alias) if config.host_key_alias
|
21
|
-
options.merge!(:host_name => config.host_name) if config.host_name
|
22
|
-
options.merge!(:keys => config.keys) if config.keys
|
23
|
-
options.merge!(:keys_only => config.keys_only) if config.keys_only
|
24
|
-
options.merge!(:hmac => config.hmac) if config.hmac
|
25
|
-
options.merge!(:port => config.port) if config.port
|
26
|
-
options.merge!(:proxy => Net::SSH::Proxy::Command.new(proxy_command)) if config.proxy_host_name
|
27
|
-
options.merge!(:rekey_limit => config.rekey_limit) if config.rekey_limit
|
28
|
-
options.merge!(:user => config.user) if config.user
|
29
|
-
options.merge!(:user_known_hosts_file => config.user_known_hosts_file) if config.user_known_hosts_file
|
30
|
-
|
31
|
-
# This is not plainly documented on the Net::SSH config class.
|
32
|
-
options.merge!(:password => config.password) if config.password
|
30
|
+
process_keys
|
31
|
+
options = base_options
|
32
|
+
|
33
|
+
config.port.nil? or options.merge!(:port => config.port)
|
34
|
+
config.password.nil? or options.merge!(:password => config.password)
|
35
|
+
config.keys.nil? or options.merge!(:keys => config.keys)
|
33
36
|
|
34
37
|
config.ui.logger.debug { "ssh_options(#{options.inspect})" }
|
35
38
|
options
|
36
39
|
end
|
37
40
|
|
41
|
+
# Builds our SSH gateway options hash.
|
42
|
+
def gateway_options
|
43
|
+
process_keys
|
44
|
+
options = base_options
|
45
|
+
|
46
|
+
config.proxy_port.nil? or options.merge!(:port => config.proxy_port)
|
47
|
+
config.proxy_password.nil? or options.merge!(:password => config.proxy_password)
|
48
|
+
config.proxy_keys.nil? or options.merge!(:keys => config.proxy_keys)
|
49
|
+
|
50
|
+
config.ui.logger.debug { "gateway_options(#{options.inspect})" }
|
51
|
+
options
|
52
|
+
end
|
53
|
+
|
54
|
+
# Iterate the keys and proxy_keys, converting them as needed.
|
55
|
+
def process_keys
|
56
|
+
config.keys = config.keys.collect do |key|
|
57
|
+
process_key(key)
|
58
|
+
end
|
59
|
+
|
60
|
+
config.proxy_keys = config.proxy_keys.collect do |proxy_key|
|
61
|
+
process_key(proxy_key)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Process a individual key, rendering it to a temporary file if needed.
|
66
|
+
def process_key(key)
|
67
|
+
if ::File.exists?(key)
|
68
|
+
key
|
69
|
+
else
|
70
|
+
tempfile = ::Tempfile.new('key')
|
71
|
+
tempfile.write(key)
|
72
|
+
tempfile.flush
|
73
|
+
|
74
|
+
tempfile.path
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
38
78
|
# Builds a human readable tag about our connection. Used for internal
|
39
79
|
# logging purposes.
|
40
80
|
def tag
|
data/lib/ztk/ssh/upload.rb
CHANGED
@@ -19,8 +19,19 @@ module ZTK
|
|
19
19
|
#
|
20
20
|
# @param [String] local The local file/path you wish to upload from.
|
21
21
|
# @param [String] remote The remote file/path you with to upload to.
|
22
|
+
# @param [Hash] options An optional hash of options.
|
23
|
+
# @option options [Boolean] :recursive (false) Whether or not to
|
24
|
+
# recursively download files and directories.
|
25
|
+
# @option options [Boolean] :use_scp (false) If set to true, the file will
|
26
|
+
# be transfered using SCP instead of SFTP. The default behaviour is to
|
27
|
+
# use SFTP. *WARNING: Recursive downloads are handled in differing
|
28
|
+
# manners between SCP and SFTP!*
|
22
29
|
# @return [Boolean] True if successful.
|
23
30
|
def upload(local, remote, options={})
|
31
|
+
options = {
|
32
|
+
:recursive => false,
|
33
|
+
:use_scp => false
|
34
|
+
}.merge(options)
|
24
35
|
options = OpenStruct.new(config.send(:table).merge(options))
|
25
36
|
|
26
37
|
options.ui.logger.debug { "config=#{config.send(:table).inspect}" }
|
@@ -28,24 +39,41 @@ module ZTK
|
|
28
39
|
config.ui.logger.info { "upload(#{local.inspect}, #{remote.inspect})" }
|
29
40
|
|
30
41
|
ZTK::RescueRetry.try(:ui => config.ui, :tries => ZTK::SSH::RESCUE_RETRY_ATTEMPTS, :on_retry => method(:on_retry)) do
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
42
|
+
if (options.use_scp == false)
|
43
|
+
sftp.upload!(local.to_s, remote.to_s) do |event, uploader, *args|
|
44
|
+
case event
|
45
|
+
when :open
|
46
|
+
options.ui.logger.debug { "upload(#{args[0].local} -> #{args[0].remote})" }
|
47
|
+
options.on_progress.nil? or options.on_progress.call(:open, args)
|
48
|
+
when :close
|
49
|
+
options.ui.logger.debug { "close(#{args[0].remote})" }
|
50
|
+
options.on_progress.nil? or options.on_progress.call(:close, args)
|
51
|
+
when :mkdir
|
52
|
+
options.ui.logger.debug { "mkdir(#{args[0]})" }
|
53
|
+
options.on_progress.nil? or options.on_progress.call(:mkdir, args)
|
54
|
+
when :put
|
55
|
+
options.ui.logger.debug { "put(#{args[0].remote}, size #{args[2].size} bytes, offset #{args[1]})" }
|
56
|
+
options.on_progress.nil? or options.on_progress.call(:put, args)
|
57
|
+
when :finish
|
58
|
+
options.ui.logger.debug { "finish" }
|
59
|
+
options.on_progress.nil? or options.on_progress.call(:finish, args)
|
60
|
+
end
|
48
61
|
end
|
62
|
+
else
|
63
|
+
opened = false
|
64
|
+
args = []
|
65
|
+
|
66
|
+
scp.upload!(local.to_s, remote.to_s, options.send(:table)) do |ch, name, sent, total|
|
67
|
+
args = [ OpenStruct.new(:size => total, :local => name, :remote => name), sent, '' ]
|
68
|
+
|
69
|
+
opened or (options.on_progress.nil? or options.on_progress.call(:open, args) and (opened = true))
|
70
|
+
|
71
|
+
options.ui.logger.debug { "put(#{args[0].remote}, sent #{args[1]}, total #{args[0].size})" }
|
72
|
+
options.on_progress.nil? or options.on_progress.call(:get, args)
|
73
|
+
end
|
74
|
+
|
75
|
+
options.ui.logger.debug { "finish" }
|
76
|
+
options.on_progress.nil? or options.on_progress.call(:finish, args)
|
49
77
|
end
|
50
78
|
end
|
51
79
|
|
data/lib/ztk/version.rb
CHANGED
data/spec/ztk/ssh_spec.rb
CHANGED
@@ -231,68 +231,73 @@ describe ZTK::SSH do
|
|
231
231
|
|
232
232
|
describe "upload" do
|
233
233
|
|
234
|
-
|
235
|
-
|
236
|
-
config
|
234
|
+
[true, false].each do |use_scp|
|
235
|
+
it "should be able to upload a file to 127.0.0.1 as the current user using #{use_scp ? 'scp' : 'sftp'} (your key must be in ssh-agent)" do
|
236
|
+
subject.config do |config|
|
237
|
+
config.ui = @ui
|
237
238
|
|
238
|
-
|
239
|
-
|
240
|
-
|
239
|
+
config.user = ENV["USER"]
|
240
|
+
config.host_name = "127.0.0.1"
|
241
|
+
end
|
241
242
|
|
242
|
-
|
243
|
+
data = "Hello World @ #{Time.now.utc}"
|
243
244
|
|
244
|
-
|
245
|
-
|
245
|
+
remote_file = File.join(ZTK::Locator.root, "tmp", "ssh-upload-remote")
|
246
|
+
File.exists?(remote_file) && File.delete(remote_file)
|
246
247
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
248
|
+
local_file = File.join(ZTK::Locator.root, "tmp", "ssh-upload-local")
|
249
|
+
if RUBY_VERSION < "1.9.3"
|
250
|
+
File.open(local_file, 'w') do |file|
|
251
|
+
file.puts(data)
|
252
|
+
end
|
253
|
+
else
|
254
|
+
IO.write(local_file, data)
|
251
255
|
end
|
252
|
-
else
|
253
|
-
IO.write(local_file, data)
|
254
|
-
end
|
255
256
|
|
256
|
-
|
257
|
-
|
258
|
-
|
257
|
+
File.exists?(remote_file).should == false
|
258
|
+
subject.upload(local_file, remote_file)
|
259
|
+
File.exists?(remote_file).should == true
|
259
260
|
|
260
|
-
|
261
|
-
|
261
|
+
File.exists?(remote_file) && File.delete(remote_file)
|
262
|
+
File.exists?(local_file) && File.delete(local_file)
|
263
|
+
end
|
262
264
|
end
|
263
265
|
|
264
266
|
end
|
265
267
|
|
266
268
|
describe "download" do
|
267
269
|
|
268
|
-
|
269
|
-
|
270
|
-
config
|
270
|
+
[true, false].each do |use_scp|
|
271
|
+
it "should be able to download a file from 127.0.0.1 as the current user using #{use_scp ? 'scp' : 'sftp'} (your key must be in ssh-agent)" do
|
272
|
+
subject.config do |config|
|
273
|
+
config.ui = @ui
|
271
274
|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
+
config.user = ENV["USER"]
|
276
|
+
config.host_name = "127.0.0.1"
|
277
|
+
config.use_scp = use_scp
|
278
|
+
end
|
275
279
|
|
276
|
-
|
280
|
+
data = "Hello World @ #{Time.now.utc}"
|
277
281
|
|
278
|
-
|
279
|
-
|
282
|
+
local_file = File.join(ZTK::Locator.root, "tmp", "ssh-download-local")
|
283
|
+
File.exists?(local_file) && File.delete(local_file)
|
280
284
|
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
+
remote_file = File.join(ZTK::Locator.root, "tmp", "ssh-download-remote")
|
286
|
+
if RUBY_VERSION < "1.9.3"
|
287
|
+
File.open(remote_file, 'w') do |file|
|
288
|
+
file.puts(data)
|
289
|
+
end
|
290
|
+
else
|
291
|
+
IO.write(remote_file, data)
|
285
292
|
end
|
286
|
-
else
|
287
|
-
IO.write(remote_file, data)
|
288
|
-
end
|
289
293
|
|
290
|
-
|
291
|
-
|
292
|
-
|
294
|
+
File.exists?(local_file).should == false
|
295
|
+
subject.download(remote_file, local_file)
|
296
|
+
File.exists?(local_file).should == true
|
293
297
|
|
294
|
-
|
295
|
-
|
298
|
+
File.exists?(local_file) && File.delete(local_file)
|
299
|
+
File.exists?(remote_file) && File.delete(remote_file)
|
300
|
+
end
|
296
301
|
end
|
297
302
|
|
298
303
|
end
|
@@ -511,72 +516,76 @@ describe ZTK::SSH do
|
|
511
516
|
|
512
517
|
describe "upload" do
|
513
518
|
|
514
|
-
|
515
|
-
|
516
|
-
config
|
519
|
+
[true, false].each do |use_scp|
|
520
|
+
it "should be able to upload a file to 127.0.0.1 as the current user #{use_scp ? 'scp' : 'sftp'} (your key must be in ssh-agent)" do
|
521
|
+
subject.config do |config|
|
522
|
+
config.ui = @ui
|
517
523
|
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
524
|
+
config.user = ENV["USER"]
|
525
|
+
config.host_name = "127.0.0.1"
|
526
|
+
config.proxy_user = ENV["USER"]
|
527
|
+
config.proxy_host_name = "127.0.0.1"
|
528
|
+
end
|
523
529
|
|
524
|
-
|
530
|
+
data = "Hello World @ #{Time.now.utc}"
|
525
531
|
|
526
|
-
|
527
|
-
|
532
|
+
remote_file = File.join(ZTK::Locator.root, "tmp", "ssh-upload-remote")
|
533
|
+
File.exists?(remote_file) && File.delete(remote_file)
|
528
534
|
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
535
|
+
local_file = File.join(ZTK::Locator.root, "tmp", "ssh-upload-local")
|
536
|
+
if RUBY_VERSION < "1.9.3"
|
537
|
+
File.open(local_file, 'w') do |file|
|
538
|
+
file.puts(data)
|
539
|
+
end
|
540
|
+
else
|
541
|
+
IO.write(local_file, data)
|
533
542
|
end
|
534
|
-
else
|
535
|
-
IO.write(local_file, data)
|
536
|
-
end
|
537
543
|
|
538
|
-
|
539
|
-
|
540
|
-
|
544
|
+
File.exists?(remote_file).should == false
|
545
|
+
subject.upload(local_file, remote_file)
|
546
|
+
File.exists?(remote_file).should == true
|
541
547
|
|
542
|
-
|
543
|
-
|
548
|
+
File.exists?(remote_file) && File.delete(remote_file)
|
549
|
+
File.exists?(local_file) && File.delete(local_file)
|
550
|
+
end
|
544
551
|
end
|
545
552
|
|
546
553
|
end
|
547
554
|
|
548
555
|
describe "download" do
|
549
556
|
|
550
|
-
|
551
|
-
|
552
|
-
config
|
557
|
+
[true, false].each do |use_scp|
|
558
|
+
it "should be able to download a file from 127.0.0.1 as the current user using #{use_scp ? 'scp' : 'sftp'} (your key must be in ssh-agent)" do
|
559
|
+
subject.config do |config|
|
560
|
+
config.ui = @ui
|
553
561
|
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
562
|
+
config.user = ENV["USER"]
|
563
|
+
config.host_name = "127.0.0.1"
|
564
|
+
config.proxy_user = ENV["USER"]
|
565
|
+
config.proxy_host_name = "127.0.0.1"
|
566
|
+
end
|
559
567
|
|
560
|
-
|
568
|
+
data = "Hello World @ #{Time.now.utc}"
|
561
569
|
|
562
|
-
|
563
|
-
|
570
|
+
local_file = File.join(ZTK::Locator.root, "tmp", "ssh-download-local")
|
571
|
+
File.exists?(local_file) && File.delete(local_file)
|
564
572
|
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
573
|
+
remote_file = File.join(ZTK::Locator.root, "tmp", "ssh-download-remote")
|
574
|
+
if RUBY_VERSION < "1.9.3"
|
575
|
+
File.open(remote_file, 'w') do |file|
|
576
|
+
file.puts(data)
|
577
|
+
end
|
578
|
+
else
|
579
|
+
IO.write(remote_file, data)
|
569
580
|
end
|
570
|
-
else
|
571
|
-
IO.write(remote_file, data)
|
572
|
-
end
|
573
581
|
|
574
|
-
|
575
|
-
|
576
|
-
|
582
|
+
File.exists?(local_file).should == false
|
583
|
+
subject.download(remote_file, local_file)
|
584
|
+
File.exists?(local_file).should == true
|
577
585
|
|
578
|
-
|
579
|
-
|
586
|
+
File.exists?(local_file) && File.delete(local_file)
|
587
|
+
File.exists?(remote_file) && File.delete(remote_file)
|
588
|
+
end
|
580
589
|
end
|
581
590
|
|
582
591
|
end
|
data/ztk.gemspec
CHANGED
@@ -39,7 +39,9 @@ Gem::Specification.new do |spec|
|
|
39
39
|
spec.add_dependency("activesupport")
|
40
40
|
spec.add_dependency("erubis")
|
41
41
|
spec.add_dependency("net-ssh")
|
42
|
+
spec.add_dependency("net-ssh-gateway")
|
42
43
|
spec.add_dependency("net-sftp")
|
44
|
+
spec.add_dependency("net-scp")
|
43
45
|
|
44
46
|
spec.add_development_dependency("pry")
|
45
47
|
spec.add_development_dependency("rake")
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ztk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.10.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-12-
|
12
|
+
date: 2013-12-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -59,6 +59,22 @@ dependencies:
|
|
59
59
|
- - ! '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: net-ssh-gateway
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
62
78
|
- !ruby/object:Gem::Dependency
|
63
79
|
name: net-sftp
|
64
80
|
requirement: !ruby/object:Gem::Requirement
|
@@ -75,6 +91,22 @@ dependencies:
|
|
75
91
|
- - ! '>='
|
76
92
|
- !ruby/object:Gem::Version
|
77
93
|
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: net-scp
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :runtime
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
78
110
|
- !ruby/object:Gem::Dependency
|
79
111
|
name: pry
|
80
112
|
requirement: !ruby/object:Gem::Requirement
|
@@ -275,7 +307,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
275
307
|
version: '0'
|
276
308
|
segments:
|
277
309
|
- 0
|
278
|
-
hash: -
|
310
|
+
hash: -3144121438206062484
|
279
311
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
280
312
|
none: false
|
281
313
|
requirements:
|
@@ -284,7 +316,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
284
316
|
version: '0'
|
285
317
|
segments:
|
286
318
|
- 0
|
287
|
-
hash: -
|
319
|
+
hash: -3144121438206062484
|
288
320
|
requirements: []
|
289
321
|
rubyforge_project:
|
290
322
|
rubygems_version: 1.8.25
|