capistrano 2.2.0 → 2.3.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/CHANGELOG +29 -0
- data/README +4 -7
- data/bin/cap +0 -0
- data/bin/capify +0 -0
- data/lib/capistrano/command.rb +32 -38
- data/lib/capistrano/configuration/actions/file_transfer.rb +21 -13
- data/lib/capistrano/configuration/actions/invocation.rb +1 -1
- data/lib/capistrano/configuration/connections.rb +30 -20
- data/lib/capistrano/errors.rb +1 -1
- data/lib/capistrano/processable.rb +53 -0
- data/lib/capistrano/recipes/deploy/remote_dependency.rb +6 -0
- data/lib/capistrano/recipes/deploy/scm/git.rb +26 -11
- data/lib/capistrano/recipes/deploy/scm/none.rb +44 -0
- data/lib/capistrano/recipes/deploy/strategy/base.rb +6 -0
- data/lib/capistrano/recipes/deploy/strategy/copy.rb +74 -3
- data/lib/capistrano/recipes/deploy.rb +15 -13
- data/lib/capistrano/role.rb +0 -14
- data/lib/capistrano/server_definition.rb +5 -0
- data/lib/capistrano/shell.rb +21 -17
- data/lib/capistrano/ssh.rb +24 -58
- data/lib/capistrano/transfer.rb +216 -0
- data/lib/capistrano/version.rb +1 -1
- data/test/cli/execute_test.rb +1 -1
- data/test/cli/help_test.rb +1 -1
- data/test/cli/options_test.rb +1 -1
- data/test/cli/ui_test.rb +1 -1
- data/test/cli_test.rb +1 -1
- data/test/command_test.rb +31 -51
- data/test/configuration/actions/file_transfer_test.rb +21 -19
- data/test/configuration/actions/inspect_test.rb +1 -1
- data/test/configuration/actions/invocation_test.rb +6 -6
- data/test/configuration/callbacks_test.rb +1 -1
- data/test/configuration/connections_test.rb +11 -12
- data/test/configuration/execution_test.rb +1 -1
- data/test/configuration/loading_test.rb +1 -1
- data/test/configuration/namespace_dsl_test.rb +1 -1
- data/test/configuration/roles_test.rb +1 -1
- data/test/configuration/servers_test.rb +1 -1
- data/test/configuration/variables_test.rb +1 -1
- data/test/configuration_test.rb +1 -1
- data/test/deploy/scm/accurev_test.rb +1 -1
- data/test/deploy/scm/base_test.rb +1 -1
- data/test/deploy/scm/git_test.rb +10 -6
- data/test/deploy/scm/mercurial_test.rb +1 -1
- data/test/deploy/strategy/copy_test.rb +120 -27
- data/test/extensions_test.rb +1 -1
- data/test/logger_test.rb +1 -1
- data/test/server_definition_test.rb +1 -1
- data/test/shell_test.rb +27 -1
- data/test/ssh_test.rb +27 -21
- data/test/task_definition_test.rb +1 -1
- data/test/transfer_test.rb +160 -0
- data/test/utils.rb +30 -34
- data/test/version_test.rb +1 -1
- metadata +26 -14
- data/lib/capistrano/gateway.rb +0 -131
- data/lib/capistrano/upload.rb +0 -152
- data/test/gateway_test.rb +0 -167
- data/test/upload_test.rb +0 -131
data/test/extensions_test.rb
CHANGED
data/test/logger_test.rb
CHANGED
data/test/shell_test.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require "
|
1
|
+
require "utils"
|
2
2
|
require 'capistrano/configuration'
|
3
3
|
require 'capistrano/shell'
|
4
4
|
|
@@ -61,4 +61,30 @@ class ShellTest < Test::Unit::TestCase
|
|
61
61
|
@shell.expects(:process_command).with("on", "app,db", "hello world")
|
62
62
|
assert @shell.read_and_execute
|
63
63
|
end
|
64
|
+
|
65
|
+
def test_task_command_with_bang_gets_processed_by_exec_tasks
|
66
|
+
while_testing_post_exec_commands do
|
67
|
+
@shell.expects(:read_line).returns("!deploy")
|
68
|
+
@shell.expects(:exec_tasks).with(["deploy"])
|
69
|
+
assert @shell.read_and_execute
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_normal_command_gets_processed_by_exec_command
|
74
|
+
while_testing_post_exec_commands do
|
75
|
+
@shell.expects(:read_line).returns("uptime")
|
76
|
+
@shell.expects(:exec_command).with("uptime",nil)
|
77
|
+
@shell.expects(:connect)
|
78
|
+
assert @shell.read_and_execute
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def while_testing_post_exec_commands(&block)
|
86
|
+
@shell.instance_variable_set(:@mutex,Mutex.new)
|
87
|
+
yield
|
88
|
+
end
|
89
|
+
|
64
90
|
end
|
data/test/ssh_test.rb
CHANGED
@@ -1,89 +1,95 @@
|
|
1
|
-
require "
|
1
|
+
require "utils"
|
2
2
|
require 'capistrano/ssh'
|
3
3
|
|
4
4
|
class SSHTest < Test::Unit::TestCase
|
5
5
|
def setup
|
6
|
-
|
7
|
-
|
6
|
+
Capistrano::ServerDefinition.stubs(:default_user).returns("default-user")
|
7
|
+
@options = { :password => nil,
|
8
8
|
:port => 22,
|
9
9
|
:auth_methods => %w(publickey hostbased) }
|
10
10
|
@server = server("capistrano")
|
11
11
|
end
|
12
12
|
|
13
13
|
def test_connect_with_bare_server_without_options_or_config_with_public_key_succeeding_should_only_loop_once
|
14
|
-
Net::SSH.expects(:start).with(@server.host, @options).returns(success = Object.new)
|
14
|
+
Net::SSH.expects(:start).with(@server.host, "default-user", @options).returns(success = Object.new)
|
15
15
|
assert_equal success, Capistrano::SSH.connect(@server)
|
16
16
|
end
|
17
17
|
|
18
18
|
def test_connect_with_bare_server_without_options_with_public_key_failing_should_try_password
|
19
|
-
Net::SSH.expects(:start).with(@server.host, @options).raises(Net::SSH::AuthenticationFailed)
|
20
|
-
Net::SSH.expects(:start).with(@server.host, @options.merge(:password => "f4b13n", :auth_methods => %w(password keyboard-interactive))).returns(success = Object.new)
|
19
|
+
Net::SSH.expects(:start).with(@server.host, "default-user", @options).raises(Net::SSH::AuthenticationFailed)
|
20
|
+
Net::SSH.expects(:start).with(@server.host, "default-user", @options.merge(:password => "f4b13n", :auth_methods => %w(password keyboard-interactive))).returns(success = Object.new)
|
21
21
|
assert_equal success, Capistrano::SSH.connect(@server, :password => "f4b13n")
|
22
22
|
end
|
23
23
|
|
24
24
|
def test_connect_with_bare_server_without_options_public_key_and_password_failing_should_raise_error
|
25
|
-
Net::SSH.expects(:start).with(@server.host, @options).raises(Net::SSH::AuthenticationFailed)
|
26
|
-
Net::SSH.expects(:start).with(@server.host, @options.merge(:password => "f4b13n", :auth_methods => %w(password keyboard-interactive))).raises(Net::SSH::AuthenticationFailed)
|
25
|
+
Net::SSH.expects(:start).with(@server.host, "default-user", @options).raises(Net::SSH::AuthenticationFailed)
|
26
|
+
Net::SSH.expects(:start).with(@server.host, "default-user", @options.merge(:password => "f4b13n", :auth_methods => %w(password keyboard-interactive))).raises(Net::SSH::AuthenticationFailed)
|
27
27
|
assert_raises(Net::SSH::AuthenticationFailed) do
|
28
28
|
Capistrano::SSH.connect(@server, :password => "f4b13n")
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
32
|
def test_connect_with_bare_server_and_user_via_public_key_should_pass_user_to_net_ssh
|
33
|
-
Net::SSH.expects(:start).with(@server.host,
|
33
|
+
Net::SSH.expects(:start).with(@server.host, "jamis", @options).returns(success = Object.new)
|
34
34
|
assert_equal success, Capistrano::SSH.connect(@server, :user => "jamis")
|
35
35
|
end
|
36
36
|
|
37
37
|
def test_connect_with_bare_server_and_user_via_password_should_pass_user_to_net_ssh
|
38
|
-
Net::SSH.expects(:start).with(@server.host,
|
39
|
-
Net::SSH.expects(:start).with(@server.host, @options.merge(:
|
38
|
+
Net::SSH.expects(:start).with(@server.host, "jamis", @options).raises(Net::SSH::AuthenticationFailed)
|
39
|
+
Net::SSH.expects(:start).with(@server.host, "jamis", @options.merge(:password => "f4b13n", :auth_methods => %w(password keyboard-interactive))).returns(success = Object.new)
|
40
40
|
assert_equal success, Capistrano::SSH.connect(@server, :user => "jamis", :password => "f4b13n")
|
41
41
|
end
|
42
42
|
|
43
43
|
def test_connect_with_bare_server_with_explicit_port_should_pass_port_to_net_ssh
|
44
|
-
Net::SSH.expects(:start).with(@server.host, @options.merge(:port => 1234)).returns(success = Object.new)
|
44
|
+
Net::SSH.expects(:start).with(@server.host, "default-user", @options.merge(:port => 1234)).returns(success = Object.new)
|
45
45
|
assert_equal success, Capistrano::SSH.connect(@server, :port => 1234)
|
46
46
|
end
|
47
47
|
|
48
48
|
def test_connect_with_server_with_user_should_pass_user_to_net_ssh
|
49
49
|
server = server("jamis@capistrano")
|
50
|
-
Net::SSH.expects(:start).with(server.host,
|
50
|
+
Net::SSH.expects(:start).with(server.host, "jamis", @options).returns(success = Object.new)
|
51
51
|
assert_equal success, Capistrano::SSH.connect(server)
|
52
52
|
end
|
53
53
|
|
54
54
|
def test_connect_with_server_with_port_should_pass_port_to_net_ssh
|
55
55
|
server = server("capistrano:1235")
|
56
|
-
Net::SSH.expects(:start).with(server.host, @options.merge(:port => 1235)).returns(success = Object.new)
|
56
|
+
Net::SSH.expects(:start).with(server.host, "default-user", @options.merge(:port => 1235)).returns(success = Object.new)
|
57
57
|
assert_equal success, Capistrano::SSH.connect(server)
|
58
58
|
end
|
59
59
|
|
60
60
|
def test_connect_with_server_with_user_and_port_should_pass_user_and_port_to_net_ssh
|
61
61
|
server = server("jamis@capistrano:1235")
|
62
|
-
Net::SSH.expects(:start).with(server.host, @options.merge(:
|
62
|
+
Net::SSH.expects(:start).with(server.host, "jamis", @options.merge(:port => 1235)).returns(success = Object.new)
|
63
|
+
assert_equal success, Capistrano::SSH.connect(server)
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_connect_with_server_with_other_ssh_options_should_pass_ssh_options_to_net_ssh
|
67
|
+
server = server("jamis@capistrano:1235", :ssh_options => { :keys => %w(some_valid_key), :auth_methods => %w(a_method), :hmac => 'none' })
|
68
|
+
Net::SSH.expects(:start).with(server.host, "jamis", @options.merge(:port => 1235, :keys => %w(some_valid_key), :auth_methods => %w(a_method), :hmac => 'none' )).returns(success = Object.new)
|
63
69
|
assert_equal success, Capistrano::SSH.connect(server)
|
64
70
|
end
|
65
71
|
|
66
72
|
def test_connect_with_ssh_options_should_use_ssh_options
|
67
73
|
ssh_options = { :username => "JamisMan", :port => 8125 }
|
68
|
-
Net::SSH.expects(:start).with(@server.host, @options.merge(:
|
74
|
+
Net::SSH.expects(:start).with(@server.host, "JamisMan", @options.merge(:port => 8125)).returns(success = Object.new)
|
69
75
|
assert_equal success, Capistrano::SSH.connect(@server, {:ssh_options => ssh_options})
|
70
76
|
end
|
71
77
|
|
72
78
|
def test_connect_with_options_and_ssh_options_should_see_options_override_ssh_options
|
73
79
|
ssh_options = { :username => "JamisMan", :port => 8125, :forward_agent => true }
|
74
|
-
Net::SSH.expects(:start).with(@server.host, @options.merge(:
|
75
|
-
assert_equal success, Capistrano::SSH.connect(@server,
|
80
|
+
Net::SSH.expects(:start).with(@server.host, "jamis", @options.merge(:port => 1235, :forward_agent => true)).returns(success = Object.new)
|
81
|
+
assert_equal success, Capistrano::SSH.connect(@server, :ssh_options => ssh_options, :user => "jamis", :port => 1235)
|
76
82
|
end
|
77
83
|
|
78
84
|
def test_connect_with_ssh_options_should_see_server_options_override_ssh_options
|
79
85
|
ssh_options = { :username => "JamisMan", :port => 8125, :forward_agent => true }
|
80
86
|
server = server("jamis@capistrano:1235")
|
81
|
-
Net::SSH.expects(:start).with(server.host, @options.merge(:
|
87
|
+
Net::SSH.expects(:start).with(server.host, "jamis", @options.merge(:port => 1235, :forward_agent => true)).returns(success = Object.new)
|
82
88
|
assert_equal success, Capistrano::SSH.connect(server, {:ssh_options => ssh_options})
|
83
89
|
end
|
84
90
|
|
85
91
|
def test_connect_should_add_xserver_accessor_to_connection
|
86
|
-
Net::SSH.expects(:start).with(@server.host, @options).returns(success = Object.new)
|
92
|
+
Net::SSH.expects(:start).with(@server.host, "default-user", @options).returns(success = Object.new)
|
87
93
|
assert_equal success, Capistrano::SSH.connect(@server)
|
88
94
|
assert success.respond_to?(:xserver)
|
89
95
|
assert success.respond_to?(:xserver)
|
@@ -91,7 +97,7 @@ class SSHTest < Test::Unit::TestCase
|
|
91
97
|
end
|
92
98
|
|
93
99
|
def test_connect_should_not_retry_if_custom_auth_methods_are_given
|
94
|
-
Net::SSH.expects(:start).with(@server.host, @options.merge(:auth_methods => %w(publickey))).raises(Net::SSH::AuthenticationFailed)
|
100
|
+
Net::SSH.expects(:start).with(@server.host, "default-user", @options.merge(:auth_methods => %w(publickey))).raises(Net::SSH::AuthenticationFailed)
|
95
101
|
assert_raises(Net::SSH::AuthenticationFailed) { Capistrano::SSH.connect(@server, :ssh_options => { :auth_methods => %w(publickey) }) }
|
96
102
|
end
|
97
103
|
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'utils'
|
2
|
+
require 'capistrano/transfer'
|
3
|
+
|
4
|
+
class TransferTest < Test::Unit::TestCase
|
5
|
+
def test_class_process_should_delegate_to_instance_process
|
6
|
+
Capistrano::Transfer.expects(:new).with(:up, "from", "to", %w(a b c), {}).returns(mock('transfer', :process! => nil)).yields
|
7
|
+
yielded = false
|
8
|
+
Capistrano::Transfer.process(:up, "from", "to", %w(a b c), {}) { yielded = true }
|
9
|
+
assert yielded
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_default_transport_is_sftp
|
13
|
+
transfer = Capistrano::Transfer.new(:up, "from", "to", [])
|
14
|
+
assert_equal :sftp, transfer.transport
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_active_is_true_when_any_sftp_transfers_are_active
|
18
|
+
returns = [false, false, true]
|
19
|
+
sessions = [session('app1', :sftp), session('app2', :sftp), session('app3', :sftp)].each { |s| s.xsftp.expects(:upload).returns(stub('operation', :active? => returns.shift)) }
|
20
|
+
transfer = Capistrano::Transfer.new(:up, "from", "to", sessions, :via => :sftp)
|
21
|
+
assert_equal true, transfer.active?
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_active_is_false_when_all_sftp_transfers_are_not_active
|
25
|
+
sessions = [session('app1', :sftp), session('app2', :sftp)].each { |s| s.xsftp.expects(:upload).returns(stub('operation', :active? => false)) }
|
26
|
+
transfer = Capistrano::Transfer.new(:up, "from", "to", sessions, :via => :sftp)
|
27
|
+
assert_equal false, transfer.active?
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_active_is_true_when_any_scp_transfers_are_active
|
31
|
+
returns = [false, false, true]
|
32
|
+
sessions = [session('app1', :scp), session('app2', :scp), session('app3', :scp)].each do |s|
|
33
|
+
channel = stub('channel', :[]= => nil, :active? => returns.shift)
|
34
|
+
s.scp.expects(:upload).returns(channel)
|
35
|
+
end
|
36
|
+
transfer = Capistrano::Transfer.new(:up, "from", "to", sessions, :via => :scp)
|
37
|
+
assert_equal true, transfer.active?
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_active_is_false_when_all_scp_transfers_are_not_active
|
41
|
+
sessions = [session('app1', :scp), session('app2', :scp), session('app3', :scp)].each do |s|
|
42
|
+
channel = stub('channel', :[]= => nil, :active? => false)
|
43
|
+
s.scp.expects(:upload).returns(channel)
|
44
|
+
end
|
45
|
+
transfer = Capistrano::Transfer.new(:up, "from", "to", sessions, :via => :scp)
|
46
|
+
assert_equal false, transfer.active?
|
47
|
+
end
|
48
|
+
|
49
|
+
[:up, :down].each do |direction|
|
50
|
+
define_method("test_sftp_#{direction}load_from_file_to_file_should_normalize_from_and_to") do
|
51
|
+
sessions = [session('app1', :sftp), session('app2', :sftp)]
|
52
|
+
|
53
|
+
sessions.each do |session|
|
54
|
+
session.xsftp.expects("#{direction}load".to_sym).with("from-#{session.xserver.host}", "to-#{session.xserver.host}",
|
55
|
+
:properties => { :server => session.xserver, :host => session.xserver.host })
|
56
|
+
end
|
57
|
+
|
58
|
+
transfer = Capistrano::Transfer.new(direction, "from-$CAPISTRANO:HOST$", "to-$CAPISTRANO:HOST$", sessions)
|
59
|
+
end
|
60
|
+
|
61
|
+
define_method("test_scp_#{direction}load_from_file_to_file_should_normalize_from_and_to") do
|
62
|
+
sessions = [session('app1', :scp), session('app2', :scp)]
|
63
|
+
|
64
|
+
sessions.each do |session|
|
65
|
+
session.scp.expects("#{direction}load".to_sym).returns({}).with("from-#{session.xserver.host}", "to-#{session.xserver.host}", :via => :scp)
|
66
|
+
end
|
67
|
+
|
68
|
+
transfer = Capistrano::Transfer.new(direction, "from-$CAPISTRANO:HOST$", "to-$CAPISTRANO:HOST$", sessions, :via => :scp)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_sftp_upload_from_IO_to_file_should_clone_the_IO_for_each_connection
|
73
|
+
sessions = [session('app1', :sftp), session('app2', :sftp)]
|
74
|
+
io = StringIO.new("from here")
|
75
|
+
|
76
|
+
sessions.each do |session|
|
77
|
+
session.xsftp.expects(:upload).with do |from, to, opts|
|
78
|
+
from != io && from.is_a?(StringIO) && from.string == io.string &&
|
79
|
+
to == "/to/here-#{session.xserver.host}" &&
|
80
|
+
opts[:properties][:server] == session.xserver &&
|
81
|
+
opts[:properties][:host] == session.xserver.host
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
transfer = Capistrano::Transfer.new(:up, StringIO.new("from here"), "/to/here-$CAPISTRANO:HOST$", sessions)
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_scp_upload_from_IO_to_file_should_clone_the_IO_for_each_connection
|
89
|
+
sessions = [session('app1', :scp), session('app2', :scp)]
|
90
|
+
io = StringIO.new("from here")
|
91
|
+
|
92
|
+
sessions.each do |session|
|
93
|
+
channel = mock('channel')
|
94
|
+
channel.expects(:[]=).with(:server, session.xserver)
|
95
|
+
channel.expects(:[]=).with(:host, session.xserver.host)
|
96
|
+
session.scp.expects(:upload).returns(channel).with do |from, to, opts|
|
97
|
+
from != io && from.is_a?(StringIO) && from.string == io.string &&
|
98
|
+
to == "/to/here-#{session.xserver.host}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
transfer = Capistrano::Transfer.new(:up, StringIO.new("from here"), "/to/here-$CAPISTRANO:HOST$", sessions, :via => :scp)
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_process_should_block_until_transfer_is_no_longer_active
|
106
|
+
transfer = Capistrano::Transfer.new(:up, "from", "to", [])
|
107
|
+
transfer.expects(:process_iteration).times(4).yields.returns(true,true,true,false)
|
108
|
+
transfer.expects(:active?).times(4)
|
109
|
+
transfer.process!
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_errors_raised_for_a_sftp_session_should_abort_session_and_continue_with_remaining_sessions
|
113
|
+
s = session('app1')
|
114
|
+
error = ExceptionWithSession.new(s)
|
115
|
+
transfer = Capistrano::Transfer.new(:up, "from", "to", [])
|
116
|
+
transfer.expects(:process_iteration).raises(error).times(3).returns(true, false)
|
117
|
+
txfr = mock('transfer', :abort! => true)
|
118
|
+
txfr.expects(:[]=).with(:failed, true)
|
119
|
+
txfr.expects(:[]=).with(:error, error)
|
120
|
+
transfer.expects(:session_map).returns(s => txfr)
|
121
|
+
transfer.process!
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_errors_raised_for_a_scp_session_should_abort_session_and_continue_with_remaining_sessions
|
125
|
+
s = session('app1')
|
126
|
+
error = ExceptionWithSession.new(s)
|
127
|
+
transfer = Capistrano::Transfer.new(:up, "from", "to", [], :via => :scp)
|
128
|
+
transfer.expects(:process_iteration).raises(error).times(3).returns(true, false)
|
129
|
+
txfr = mock('channel', :close => true)
|
130
|
+
txfr.expects(:[]=).with(:failed, true)
|
131
|
+
txfr.expects(:[]=).with(:error, error)
|
132
|
+
transfer.expects(:session_map).returns(s => txfr)
|
133
|
+
transfer.process!
|
134
|
+
end
|
135
|
+
|
136
|
+
private
|
137
|
+
|
138
|
+
class ExceptionWithSession < ::Exception
|
139
|
+
attr_reader :session
|
140
|
+
|
141
|
+
def initialize(session)
|
142
|
+
@session = session
|
143
|
+
super()
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def session(host, mode=nil)
|
148
|
+
session = stub('session', :xserver => stub('server', :host => host))
|
149
|
+
case mode
|
150
|
+
when :sftp
|
151
|
+
sftp = stub('sftp')
|
152
|
+
session.expects(:sftp).with(false).returns(sftp)
|
153
|
+
sftp.expects(:connect).yields(sftp).returns(sftp)
|
154
|
+
session.stubs(:xsftp).returns(sftp)
|
155
|
+
when :scp
|
156
|
+
session.stubs(:scp).returns(stub('scp'))
|
157
|
+
end
|
158
|
+
session
|
159
|
+
end
|
160
|
+
end
|
data/test/utils.rb
CHANGED
@@ -1,42 +1,38 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
gem 'mocha'
|
7
|
-
rescue LoadError
|
8
|
-
end
|
9
|
-
|
10
|
-
require 'test/unit'
|
11
|
-
require 'mocha'
|
12
|
-
require 'capistrano/server_definition'
|
1
|
+
begin
|
2
|
+
require 'rubygems'
|
3
|
+
gem 'mocha'
|
4
|
+
rescue LoadError
|
5
|
+
end
|
13
6
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
7
|
+
require 'test/unit'
|
8
|
+
require 'mocha'
|
9
|
+
require 'capistrano/server_definition'
|
18
10
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
11
|
+
module TestExtensions
|
12
|
+
def server(host, options={})
|
13
|
+
Capistrano::ServerDefinition.new(host, options)
|
14
|
+
end
|
24
15
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
16
|
+
def namespace(fqn=nil)
|
17
|
+
space = stub(:roles => {}, :fully_qualified_name => fqn, :default_task => nil)
|
18
|
+
yield(space) if block_given?
|
19
|
+
space
|
20
|
+
end
|
30
21
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
return task
|
36
|
-
end
|
22
|
+
def role(space, name, *args)
|
23
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
24
|
+
space.roles[name] ||= []
|
25
|
+
space.roles[name].concat(args.map { |h| Capistrano::ServerDefinition.new(h, opts) })
|
37
26
|
end
|
38
27
|
|
39
|
-
|
40
|
-
|
28
|
+
def new_task(name, namespace=@namespace, options={}, &block)
|
29
|
+
block ||= Proc.new {}
|
30
|
+
task = Capistrano::TaskDefinition.new(name, namespace, options, &block)
|
31
|
+
assert_equal block, task.body
|
32
|
+
return task
|
41
33
|
end
|
42
34
|
end
|
35
|
+
|
36
|
+
class Test::Unit::TestCase
|
37
|
+
include TestExtensions
|
38
|
+
end
|
data/test/version_test.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capistrano
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jamis Buck
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-02
|
12
|
+
date: 2008-05-02 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -19,10 +19,7 @@ dependencies:
|
|
19
19
|
requirements:
|
20
20
|
- - ">="
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version:
|
23
|
-
- - <
|
24
|
-
- !ruby/object:Gem::Version
|
25
|
-
version: 1.99.0
|
22
|
+
version: 2.0.0
|
26
23
|
version:
|
27
24
|
- !ruby/object:Gem::Dependency
|
28
25
|
name: net-sftp
|
@@ -31,10 +28,25 @@ dependencies:
|
|
31
28
|
requirements:
|
32
29
|
- - ">="
|
33
30
|
- !ruby/object:Gem::Version
|
34
|
-
version:
|
35
|
-
|
31
|
+
version: 2.0.0
|
32
|
+
version:
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: net-scp
|
35
|
+
version_requirement:
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.0.0
|
41
|
+
version:
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: net-ssh-gateway
|
44
|
+
version_requirement:
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
36
48
|
- !ruby/object:Gem::Version
|
37
|
-
version: 1.
|
49
|
+
version: 1.0.0
|
38
50
|
version:
|
39
51
|
- !ruby/object:Gem::Dependency
|
40
52
|
name: highline
|
@@ -83,8 +95,8 @@ files:
|
|
83
95
|
- lib/capistrano/configuration.rb
|
84
96
|
- lib/capistrano/errors.rb
|
85
97
|
- lib/capistrano/extensions.rb
|
86
|
-
- lib/capistrano/gateway.rb
|
87
98
|
- lib/capistrano/logger.rb
|
99
|
+
- lib/capistrano/processable.rb
|
88
100
|
- lib/capistrano/recipes
|
89
101
|
- lib/capistrano/recipes/compat.rb
|
90
102
|
- lib/capistrano/recipes/deploy
|
@@ -99,6 +111,7 @@ files:
|
|
99
111
|
- lib/capistrano/recipes/deploy/scm/darcs.rb
|
100
112
|
- lib/capistrano/recipes/deploy/scm/git.rb
|
101
113
|
- lib/capistrano/recipes/deploy/scm/mercurial.rb
|
114
|
+
- lib/capistrano/recipes/deploy/scm/none.rb
|
102
115
|
- lib/capistrano/recipes/deploy/scm/perforce.rb
|
103
116
|
- lib/capistrano/recipes/deploy/scm/subversion.rb
|
104
117
|
- lib/capistrano/recipes/deploy/scm.rb
|
@@ -122,7 +135,7 @@ files:
|
|
122
135
|
- lib/capistrano/shell.rb
|
123
136
|
- lib/capistrano/ssh.rb
|
124
137
|
- lib/capistrano/task_definition.rb
|
125
|
-
- lib/capistrano/
|
138
|
+
- lib/capistrano/transfer.rb
|
126
139
|
- lib/capistrano/version.rb
|
127
140
|
- lib/capistrano.rb
|
128
141
|
- examples/sample.rb
|
@@ -160,13 +173,12 @@ files:
|
|
160
173
|
- test/fixtures/cli_integration.rb
|
161
174
|
- test/fixtures/config.rb
|
162
175
|
- test/fixtures/custom.rb
|
163
|
-
- test/gateway_test.rb
|
164
176
|
- test/logger_test.rb
|
165
177
|
- test/server_definition_test.rb
|
166
178
|
- test/shell_test.rb
|
167
179
|
- test/ssh_test.rb
|
168
180
|
- test/task_definition_test.rb
|
169
|
-
- test/
|
181
|
+
- test/transfer_test.rb
|
170
182
|
- test/utils.rb
|
171
183
|
- test/version_test.rb
|
172
184
|
- README
|
@@ -194,7 +206,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
194
206
|
requirements: []
|
195
207
|
|
196
208
|
rubyforge_project: capistrano
|
197
|
-
rubygems_version: 1.
|
209
|
+
rubygems_version: 1.1.1
|
198
210
|
signing_key:
|
199
211
|
specification_version: 2
|
200
212
|
summary: Capistrano is a utility and framework for executing commands in parallel on multiple remote machines, via SSH.
|
data/lib/capistrano/gateway.rb
DELETED
@@ -1,131 +0,0 @@
|
|
1
|
-
if RUBY_VERSION == "1.8.6"
|
2
|
-
begin
|
3
|
-
require 'fastthread'
|
4
|
-
rescue LoadError
|
5
|
-
warn "You are running Ruby 1.8.6, which has a bug in its threading implementation."
|
6
|
-
warn "You are liable to encounter deadlocks running Capistrano, unless you install"
|
7
|
-
warn "the fastthread library, which is available as a gem:"
|
8
|
-
warn " gem install fastthread"
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
require 'thread'
|
13
|
-
require 'capistrano/errors'
|
14
|
-
require 'capistrano/ssh'
|
15
|
-
require 'capistrano/server_definition'
|
16
|
-
|
17
|
-
Thread.abort_on_exception = true
|
18
|
-
|
19
|
-
module Capistrano
|
20
|
-
|
21
|
-
# Black magic. It uses threads and Net::SSH to set up a connection to a
|
22
|
-
# gateway server, through which connections to other servers may be
|
23
|
-
# tunnelled.
|
24
|
-
#
|
25
|
-
# It is used internally by Capistrano, but may be useful on its own, as well.
|
26
|
-
#
|
27
|
-
# Usage:
|
28
|
-
#
|
29
|
-
# gateway = Capistrano::Gateway.new(Capistrano::ServerDefinition.new('gateway.example.com'))
|
30
|
-
#
|
31
|
-
# sess1 = gateway.connect_to(Capistrano::ServerDefinition.new('hidden.example.com'))
|
32
|
-
# sess2 = gateway.connect_to(Capistrano::ServerDefinition.new('other.example.com'))
|
33
|
-
class Gateway
|
34
|
-
# The Thread instance driving the gateway connection.
|
35
|
-
attr_reader :thread
|
36
|
-
|
37
|
-
# The Net::SSH session representing the gateway connection.
|
38
|
-
attr_reader :session
|
39
|
-
|
40
|
-
MAX_PORT = 65535
|
41
|
-
MIN_PORT = 1024
|
42
|
-
|
43
|
-
def initialize(server, options={}) #:nodoc:
|
44
|
-
@options = options
|
45
|
-
@next_port = MAX_PORT
|
46
|
-
@terminate_thread = false
|
47
|
-
@port_guard = Mutex.new
|
48
|
-
|
49
|
-
mutex = Mutex.new
|
50
|
-
waiter = ConditionVariable.new
|
51
|
-
|
52
|
-
mutex.synchronize do
|
53
|
-
@thread = Thread.new do
|
54
|
-
logger.trace "starting connection to gateway `#{server}'" if logger
|
55
|
-
SSH.connect(server, @options) do |@session|
|
56
|
-
logger.trace "gateway connection established" if logger
|
57
|
-
mutex.synchronize { waiter.signal }
|
58
|
-
@session.loop do
|
59
|
-
!@terminate_thread
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
waiter.wait(mutex)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
# Shuts down all forwarded connections and terminates the gateway.
|
69
|
-
def shutdown!
|
70
|
-
# cancel all active forward channels
|
71
|
-
session.forward.active_locals.each do |lport, host, port|
|
72
|
-
session.forward.cancel_local(lport)
|
73
|
-
end
|
74
|
-
|
75
|
-
# terminate the gateway thread
|
76
|
-
@terminate_thread = true
|
77
|
-
|
78
|
-
# wait for the gateway thread to stop
|
79
|
-
thread.join
|
80
|
-
end
|
81
|
-
|
82
|
-
# Connects to the given server by opening a forwarded port from the local
|
83
|
-
# host to the server, via the gateway, and then opens and returns a new
|
84
|
-
# Net::SSH connection via that port.
|
85
|
-
def connect_to(server)
|
86
|
-
connection = nil
|
87
|
-
logger.debug "establishing connection to `#{server}' via gateway" if logger
|
88
|
-
local_port = next_port
|
89
|
-
|
90
|
-
thread = Thread.new do
|
91
|
-
begin
|
92
|
-
local_host = ServerDefinition.new("127.0.0.1", :user => server.user, :port => local_port)
|
93
|
-
session.forward.local(local_port, server.host, server.port || 22)
|
94
|
-
connection = SSH.connect(local_host, @options)
|
95
|
-
connection.xserver = server
|
96
|
-
logger.trace "connected: `#{server}' (via gateway)" if logger
|
97
|
-
rescue Errno::EADDRINUSE
|
98
|
-
local_port = next_port
|
99
|
-
retry
|
100
|
-
rescue Exception => e
|
101
|
-
warn "#{e.class}: #{e.message}"
|
102
|
-
warn e.backtrace.join("\n")
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
thread.join
|
107
|
-
if connection.nil?
|
108
|
-
error = ConnectionError.new("could not establish connection to `#{server}'")
|
109
|
-
error.hosts = [server]
|
110
|
-
raise error
|
111
|
-
end
|
112
|
-
|
113
|
-
connection
|
114
|
-
end
|
115
|
-
|
116
|
-
private
|
117
|
-
|
118
|
-
def logger
|
119
|
-
@options[:logger]
|
120
|
-
end
|
121
|
-
|
122
|
-
def next_port
|
123
|
-
@port_guard.synchronize do
|
124
|
-
port = @next_port
|
125
|
-
@next_port -= 1
|
126
|
-
@next_port = MAX_PORT if @next_port < MIN_PORT
|
127
|
-
port
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|