Permalink
Browse files

restore plugin extension mechanism, fix hostname problem for tunnelle…

…d connections

git-svn-id: http://svn.rubyonrails.org/rails/tools/capistrano@6436 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
1 parent f8d425e commit 55e194c3f058615680602fa14df25710806c120c @jamis jamis committed Mar 16, 2007
View
2 capistrano.gemspec
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
on multiple remote machines, via SSH.
DESC
- s.files = Dir.glob("{bin,lib,examples,test}/**/*") + %w(README MIT-LICENSE CHANGELOG THANKS)
+ s.files = Dir.glob("{bin,lib,examples,test}/**/*") + %w(README MIT-LICENSE CHANGELOG)
s.require_path = 'lib'
s.autorequire = 'capistrano'
View
1 lib/capistrano.rb
@@ -1 +1,2 @@
require 'capistrano/configuration'
+require 'capistrano/extensions'
View
1 lib/capistrano/cli.rb
@@ -1,3 +1,4 @@
+require 'capistrano'
require 'capistrano/cli/execute'
require 'capistrano/cli/help'
require 'capistrano/cli/options'
View
2 lib/capistrano/command.rb
@@ -75,7 +75,7 @@ def logger
def open_channels
sessions.map do |session|
session.open_channel do |channel|
- channel[:host] = session.host
+ channel[:host] = session.real_host
channel[:options] = options
channel.request_pty :want_reply => true
View
1 lib/capistrano/configuration.rb
@@ -1,4 +1,3 @@
-#require 'capistrano/extensions'
require 'capistrano/logger'
require 'capistrano/configuration/connections'
View
77 lib/capistrano/extensions.rb
@@ -1,36 +1,41 @@
-# module Capistrano
-# class ExtensionProxy
-# def initialize(actor, mod)
-# @actor = actor
-# extend(mod)
-# end
-#
-# def method_missing(sym, *args, &block)
-# @actor.send(sym, *args, &block)
-# end
-# end
-#
-# EXTENSIONS = {}
-#
-# def self.plugin(name, mod)
-# return false if EXTENSIONS.has_key?(name)
-#
-# Capistrano::Actor.class_eval <<-STR, __FILE__, __LINE__+1
-# def #{name}
-# @__#{name}_proxy ||= Capistrano::ExtensionProxy.new(self, Capistrano::EXTENSIONS[#{name.inspect}])
-# end
-# STR
-#
-# EXTENSIONS[name] = mod
-# return true
-# end
-#
-# def self.remove_plugin(name)
-# if EXTENSIONS.delete(name)
-# Capistrano::Actor.send(:remove_method, name)
-# return true
-# end
-#
-# return false
-# end
-# end
+module Capistrano
+ class ExtensionProxy
+ def initialize(config, mod)
+ @config = config
+ extend(mod)
+ end
+
+ def method_missing(sym, *args, &block)
+ @config.send(sym, *args, &block)
+ end
+ end
+
+ EXTENSIONS = {}
+
+ def self.plugin(name, mod)
+ return false if EXTENSIONS.has_key?(name)
+
+ Capistrano::Configuration.class_eval <<-STR, __FILE__, __LINE__+1
+ def #{name}
+ @__#{name}_proxy ||= Capistrano::ExtensionProxy.new(self, Capistrano::EXTENSIONS[#{name.inspect}])
+ end
+ STR
+
+ EXTENSIONS[name] = mod
+ return true
+ end
+
+ def self.remove_plugin(name)
+ if EXTENSIONS.delete(name)
+ Capistrano::Configuration.send(:remove_method, name)
+ return true
+ end
+
+ return false
+ end
+
+ def self.configuration(*args)
+ warn "[DEPRECATION] Capistrano.configuration is deprecated. Use Capistrano::Configuration.instance instead"
+ Capistrano::Configuration.instance(*args)
+ end
+end
View
1 lib/capistrano/gateway.rb
@@ -81,6 +81,7 @@ def connect_to(server)
local_host = ServerDefinition.new("127.0.0.1", :user => server.user, :port => local_port)
session.forward.local(local_port, server.host, server.port || 22)
connection = SSH.connect(local_host, @options)
+ connection.real_host = server.host
logger.trace "connected: `#{server.host}' (via gateway)" if logger
rescue Errno::EADDRINUSE
local_port = next_port
View
17 lib/capistrano/ssh.rb
@@ -12,6 +12,20 @@ module Capistrano
# A helper class for dealing with SSH connections.
class SSH
+ # Patch an accessor onto an SSH connection so that we can record the "real"
+ # host behind the connection. This is useful because the gateway returns
+ # connections whose "host" is 127.0.0.1, instead of the host on the other
+ # side of the tunnel.
+ module RealHost #:nodoc:
+ def self.apply_to(connection, host)
+ connection.extend(RealHost)
+ connection.real_host = host
+ connection
+ end
+
+ attr_accessor :real_host
+ end
+
# The default port for SSH.
DEFAULT_PORT = 22
@@ -34,7 +48,8 @@ def self.connect(server, options={}, &block)
:auth_methods => methods.shift }
ssh_options.update(options[:ssh_options]) if options[:ssh_options]
- Net::SSH.start(server.host, ssh_options, &block)
+ connection = Net::SSH.start(server.host, ssh_options, &block)
+ RealHost.apply_to(connection, server.host)
rescue Net::SSH::AuthenticationFailed
raise if methods.empty?
View
8 test/command_test.rb
@@ -53,7 +53,7 @@ def test_env_with_multiple_keys_should_chain_the_entries_together
end
def test_open_channel_should_set_host_key_on_channel
- session = mock(:host => "capistrano")
+ session = mock(:real_host => "capistrano")
channel = stub_everything
session.expects(:open_channel).yields(channel)
@@ -63,7 +63,7 @@ def test_open_channel_should_set_host_key_on_channel
end
def test_open_channel_should_set_options_key_on_channel
- session = mock(:host => "capistrano")
+ session = mock(:real_host => "capistrano")
channel = stub_everything
session.expects(:open_channel).yields(channel)
@@ -73,7 +73,7 @@ def test_open_channel_should_set_options_key_on_channel
end
def test_open_channel_should_request_pty
- session = mock(:host => "capistrano")
+ session = mock(:real_host => "capistrano")
channel = stub_everything
session.expects(:open_channel).yields(channel)
@@ -240,7 +240,7 @@ def new_channel(closed, status=nil)
end
def setup_for_extracting_channel_action(action, *args)
- session = mock(:host => "capistrano")
+ session = mock(:real_host => "capistrano")
channel = stub_everything
session.expects(:open_channel).yields(channel)
View
31 test/gateway_test.rb
@@ -25,39 +25,46 @@ def test_shutdown_without_any_open_connections_should_terminate_session
def test_connect_to_should_start_local_ports_at_65535
gateway = new_gateway
- expect_connect_to(:host => "127.0.0.1", :port => 65535).returns :app1
+ expect_connect_to(:host => "127.0.0.1", :port => 65535).returns(result = sess_with_real_host("app1"))
newsess = gateway.connect_to(server("app1"))
- assert_equal :app1, newsess
+ assert_equal result, newsess
assert_equal [65535, "app1", 22], gateway.session.forward.active_locals[65535]
end
def test_connect_to_should_decrement_port_and_retry_if_ports_are_in_use
gateway = new_gateway(:reserved => lambda { |n| n > 65000 })
- expect_connect_to(:host => "127.0.0.1", :port => 65000).returns :app1
+ expect_connect_to(:host => "127.0.0.1", :port => 65000).returns(result = sess_with_real_host("app1"))
newsess = gateway.connect_to(server("app1"))
- assert_equal :app1, newsess
+ assert_equal result, newsess
assert_equal [65000, "app1", 22], gateway.session.forward.active_locals[65000]
end
def test_connect_to_should_honor_user_specification_in_server_definition
gateway = new_gateway
- expect_connect_to(:host => "127.0.0.1", :user => "jamis", :port => 65535).returns :app1
+ expect_connect_to(:host => "127.0.0.1", :user => "jamis", :port => 65535).returns(result = sess_with_real_host("app1"))
newsess = gateway.connect_to(server("jamis@app1"))
- assert_equal :app1, newsess
+ assert_equal result, newsess
assert_equal [65535, "app1", 22], gateway.session.forward.active_locals[65535]
end
def test_connect_to_should_honor_port_specification_in_server_definition
gateway = new_gateway
- expect_connect_to(:host => "127.0.0.1", :port => 65535).returns :app1
+ expect_connect_to(:host => "127.0.0.1", :port => 65535).returns(result = sess_with_real_host("app1"))
newsess = gateway.connect_to(server("app1:1234"))
- assert_equal :app1, newsess
+ assert_equal result, newsess
assert_equal [65535, "app1", 1234], gateway.session.forward.active_locals[65535]
end
+ def test_connect_to_should_set_real_host_to_tunnel_target
+ gateway = new_gateway
+ expect_connect_to(:host => "127.0.0.1", :port => 65535).returns(result = sess_with_real_host("app1"))
+ newsess = gateway.connect_to(server("app1:1234"))
+ assert_equal result, newsess
+ end
+
def test_shutdown_should_cancel_active_forwarded_ports
gateway = new_gateway
- expect_connect_to(:host => "127.0.0.1", :port => 65535).returns :app1
+ expect_connect_to(:host => "127.0.0.1", :port => 65535).returns(sess_with_real_host("app1"))
gateway.connect_to(server("app1"))
assert !gateway.session.forward.active_locals.empty?
gateway.shutdown!
@@ -73,6 +80,12 @@ def test_error_while_connecting_should_cause_connection_to_fail
private
+ def sess_with_real_host(host)
+ sess = mock("session")
+ sess.expects(:real_host=).with(host)
+ sess
+ end
+
def expect_connect_to(options={})
Capistrano::SSH.expects(:connect).with do |server,config|
options.all? do |key, value|
View
48 test/ssh_test.rb
@@ -11,14 +11,14 @@ def setup
end
def test_connect_with_bare_server_without_options_or_config_with_public_key_succeeding_should_only_loop_once
- Net::SSH.expects(:start).with(@server.host, @options).returns(:success)
- assert_equal :success, Capistrano::SSH.connect(@server)
+ Net::SSH.expects(:start).with(@server.host, @options).returns(success = Object.new)
+ assert_equal success, Capistrano::SSH.connect(@server)
end
def test_connect_with_bare_server_without_options_with_public_key_failing_should_try_password
Net::SSH.expects(:start).with(@server.host, @options).raises(Net::SSH::AuthenticationFailed)
- Net::SSH.expects(:start).with(@server.host, @options.merge(:password => "f4b13n", :auth_methods => %w(password keyboard-interactive))).returns(:success)
- assert_equal :success, Capistrano::SSH.connect(@server, :password => "f4b13n")
+ Net::SSH.expects(:start).with(@server.host, @options.merge(:password => "f4b13n", :auth_methods => %w(password keyboard-interactive))).returns(success = Object.new)
+ assert_equal success, Capistrano::SSH.connect(@server, :password => "f4b13n")
end
def test_connect_with_bare_server_without_options_public_key_and_password_failing_should_raise_error
@@ -30,49 +30,57 @@ def test_connect_with_bare_server_without_options_public_key_and_password_failin
end
def test_connect_with_bare_server_and_user_via_public_key_should_pass_user_to_net_ssh
- Net::SSH.expects(:start).with(@server.host, @options.merge(:username => "jamis")).returns(:success)
- assert_equal :success, Capistrano::SSH.connect(@server, :user => "jamis")
+ Net::SSH.expects(:start).with(@server.host, @options.merge(:username => "jamis")).returns(success = Object.new)
+ assert_equal success, Capistrano::SSH.connect(@server, :user => "jamis")
end
def test_connect_with_bare_server_and_user_via_password_should_pass_user_to_net_ssh
Net::SSH.expects(:start).with(@server.host, @options.merge(:username => "jamis")).raises(Net::SSH::AuthenticationFailed)
- Net::SSH.expects(:start).with(@server.host, @options.merge(:username => "jamis", :password => "f4b13n", :auth_methods => %w(password keyboard-interactive))).returns(:success)
- assert_equal :success, Capistrano::SSH.connect(@server, :user => "jamis", :password => "f4b13n")
+ Net::SSH.expects(:start).with(@server.host, @options.merge(:username => "jamis", :password => "f4b13n", :auth_methods => %w(password keyboard-interactive))).returns(success = Object.new)
+ assert_equal success, Capistrano::SSH.connect(@server, :user => "jamis", :password => "f4b13n")
end
def test_connect_with_bare_server_with_explicit_port_should_pass_port_to_net_ssh
- Net::SSH.expects(:start).with(@server.host, @options.merge(:port => 1234)).returns(:success)
- assert_equal :success, Capistrano::SSH.connect(@server, :port => 1234)
+ Net::SSH.expects(:start).with(@server.host, @options.merge(:port => 1234)).returns(success = Object.new)
+ assert_equal success, Capistrano::SSH.connect(@server, :port => 1234)
end
def test_connect_with_server_with_user_should_pass_user_to_net_ssh
server = server("jamis@capistrano")
- Net::SSH.expects(:start).with(server.host, @options.merge(:username => "jamis")).returns(:success)
- assert_equal :success, Capistrano::SSH.connect(server)
+ Net::SSH.expects(:start).with(server.host, @options.merge(:username => "jamis")).returns(success = Object.new)
+ assert_equal success, Capistrano::SSH.connect(server)
end
def test_connect_with_server_with_port_should_pass_port_to_net_ssh
server = server("capistrano:1235")
- Net::SSH.expects(:start).with(server.host, @options.merge(:port => 1235)).returns(:success)
- assert_equal :success, Capistrano::SSH.connect(server)
+ Net::SSH.expects(:start).with(server.host, @options.merge(:port => 1235)).returns(success = Object.new)
+ assert_equal success, Capistrano::SSH.connect(server)
end
def test_connect_with_server_with_user_and_port_should_pass_user_and_port_to_net_ssh
server = server("jamis@capistrano:1235")
- Net::SSH.expects(:start).with(server.host, @options.merge(:username => "jamis", :port => 1235)).returns(:success)
- assert_equal :success, Capistrano::SSH.connect(server)
+ Net::SSH.expects(:start).with(server.host, @options.merge(:username => "jamis", :port => 1235)).returns(success = Object.new)
+ assert_equal success, Capistrano::SSH.connect(server)
end
def test_connect_with_ssh_options_should_override_options
ssh_options = { :username => "JamisMan", :port => 8125 }
- Net::SSH.expects(:start).with(@server.host, @options.merge(:username => "JamisMan", :port => 8125)).returns(:success)
- assert_equal :success, Capistrano::SSH.connect(@server, {:ssh_options => ssh_options, :user => "jamis", :port => 1235})
+ Net::SSH.expects(:start).with(@server.host, @options.merge(:username => "JamisMan", :port => 8125)).returns(success = Object.new)
+ assert_equal success, Capistrano::SSH.connect(@server, {:ssh_options => ssh_options, :user => "jamis", :port => 1235})
end
def test_connect_with_ssh_options_should_override_server_options
ssh_options = { :username => "JamisMan", :port => 8125 }
server = server("jamis@capistrano:1235")
- Net::SSH.expects(:start).with(server.host, @options.merge(:username => "JamisMan", :port => 8125)).returns(:success)
- assert_equal :success, Capistrano::SSH.connect(server, {:ssh_options => ssh_options})
+ Net::SSH.expects(:start).with(server.host, @options.merge(:username => "JamisMan", :port => 8125)).returns(success = Object.new)
+ assert_equal success, Capistrano::SSH.connect(server, {:ssh_options => ssh_options})
+ end
+
+ def test_connect_should_add_real_host_accessor_to_connection
+ Net::SSH.expects(:start).with(@server.host, @options).returns(success = Object.new)
+ assert_equal success, Capistrano::SSH.connect(@server)
+ assert success.respond_to?(:real_host)
+ assert success.respond_to?(:real_host=)
+ assert_equal success.real_host, @server.host
end
end

0 comments on commit 55e194c

Please sign in to comment.