summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml17
-rw-r--r--CHANGES.txt5
-rw-r--r--README.rdoc2
-rw-r--r--Rakefile10
-rw-r--r--gem-public_cert.pem36
-rw-r--r--lib/net/ssh/multi/pending_connection.rb22
-rw-r--r--lib/net/ssh/multi/server.rb2
-rw-r--r--lib/net/ssh/multi/session.rb11
-rw-r--r--lib/net/ssh/multi/session_actions.rb4
-rw-r--r--lib/net/ssh/multi/version.rb10
-rw-r--r--net-ssh-multi.gemspec16
-rw-r--r--test/channel_test.rb2
-rw-r--r--test/session_actions_test.rb2
-rw-r--r--test/session_test.rb21
14 files changed, 124 insertions, 36 deletions
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..b520c8f
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,17 @@
+language: ruby
+sudo: false
+rvm:
+ - 2.0.0
+ - 2.1.0
+ - 2.2.0
+ - 2.3.0
+ - jruby-head
+ - rbx-2
+
+install: gem install test-unit mocha net-ssh net-ssh-gateway
+
+script: rake test
+
+matrix:
+ allow_failures:
+ - rvm: jruby-head
diff --git a/CHANGES.txt b/CHANGES.txt
index 48d94ab..92be5cd 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,8 @@
+=== 1.3.0.rc1 / 12 Mar 2016
+
+* Make sure we wait no more than keeepalive in select [Eugene Kenny]
+* Forward action [Yukihiko SAWANOBORI]
+* Net-ssh 3.0 compatibility [Balasankar C]
=== 1.2.1 / 11 Apr 2015
diff --git a/README.rdoc b/README.rdoc
index f45918e..1187637 100644
--- a/README.rdoc
+++ b/README.rdoc
@@ -66,7 +66,7 @@ If you want to run the tests or use any of the Rake tasks, you'll need:
* gem install net-ssh-multi
-However, in order to be sure the code you're installing hasn't been tampered with, it's recommended that you verify the signiture[http://docs.rubygems.org/read/chapter/21]. To do this, you need to add my public key as a trusted certificate (you only need to do this once):
+However, in order to be sure the code you're installing hasn't been tampered with, it's recommended that you verify the signature[http://docs.rubygems.org/read/chapter/21]. To do this, you need to add my public key as a trusted certificate (you only need to do this once):
# Add the public key as a trusted certificate
# (You only need to do this once)
diff --git a/Rakefile b/Rakefile
index 039f5cc..3420250 100644
--- a/Rakefile
+++ b/Rakefile
@@ -31,8 +31,14 @@ begin
s.license = "MIT"
- s.signing_key = File.join('/mnt/gem/', 'gem-private_key.pem')
- s.cert_chain = ['gem-public_cert.pem']
+ unless ENV['NET_SSH_NOKEY']
+ signing_key = File.join('/mnt/gem/', 'net-ssh-private_key.pem')
+ s.signing_key = signing_key
+ s.cert_chain = ['gem-public_cert.pem']
+ unless (Rake.application.top_level_tasks & ['build','install']).empty?
+ raise "No key found at #{signing_key} for signing, use rake <taskname> NET_SSH_NOKEY=1 to build without key" unless File.exist?(signing_key)
+ end
+ end
end
Jeweler::GemcutterTasks.new
rescue LoadError
diff --git a/gem-public_cert.pem b/gem-public_cert.pem
index 1bda370..ffa10de 100644
--- a/gem-public_cert.pem
+++ b/gem-public_cert.pem
@@ -1,20 +1,20 @@
-----BEGIN CERTIFICATE-----
-MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMQ8wDQYDVQQDDAZkZWxh
-bm8xGTAXBgoJkiaJk/IsZAEZFglzb2x1dGlvdXMxEzARBgoJkiaJk/IsZAEZFgNj
-b20wHhcNMTMwMjA2MTE1NzQ1WhcNMTQwMjA2MTE1NzQ1WjBBMQ8wDQYDVQQDDAZk
-ZWxhbm8xGTAXBgoJkiaJk/IsZAEZFglzb2x1dGlvdXMxEzARBgoJkiaJk/IsZAEZ
-FgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDg1hMtl0XsMuUK
-AKTgYWv3gjj7vuEsE2EjT+vyBg8/LpqVVwZziiaebJT9IZiQ+sCFqbiakj0b53pI
-hg1yOaBEmH6/W0L7rwzqaRV9sW1eJs9JxFYQCnd67zUnzj8nnRlOjG+hhIG+Vsij
-npsGbt28pefuNZJjO5q2clAlfSniIIHfIsU7/StEYu6FUGOjnwryZ0r5yJlr9RrE
-Gs+q0DW8QnZ9UpAfuDFQZuIqeKQFFLE7nMmCGaA+0BN1nLl3fVHNbLHq7Avk8+Z+
-ZuuvkdscbHlO/l+3xCNQ5nUnHwq0ADAbMLOlmiYYzqXoWLjmeI6me/clktJCfN2R
-oZG3UQvvAgMBAAGjOTA3MAkGA1UdEwQCMAAwHQYDVR0OBBYEFMSJOEtHzE4l0azv
-M0JK0kKNToK1MAsGA1UdDwQEAwIEsDANBgkqhkiG9w0BAQUFAAOCAQEAtOdE73qx
-OH2ydi9oT2hS5f9G0y1Z70Tlwh+VGExyfxzVE9XwC+iPpJxNraiHYgF/9/oky7ZZ
-R9q0/tJneuhAenZdiQkX7oi4O3v9wRS6YHoWBxMPFKVRLNTzvVJsbmfpCAlp5/5g
-ps4wQFy5mibElGVlOobf/ghqZ25HS9J6kd0/C/ry0AUtTogsL7TxGwT4kbCx63ub
-3vywEEhsJUzfd97GCABmtQfRTldX/j7F1z/5wd8p+hfdox1iibds9ZtfaZA3KzKn
-kchWN9B6zg9r1XMQ8BM2Jz0XoPanPe354+lWwjpkRKbFow/ZbQHcCLCq24+N6b6g
-dgKfNDzwiDpqCA==
+MIIDODCCAiCgAwIBAgIBADANBgkqhkiG9w0BAQUFADBCMRAwDgYDVQQDDAduZXQt
+c3NoMRkwFwYKCZImiZPyLGQBGRYJc29sdXRpb3VzMRMwEQYKCZImiZPyLGQBGRYD
+Y29tMB4XDTE1MTIwNjIxMDYyNFoXDTE2MTIwNTIxMDYyNFowQjEQMA4GA1UEAwwH
+bmV0LXNzaDEZMBcGCgmSJomT8ixkARkWCXNvbHV0aW91czETMBEGCgmSJomT8ixk
+ARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMYnhNtn0f6p
+nTylB8mE8lMdoMLJC8KwpMWsvk73Pe2WVDsH/OSwwwz6oUGk1i70cJyDjIEBNpwT
+88GpVXJSumvqVsf9fCg3mWNeb5t0J+aeNm9MIvYVMTqj5tydoXQiwnILRDYHV9tZ
+1c3o59/VlahSTpZ7YEgzVufpAkvEGkbJiG849exiipK7MN/ZIkMOxYVnyRXk43Xc
+6GYlsHOfSgPwcXwW5g57DCwLQLWrjDsTka28dxDmO7B5Lv5EqzINxVxWsu43OgZG
+21Io/jIyf5PNpeKPKNGDuAQJ8mvdMYBJoDhtCwgsUYbl0BZzA7g4ytl51HtIeP+j
+Qp/eAvs/RrECAwEAAaM5MDcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUBfKiwO2eM4NE
+iRrVG793qEPLYyMwCwYDVR0PBAQDAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQCfZFdb
+p4jzkfIzGDbiOxd0R8sdqJoC4nMLEgnQ7dLulawwA3IXe3sHAKgA5kmH3prsKc5H
+zVmM5NlH2P1nRbegIkQTYiIod1hZQCNxdmVG/fprMqPq0ybpUOjjrP5pj0OtszE1
+F2dQia1hOEstMR+n0nAtWII9HJAEyeZjVV0s2Cl7Pt85XJ3hxFcCKwzqsK5xRI7a
+B3vwh3/JJYrFonIohQ//Lg9qTZASEkoKLlq1/hFeICoCGGIGLq45ZB7CzXLooCKi
+s/ZUKye79ELwFYKJOhjW5g725OL3hy+llhEleytwKRwgXFQBPTC4f5UkdxZVVWGH
+e2C9M1m/2odPZo8h
-----END CERTIFICATE-----
diff --git a/lib/net/ssh/multi/pending_connection.rb b/lib/net/ssh/multi/pending_connection.rb
index 6af0fac..5faaf70 100644
--- a/lib/net/ssh/multi/pending_connection.rb
+++ b/lib/net/ssh/multi/pending_connection.rb
@@ -31,6 +31,28 @@ module Net; module SSH; module Multi
end
end
+ # Represents a #forward action.
+ class ForwardRecording
+ def initialize
+ @recordings = []
+ end
+
+ def remote(port, host, remote_port, remote_host="127.0.0.1")
+ @recordings << [:remote, port, host, remote_port, remote_host]
+ end
+
+ def replay_on(session)
+ forward = session.forward
+ @recordings.each { |args| forward.send(*args) }
+ end
+ end
+
+ def forward
+ forward = ForwardRecording.new
+ @recordings << forward
+ forward
+ end
+
# Represents a #send_global_request action.
class SendGlobalRequestRecording #:nodoc:
attr_reader :type, :extra, :callback
diff --git a/lib/net/ssh/multi/server.rb b/lib/net/ssh/multi/server.rb
index 77c5948..bcf3678 100644
--- a/lib/net/ssh/multi/server.rb
+++ b/lib/net/ssh/multi/server.rb
@@ -1,4 +1,5 @@
require 'net/ssh'
+require 'timeout'
module Net; module SSH; module Multi
# Encapsulates the connection information for a single remote server, as well
@@ -55,6 +56,7 @@ module Net; module SSH; module Multi
@gateway = @options.delete(:via)
@failed = false
+ @session = @ready_session = nil
end
# Returns the value of the server property with the given +key+. Server
diff --git a/lib/net/ssh/multi/session.rb b/lib/net/ssh/multi/session.rb
index 2e2468f..409aeae 100644
--- a/lib/net/ssh/multi/session.rb
+++ b/lib/net/ssh/multi/session.rb
@@ -425,7 +425,7 @@ module Net; module SSH; module Multi
# +false+ (the block returned +false+).
def process(wait=nil, &block)
realize_pending_connections!
- wait = @connect_threads.any? ? 0 : wait
+ wait = @connect_threads.any? ? 0 : io_select_wait(wait)
return false unless preprocess(&block)
@@ -441,6 +441,15 @@ module Net; module SSH; module Multi
end
end
+ def io_select_wait(wait)
+ [wait, keepalive_interval].compact.min
+ end
+
+ def keepalive_interval
+ servers = server_list.select { |s| s.options[:keepalive] }
+ servers.map { |s| s.options[:keepalive_interval] }.compact.min
+ end
+
# Runs the preprocess stage on all servers. Returns false if the block
# returns false, and true if there either is no block, or it returns true.
# This is called as part of the #process method.
diff --git a/lib/net/ssh/multi/session_actions.rb b/lib/net/ssh/multi/session_actions.rb
index 2d87392..c6b1355 100644
--- a/lib/net/ssh/multi/session_actions.rb
+++ b/lib/net/ssh/multi/session_actions.rb
@@ -118,8 +118,8 @@ module Net; module SSH; module Multi
# end
def exec(command, &block)
open_channel do |channel|
- channel.exec(command) do |ch, success|
- raise "could not execute command: #{command.inspect} (#{ch[:host]})" unless success
+ channel.exec(command) do |c, success|
+ raise "could not execute command: #{command.inspect} (#{c[:host]})" unless success
channel.on_data do |ch, data|
if block
diff --git a/lib/net/ssh/multi/version.rb b/lib/net/ssh/multi/version.rb
index 9854f32..c2f085e 100644
--- a/lib/net/ssh/multi/version.rb
+++ b/lib/net/ssh/multi/version.rb
@@ -7,13 +7,17 @@ module Net; module SSH; module Multi
MAJOR = 1
# The minor component of the library's version
- MINOR = 2
+ MINOR = 3
# The tiny component of the library's version
- TINY = 1
+ TINY = 0
+
+ # The prerelease component of this version of the Net::SSH library
+ # nil allowed
+ PRE = "rc1"
# The library's version as a Version instance
- CURRENT = new(MAJOR, MINOR, TINY)
+ CURRENT = new(*[MAJOR, MINOR, TINY, PRE].compact)
# The library's version as a String instance
STRING = CURRENT.to_s
diff --git a/net-ssh-multi.gemspec b/net-ssh-multi.gemspec
index 5b3bbe7..fb7ade3 100644
--- a/net-ssh-multi.gemspec
+++ b/net-ssh-multi.gemspec
@@ -2,15 +2,17 @@
# DO NOT EDIT THIS FILE DIRECTLY
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
# -*- encoding: utf-8 -*-
+# stub: net-ssh-multi 1.3.0.rc1 ruby lib
Gem::Specification.new do |s|
s.name = "net-ssh-multi"
- s.version = "1.2.1"
+ s.version = "1.3.0.rc1"
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
+ s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
+ s.require_paths = ["lib"]
s.authors = ["Jamis Buck", "Delano Mandelbaum"]
s.cert_chain = ["gem-public_cert.pem"]
- s.date = "2015-04-11"
+ s.date = "2016-03-24"
s.description = "Control multiple Net::SSH connections via a single interface."
s.email = "net-ssh@solutious.com"
s.extra_rdoc_files = [
@@ -18,6 +20,7 @@ Gem::Specification.new do |s|
"README.rdoc"
]
s.files = [
+ ".travis.yml",
"CHANGES.txt",
"LICENSE.txt",
"README.rdoc",
@@ -45,14 +48,13 @@ Gem::Specification.new do |s|
]
s.homepage = "https://github.com/net-ssh/net-scp"
s.licenses = ["MIT"]
- s.require_paths = ["lib"]
s.rubyforge_project = "net-ssh-multi"
- s.rubygems_version = "1.8.23"
- s.signing_key = "/mnt/gem/gem-private_key.pem"
+ s.rubygems_version = "2.4.6"
+ s.signing_key = "/mnt/gem/net-ssh-private_key.pem"
s.summary = "Control multiple Net::SSH connections via a single interface."
if s.respond_to? :specification_version then
- s.specification_version = 3
+ s.specification_version = 4
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
s.add_runtime_dependency(%q<net-ssh>, [">= 2.6.5"])
diff --git a/test/channel_test.rb b/test/channel_test.rb
index 2c08573..475c59b 100644
--- a/test/channel_test.rb
+++ b/test/channel_test.rb
@@ -3,7 +3,7 @@ require 'net/ssh/multi/channel'
class ChannelTest < Minitest::Test
def test_each_should_iterate_over_each_component_channel
- channels = [c1 = mock('channel'), c2 = mock('channel'), c3 = mock('channel')]
+ channels = [mock('channel'), mock('channel'), mock('channel')]
channel = Net::SSH::Multi::Channel.new(mock('session'), channels)
result = []
channel.each { |c| result << c }
diff --git a/test/session_actions_test.rb b/test/session_actions_test.rb
index e6de5b1..c9e29d6 100644
--- a/test/session_actions_test.rb
+++ b/test/session_actions_test.rb
@@ -94,7 +94,7 @@ class SessionActionsTest < Minitest::Test
c.expects(:on_extended_data).yields(c, 1, "stderr")
c.expects(:on_request)
results = {}
- @session.exec("something") do |c, stream, data|
+ @session.exec("something") do |_, stream, data|
results[stream] = data
end
assert_equal({:stdout => "stdout", :stderr => "stderr"}, results)
diff --git a/test/session_test.rb b/test/session_test.rb
index 42a56b2..c027db9 100644
--- a/test/session_test.rb
+++ b/test/session_test.rb
@@ -198,4 +198,25 @@ class SessionTest < Minitest::Test
IO.expects(:select).with([:a, :b, :c], [:a, :c], nil, 5).returns([[:b, :c], [:a, :c]])
@session.process(5)
end
+
+ def test_process_should_pass_minimum_keepalive_interval_as_io_select_timeout
+ @session.use('h1', :keepalive => true)
+ @session.use('h2', :keepalive_interval => 1)
+ @session.use('h3', :keepalive => true, :keepalive_interval => 2)
+ @session.use('h4', :keepalive => true, :keepalive_interval => 3)
+ IO.expects(:select).with([], [], nil, 2)
+ @session.process
+ end
+
+ def test_process_should_pass_wait_as_io_select_timeout_if_provided_and_minimum
+ @session.use('h1', :keepalive => true, :keepalive_interval => 1)
+ IO.expects(:select).with([], [], nil, 1)
+ @session.process(2)
+ end
+
+ def test_process_should_pass_nil_as_io_select_timeout_by_default
+ @session.use('h1')
+ IO.expects(:select).with([], [], nil, nil)
+ @session.process
+ end
end