switchtower 0.10.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/switchtower/actor.rb +51 -20
- data/lib/switchtower/cli.rb +1 -1
- data/lib/switchtower/command.rb +1 -2
- data/lib/switchtower/configuration.rb +49 -7
- data/lib/switchtower/extensions.rb +38 -0
- data/lib/switchtower/gateway.rb +15 -3
- data/lib/switchtower/generators/rails/deployment/templates/switchtower.rake +6 -2
- data/lib/switchtower/logger.rb +8 -5
- data/lib/switchtower/recipes/standard.rb +49 -10
- data/lib/switchtower/scm/base.rb +2 -2
- data/lib/switchtower/scm/baz.rb +118 -0
- data/lib/switchtower/scm/bzr.rb +70 -0
- data/lib/switchtower/scm/cvs.rb +57 -6
- data/lib/switchtower/scm/perforce.rb +139 -0
- data/lib/switchtower/scm/subversion.rb +8 -3
- data/lib/switchtower/transfer.rb +1 -1
- data/lib/switchtower/utils.rb +26 -0
- data/lib/switchtower/version.rb +3 -3
- data/test/actor_test.rb +34 -1
- data/test/configuration_test.rb +16 -1
- data/test/fixtures/custom.rb +3 -0
- data/test/scm/cvs_test.rb +24 -2
- data/test/scm/subversion_test.rb +17 -2
- data/test/utils.rb +8 -0
- metadata +9 -3
data/lib/switchtower/transfer.rb
CHANGED
@@ -58,7 +58,7 @@ module SwitchTower
|
|
58
58
|
sftp = @actor.sessions[server].sftp
|
59
59
|
sftp.connect unless sftp.state == :open
|
60
60
|
|
61
|
-
sftp.open(@filename, IO::WRONLY | IO::CREAT, @params[:mode] || 0660) do |status, handle|
|
61
|
+
sftp.open(@filename, IO::WRONLY | IO::CREAT | IO::TRUNC, @params[:mode] || 0660) do |status, handle|
|
62
62
|
break unless check_status("open #{@filename}", server, status)
|
63
63
|
|
64
64
|
logger.info "uploading data to #{server}:#{@filename}"
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module SwitchTower
|
2
|
+
# A helper method for converting a comma-delimited string into an array of
|
3
|
+
# roles.
|
4
|
+
def self.str2roles(string)
|
5
|
+
list = string.split(/,/).map { |s| s.strip.to_sym }
|
6
|
+
list.empty? ? nil : list
|
7
|
+
end
|
8
|
+
|
9
|
+
# Used by third-party task bundles to identify the switchtower configuration
|
10
|
+
# that is loading them. It's return value is not reliable in other contexts.
|
11
|
+
# If +require_config+ is not false, an exception will be raised if the current
|
12
|
+
# configuration is not set.
|
13
|
+
def self.configuration(require_config=false)
|
14
|
+
config = Thread.current[:switchtower_configuration]
|
15
|
+
if require_config && config.nil?
|
16
|
+
raise "Please require this file from within a SwitchTower recipe"
|
17
|
+
end
|
18
|
+
config
|
19
|
+
end
|
20
|
+
|
21
|
+
# Used internally by SwitchTower to specify the current configuration before
|
22
|
+
# loading a third-party task bundle.
|
23
|
+
def self.configuration=(config)
|
24
|
+
Thread.current[:switchtower_configuration] = config
|
25
|
+
end
|
26
|
+
end
|
data/lib/switchtower/version.rb
CHANGED
@@ -18,13 +18,13 @@ module SwitchTower
|
|
18
18
|
good
|
19
19
|
end
|
20
20
|
|
21
|
-
MAJOR =
|
22
|
-
MINOR =
|
21
|
+
MAJOR = 1
|
22
|
+
MINOR = 0
|
23
23
|
TINY = 0
|
24
24
|
|
25
25
|
STRING = [MAJOR, MINOR, TINY].join(".")
|
26
26
|
|
27
|
-
SSH_REQUIRED = [1,0,
|
27
|
+
SSH_REQUIRED = [1,0,8]
|
28
28
|
SFTP_REQUIRED = [1,1,0]
|
29
29
|
end
|
30
30
|
end
|
data/test/actor_test.rb
CHANGED
@@ -4,6 +4,7 @@ require 'stringio'
|
|
4
4
|
require 'test/unit'
|
5
5
|
require 'switchtower/actor'
|
6
6
|
require 'switchtower/logger'
|
7
|
+
require 'switchtower/configuration'
|
7
8
|
|
8
9
|
class ActorTest < Test::Unit::TestCase
|
9
10
|
|
@@ -83,6 +84,12 @@ class ActorTest < Test::Unit::TestCase
|
|
83
84
|
end
|
84
85
|
end
|
85
86
|
|
87
|
+
module CustomExtension
|
88
|
+
def do_something_extra(a, b, c)
|
89
|
+
run "echo '#{a} :: #{b} :: #{c}'"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
86
93
|
def setup
|
87
94
|
TestingCommand.reset!
|
88
95
|
@actor = TestActor.new(MockConfiguration.new)
|
@@ -162,7 +169,7 @@ class ActorTest < Test::Unit::TestCase
|
|
162
169
|
run "do this"
|
163
170
|
end
|
164
171
|
|
165
|
-
assert_equal %w(01.example.com 02.example.com 03.example.com 04.example.com 05.example.com 06.example.com 07.example.com all.example.com), @actor.tasks[:foo].servers
|
172
|
+
assert_equal %w(01.example.com 02.example.com 03.example.com 04.example.com 05.example.com 06.example.com 07.example.com all.example.com), @actor.tasks[:foo].servers.sort
|
166
173
|
end
|
167
174
|
|
168
175
|
def test_run_in_task_without_explicit_roles_selects_all_roles
|
@@ -258,4 +265,30 @@ class ActorTest < Test::Unit::TestCase
|
|
258
265
|
@actor.foo
|
259
266
|
assert_equal %w(foo after_foo), history
|
260
267
|
end
|
268
|
+
|
269
|
+
def test_uppercase_variables
|
270
|
+
config = SwitchTower::Configuration.new(TestActor)
|
271
|
+
config.set :HELLO, "world"
|
272
|
+
assert_equal "world", config.actor.instance_eval("HELLO")
|
273
|
+
config.set :HELLO, "test"
|
274
|
+
assert_equal "test", config.actor.instance_eval("HELLO")
|
275
|
+
end
|
276
|
+
|
277
|
+
def test_connect_when_no_matching_servers
|
278
|
+
@actor.define_task :foo, :roles => :db, :only => { :fnoofy => true } do
|
279
|
+
run "do this"
|
280
|
+
end
|
281
|
+
|
282
|
+
assert_raises(RuntimeError) { @actor.foo }
|
283
|
+
end
|
284
|
+
|
285
|
+
def test_custom_extension
|
286
|
+
assert SwitchTower.plugin(:custom, CustomExtension)
|
287
|
+
@actor.define_task :foo, :roles => :db do
|
288
|
+
custom.do_something_extra(1, 2, 3)
|
289
|
+
end
|
290
|
+
assert_nothing_raised { @actor.foo }
|
291
|
+
assert TestingCommand.invoked?
|
292
|
+
assert SwitchTower.remove_plugin(:custom)
|
293
|
+
end
|
261
294
|
end
|
data/test/configuration_test.rb
CHANGED
@@ -125,6 +125,16 @@ class ConfigurationTest < Test::Unit::TestCase
|
|
125
125
|
assert_equal 1, @config.roles[:web].length
|
126
126
|
end
|
127
127
|
|
128
|
+
def test_load_proc_explicit
|
129
|
+
@config.load :proc => Proc.new { set :gateway, "nifty.zoo.test" }
|
130
|
+
assert_equal "nifty.zoo.test", @config.gateway
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_load_proc_implicit
|
134
|
+
@config.load { set :gateway, "nifty.zoo.test" }
|
135
|
+
assert_equal "nifty.zoo.test", @config.gateway
|
136
|
+
end
|
137
|
+
|
128
138
|
def test_task_without_options
|
129
139
|
block = Proc.new { }
|
130
140
|
@config.task :hello, &block
|
@@ -209,10 +219,15 @@ class ConfigurationTest < Test::Unit::TestCase
|
|
209
219
|
end
|
210
220
|
|
211
221
|
def test_get_proc_variable_sets_original_value_hash
|
212
|
-
@config.set
|
222
|
+
@config.set(:proc) { "foo" }
|
213
223
|
assert_nil @config[:original_value][:proc]
|
214
224
|
assert_equal "foo", @config[:proc]
|
215
225
|
assert_not_nil @config[:original_value][:proc]
|
216
226
|
assert @config[:original_value][:proc].respond_to?(:call)
|
217
227
|
end
|
228
|
+
|
229
|
+
def test_require
|
230
|
+
@config.require "#{File.dirname(__FILE__)}/fixtures/custom"
|
231
|
+
assert_equal "foo", @config.gateway
|
232
|
+
end
|
218
233
|
end
|
data/test/scm/cvs_test.rb
CHANGED
@@ -9,10 +9,15 @@ class ScmCvsTest < Test::Unit::TestCase
|
|
9
9
|
attr_accessor :story
|
10
10
|
attr_reader :last_path
|
11
11
|
|
12
|
-
def cvs_log(path)
|
12
|
+
def cvs_log(path,branch)
|
13
13
|
@last_path = path
|
14
14
|
story.shift
|
15
15
|
end
|
16
|
+
|
17
|
+
def cvs_branch(path)
|
18
|
+
"deploy-me"
|
19
|
+
end
|
20
|
+
|
16
21
|
end
|
17
22
|
|
18
23
|
class MockChannel
|
@@ -56,7 +61,6 @@ class ScmCvsTest < Test::Unit::TestCase
|
|
56
61
|
def setup
|
57
62
|
@config = MockConfiguration.new
|
58
63
|
@config[:repository] = ":ext:joetester@rubyforge.org:/hello/world"
|
59
|
-
@config[:local] = "/hello/world"
|
60
64
|
@config[:cvs] = "/path/to/cvs"
|
61
65
|
@config[:password] = "chocolatebrownies"
|
62
66
|
@config[:now] = Time.utc(2005,8,24,12,0,0)
|
@@ -144,11 +148,19 @@ MSG
|
|
144
148
|
end
|
145
149
|
|
146
150
|
def test_latest_revision
|
151
|
+
@config[:local] = "/hello/world"
|
147
152
|
@scm.story = [ @log_msg ]
|
148
153
|
assert_equal "2004-10-12 02:21:02", @scm.latest_revision
|
149
154
|
assert_equal "/hello/world", @scm.last_path
|
150
155
|
end
|
151
156
|
|
157
|
+
def test_latest_with_default_local
|
158
|
+
@config[:local] = nil
|
159
|
+
@scm.story = [ @log_msg ]
|
160
|
+
assert_equal "2004-10-12 02:21:02", @scm.latest_revision
|
161
|
+
assert_equal ".", @scm.last_path
|
162
|
+
end
|
163
|
+
|
152
164
|
def test_checkout
|
153
165
|
@actor.story = []
|
154
166
|
assert_nothing_raised { @scm.checkout(@actor) }
|
@@ -161,4 +173,14 @@ MSG
|
|
161
173
|
assert_nothing_raised { @scm.checkout(@actor) }
|
162
174
|
assert_equal ["chocolatebrownies\n"], @actor.channels.last.sent_data
|
163
175
|
end
|
176
|
+
|
177
|
+
def test_current_branch
|
178
|
+
assert_equal "deploy-me", @scm.current_branch
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_default_current_branch
|
182
|
+
@config[:branch] = "default-branch"
|
183
|
+
@scm = CvsTest.new(@config)
|
184
|
+
assert_equal "default-branch", @scm.current_branch
|
185
|
+
end
|
164
186
|
end
|
data/test/scm/subversion_test.rb
CHANGED
@@ -84,7 +84,7 @@ MSG
|
|
84
84
|
@actor.story = []
|
85
85
|
assert_nothing_raised { @scm.checkout(@actor) }
|
86
86
|
assert_nil @actor.channels.last.sent_data
|
87
|
-
assert_match %r{/path/to/svn}, @actor.command
|
87
|
+
assert_match %r{/path/to/svn co\s+-q}, @actor.command
|
88
88
|
end
|
89
89
|
|
90
90
|
def test_checkout_via_export
|
@@ -92,7 +92,7 @@ MSG
|
|
92
92
|
@config[:checkout] = "export"
|
93
93
|
assert_nothing_raised { @scm.checkout(@actor) }
|
94
94
|
assert_nil @actor.channels.last.sent_data
|
95
|
-
assert_match %r{/path/to/svn export}, @actor.command
|
95
|
+
assert_match %r{/path/to/svn export\s+-q}, @actor.command
|
96
96
|
end
|
97
97
|
|
98
98
|
def test_update
|
@@ -119,4 +119,19 @@ MSG
|
|
119
119
|
assert_nothing_raised { @scm.checkout(@actor) }
|
120
120
|
assert_equal ["chocolatebrownies\n"], @actor.channels.last.sent_data
|
121
121
|
end
|
122
|
+
|
123
|
+
def test_svn_password
|
124
|
+
@config[:svn_password] = "butterscotchcandies"
|
125
|
+
@actor.story = [[:out, "Password: "]]
|
126
|
+
assert_nothing_raised { @scm.checkout(@actor) }
|
127
|
+
assert_equal ["butterscotchcandies\n"], @actor.channels.last.sent_data
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_svn_username
|
131
|
+
@actor.story = []
|
132
|
+
@config[:svn_username] = "turtledove"
|
133
|
+
assert_nothing_raised { @scm.checkout(@actor) }
|
134
|
+
assert_nil @actor.channels.last.sent_data
|
135
|
+
assert_match %r{/path/to/svn co --username turtledove}, @actor.command
|
136
|
+
end
|
122
137
|
end
|
data/test/utils.rb
CHANGED
@@ -32,6 +32,14 @@ class MockConfiguration < Hash
|
|
32
32
|
@logger ||= MockLogger.new
|
33
33
|
end
|
34
34
|
|
35
|
+
def set(variable, value=nil, &block)
|
36
|
+
self[variable] = value
|
37
|
+
end
|
38
|
+
|
39
|
+
def respond_to?(sym)
|
40
|
+
self.has_key?(sym)
|
41
|
+
end
|
42
|
+
|
35
43
|
def method_missing(sym, *args)
|
36
44
|
if args.length == 0
|
37
45
|
self[sym]
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: switchtower
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2006-
|
6
|
+
version: 1.0.0
|
7
|
+
date: 2006-02-18 00:00:00 -07:00
|
8
8
|
summary: "SwitchTower is a framework and utility for executing commands in parallel on
|
9
9
|
multiple remote machines, via SSH. The primary goal is to simplify and
|
10
10
|
automate the deployment of web applications."
|
@@ -38,6 +38,7 @@ files:
|
|
38
38
|
- lib/switchtower/cli.rb
|
39
39
|
- lib/switchtower/command.rb
|
40
40
|
- lib/switchtower/configuration.rb
|
41
|
+
- lib/switchtower/extensions.rb
|
41
42
|
- lib/switchtower/gateway.rb
|
42
43
|
- lib/switchtower/generators
|
43
44
|
- lib/switchtower/logger.rb
|
@@ -45,6 +46,7 @@ files:
|
|
45
46
|
- lib/switchtower/scm
|
46
47
|
- lib/switchtower/ssh.rb
|
47
48
|
- lib/switchtower/transfer.rb
|
49
|
+
- lib/switchtower/utils.rb
|
48
50
|
- lib/switchtower/version.rb
|
49
51
|
- lib/switchtower/generators/rails
|
50
52
|
- lib/switchtower/generators/rails/deployment
|
@@ -57,8 +59,11 @@ files:
|
|
57
59
|
- lib/switchtower/recipes/templates
|
58
60
|
- lib/switchtower/recipes/templates/maintenance.rhtml
|
59
61
|
- lib/switchtower/scm/base.rb
|
62
|
+
- lib/switchtower/scm/baz.rb
|
63
|
+
- lib/switchtower/scm/bzr.rb
|
60
64
|
- lib/switchtower/scm/cvs.rb
|
61
65
|
- lib/switchtower/scm/darcs.rb
|
66
|
+
- lib/switchtower/scm/perforce.rb
|
62
67
|
- lib/switchtower/scm/subversion.rb
|
63
68
|
- examples/sample.rb
|
64
69
|
- test/actor_test.rb
|
@@ -69,6 +74,7 @@ files:
|
|
69
74
|
- test/ssh_test.rb
|
70
75
|
- test/utils.rb
|
71
76
|
- test/fixtures/config.rb
|
77
|
+
- test/fixtures/custom.rb
|
72
78
|
- test/scm/cvs_test.rb
|
73
79
|
- test/scm/subversion_test.rb
|
74
80
|
test_files: []
|
@@ -87,7 +93,7 @@ dependencies:
|
|
87
93
|
-
|
88
94
|
- ">="
|
89
95
|
- !ruby/object:Gem::Version
|
90
|
-
version: 1.0.
|
96
|
+
version: 1.0.8
|
91
97
|
version:
|
92
98
|
- !ruby/object:Gem::Dependency
|
93
99
|
name: net-sftp
|