switchtower 0.9.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.
@@ -0,0 +1,43 @@
1
+ $:.unshift File.dirname(__FILE__) + "/../lib"
2
+
3
+ require 'stringio'
4
+ require 'test/unit'
5
+ require 'switchtower/command'
6
+
7
+ class CommandTest < Test::Unit::TestCase
8
+ class MockSession
9
+ def open_channel
10
+ { :closed => true, :status => 0 }
11
+ end
12
+ end
13
+
14
+ class MockActor
15
+ attr_reader :sessions
16
+
17
+ def initialize
18
+ @sessions = Hash.new { |h,k| h[k] = MockSession.new }
19
+ end
20
+ end
21
+
22
+ def setup
23
+ @actor = MockActor.new
24
+ end
25
+
26
+ def test_command_executes_on_all_servers
27
+ command = SwitchTower::Command.new(%w(server1 server2 server3),
28
+ "hello", nil, {}, @actor)
29
+ assert_equal %w(server1 server2 server3), @actor.sessions.keys.sort
30
+ end
31
+
32
+ def test_command_with_newlines
33
+ command = SwitchTower::Command.new(%w(server1), "hello\nworld", nil, {},
34
+ @actor)
35
+ assert_equal "hello\\\nworld", command.command
36
+ end
37
+
38
+ def test_command_with_windows_newlines
39
+ command = SwitchTower::Command.new(%w(server1), "hello\r\nworld", nil, {},
40
+ @actor)
41
+ assert_equal "hello\\\nworld", command.command
42
+ end
43
+ end
@@ -0,0 +1,210 @@
1
+ $:.unshift File.dirname(__FILE__) + "/../lib"
2
+
3
+ require 'test/unit'
4
+ require 'switchtower/configuration'
5
+ require 'flexmock'
6
+
7
+ class ConfigurationTest < Test::Unit::TestCase
8
+ class MockActor
9
+ attr_reader :tasks
10
+
11
+ def initialize(config)
12
+ end
13
+
14
+ def define_task(*args, &block)
15
+ (@tasks ||= []).push [args, block].flatten
16
+ end
17
+ end
18
+
19
+ class MockSCM
20
+ attr_reader :configuration
21
+
22
+ def initialize(config)
23
+ @configuration = config
24
+ end
25
+ end
26
+
27
+ def setup
28
+ @config = SwitchTower::Configuration.new(MockActor)
29
+ @config.set :scm, MockSCM
30
+ end
31
+
32
+ def test_version_dir_default
33
+ assert "releases", @config.version_dir
34
+ end
35
+
36
+ def test_current_dir_default
37
+ assert "current", @config.current_dir
38
+ end
39
+
40
+ def test_shared_dir_default
41
+ assert "shared", @config.shared_dir
42
+ end
43
+
44
+ def test_set_repository
45
+ @config.set :repository, "/foo/bar/baz"
46
+ assert_equal "/foo/bar/baz", @config.repository
47
+ end
48
+
49
+ def test_set_user
50
+ @config.set :user, "flippy"
51
+ assert_equal "flippy", @config.user
52
+ end
53
+
54
+ def test_define_single_role
55
+ @config.role :app, "somewhere.example.com"
56
+ assert_equal 1, @config.roles[:app].length
57
+ assert_equal "somewhere.example.com", @config.roles[:app].first.host
58
+ assert_equal Hash.new, @config.roles[:app].first.options
59
+ end
60
+
61
+ def test_define_single_role_with_options
62
+ @config.role :app, "somewhere.example.com", :primary => true
63
+ assert_equal 1, @config.roles[:app].length
64
+ assert_equal "somewhere.example.com", @config.roles[:app].first.host
65
+ assert_equal({:primary => true}, @config.roles[:app].first.options)
66
+ end
67
+
68
+ def test_define_multi_role
69
+ @config.role :app, "somewhere.example.com", "else.example.com"
70
+ assert_equal 2, @config.roles[:app].length
71
+ assert_equal "somewhere.example.com", @config.roles[:app].first.host
72
+ assert_equal "else.example.com", @config.roles[:app].last.host
73
+ assert_equal({}, @config.roles[:app].first.options)
74
+ assert_equal({}, @config.roles[:app].last.options)
75
+ end
76
+
77
+ def test_define_multi_role_with_options
78
+ @config.role :app, "somewhere.example.com", "else.example.com", :primary => true
79
+ assert_equal 2, @config.roles[:app].length
80
+ assert_equal "somewhere.example.com", @config.roles[:app].first.host
81
+ assert_equal "else.example.com", @config.roles[:app].last.host
82
+ assert_equal({:primary => true}, @config.roles[:app].first.options)
83
+ assert_equal({:primary => true}, @config.roles[:app].last.options)
84
+ end
85
+
86
+ def test_load_string_unnamed
87
+ @config.load :string => "set :repository, __FILE__"
88
+ assert_equal "<eval>", @config.repository
89
+ end
90
+
91
+ def test_load_string_named
92
+ @config.load :string => "set :repository, __FILE__", :name => "test.rb"
93
+ assert_equal "test.rb", @config.repository
94
+ end
95
+
96
+ def test_load
97
+ file = File.dirname(__FILE__) + "/fixtures/config.rb"
98
+ @config.load file
99
+ assert_equal "1/2/foo", @config.repository
100
+ assert_equal "./#{file}.example.com", @config.gateway
101
+ assert_equal 1, @config.roles[:web].length
102
+ end
103
+
104
+ def test_load_explicit_name
105
+ file = File.dirname(__FILE__) + "/fixtures/config.rb"
106
+ @config.load file, :name => "config"
107
+ assert_equal "1/2/foo", @config.repository
108
+ assert_equal "config.example.com", @config.gateway
109
+ assert_equal 1, @config.roles[:web].length
110
+ end
111
+
112
+ def test_load_file_implied_name
113
+ file = File.dirname(__FILE__) + "/fixtures/config.rb"
114
+ @config.load :file => file
115
+ assert_equal "1/2/foo", @config.repository
116
+ assert_equal "./#{file}.example.com", @config.gateway
117
+ assert_equal 1, @config.roles[:web].length
118
+ end
119
+
120
+ def test_load_file_explicit_name
121
+ file = File.dirname(__FILE__) + "/fixtures/config.rb"
122
+ @config.load :file => file, :name => "config"
123
+ assert_equal "1/2/foo", @config.repository
124
+ assert_equal "config.example.com", @config.gateway
125
+ assert_equal 1, @config.roles[:web].length
126
+ end
127
+
128
+ def test_task_without_options
129
+ block = Proc.new { }
130
+ @config.task :hello, &block
131
+ assert_equal 1, @config.actor.tasks.length
132
+ assert_equal :hello, @config.actor.tasks[0][0]
133
+ assert_equal({}, @config.actor.tasks[0][1])
134
+ assert_equal block, @config.actor.tasks[0][2]
135
+ end
136
+
137
+ def test_task_with_options
138
+ block = Proc.new { }
139
+ @config.task :hello, :roles => :app, &block
140
+ assert_equal 1, @config.actor.tasks.length
141
+ assert_equal :hello, @config.actor.tasks[0][0]
142
+ assert_equal({:roles => :app}, @config.actor.tasks[0][1])
143
+ assert_equal block, @config.actor.tasks[0][2]
144
+ end
145
+
146
+ def test_source
147
+ @config.set :repository, "/foo/bar/baz"
148
+ assert_equal "/foo/bar/baz", @config.source.configuration.repository
149
+ end
150
+
151
+ def test_releases_path_default
152
+ @config.set :deploy_to, "/start/of/path"
153
+ assert_equal "/start/of/path/releases", @config.releases_path
154
+ end
155
+
156
+ def test_releases_path_custom
157
+ @config.set :deploy_to, "/start/of/path"
158
+ @config.set :version_dir, "right/here"
159
+ assert_equal "/start/of/path/right/here", @config.releases_path
160
+ end
161
+
162
+ def test_current_path_default
163
+ @config.set :deploy_to, "/start/of/path"
164
+ assert_equal "/start/of/path/current", @config.current_path
165
+ end
166
+
167
+ def test_current_path_custom
168
+ @config.set :deploy_to, "/start/of/path"
169
+ @config.set :current_dir, "right/here"
170
+ assert_equal "/start/of/path/right/here", @config.current_path
171
+ end
172
+
173
+ def test_shared_path_default
174
+ @config.set :deploy_to, "/start/of/path"
175
+ assert_equal "/start/of/path/shared", @config.shared_path
176
+ end
177
+
178
+ def test_shared_path_custom
179
+ @config.set :deploy_to, "/start/of/path"
180
+ @config.set :shared_dir, "right/here"
181
+ assert_equal "/start/of/path/right/here", @config.shared_path
182
+ end
183
+
184
+ def test_release_path_implicit
185
+ @config.set :deploy_to, "/start/of/path"
186
+ assert_equal "/start/of/path/releases/#{@config.now.strftime("%Y%m%d%H%M%S")}", @config.release_path
187
+ end
188
+
189
+ def test_release_path_explicit
190
+ @config.set :deploy_to, "/start/of/path"
191
+ assert_equal "/start/of/path/releases/silly", @config.release_path("silly")
192
+ end
193
+
194
+ def test_task_description
195
+ block = Proc.new { }
196
+ @config.desc "A sample task"
197
+ @config.task :hello, &block
198
+ assert_equal "A sample task", @config.actor.tasks[0][1][:desc]
199
+ end
200
+
201
+ def test_set_scm_to_darcs
202
+ @config.set :scm, :darcs
203
+ assert_equal "SwitchTower::SCM::Darcs", @config.source.class.name
204
+ end
205
+
206
+ def test_set_scm_to_subversion
207
+ @config.set :scm, :subversion
208
+ assert_equal "SwitchTower::SCM::Subversion", @config.source.class.name
209
+ end
210
+ end
@@ -0,0 +1,5 @@
1
+ set :application, "foo"
2
+ set :repository, "1/2/#{application}"
3
+ set :gateway, "#{__FILE__}.example.com"
4
+
5
+ role :web, "www.example.com", :primary => true
@@ -0,0 +1,164 @@
1
+ $:.unshift File.dirname(__FILE__) + "/../../lib"
2
+
3
+ require File.dirname(__FILE__) + "/../utils"
4
+ require 'test/unit'
5
+ require 'switchtower/scm/cvs'
6
+
7
+ class ScmCvsTest < Test::Unit::TestCase
8
+ class CvsTest < SwitchTower::SCM::Cvs
9
+ attr_accessor :story
10
+ attr_reader :last_path
11
+
12
+ def cvs_log(path)
13
+ @last_path = path
14
+ story.shift
15
+ end
16
+ end
17
+
18
+ class MockChannel
19
+ attr_reader :sent_data
20
+
21
+ def send_data(data)
22
+ @sent_data ||= []
23
+ @sent_data << data
24
+ end
25
+
26
+ def [](name)
27
+ "value"
28
+ end
29
+ end
30
+
31
+ class MockActor
32
+ attr_reader :command
33
+ attr_reader :channels
34
+ attr_accessor :story
35
+
36
+ def initialize(config)
37
+ @config = config
38
+ end
39
+
40
+ def run(command)
41
+ @command = command
42
+ @channels ||= []
43
+ @channels << MockChannel.new
44
+ story.each { |stream, line| yield @channels.last, stream, line }
45
+ end
46
+
47
+ def release_path
48
+ (@config[:now] || Time.now.utc).strftime("%Y%m%d%H%M%S")
49
+ end
50
+
51
+ def method_missing(sym, *args)
52
+ @config.send(sym, *args)
53
+ end
54
+ end
55
+
56
+ def setup
57
+ @config = MockConfiguration.new
58
+ @config[:repository] = ":ext:joetester@rubyforge.org:/hello/world"
59
+ @config[:local] = "/hello/world"
60
+ @config[:cvs] = "/path/to/cvs"
61
+ @config[:password] = "chocolatebrownies"
62
+ @config[:now] = Time.utc(2005,8,24,12,0,0)
63
+ @scm = CvsTest.new(@config)
64
+ @actor = MockActor.new(@config)
65
+ @log_msg = <<MSG.strip
66
+ RCS file: /var/cvs/copland/copland/LICENSE,v
67
+ Working file: LICENSE
68
+ head: 1.1
69
+ branch:
70
+ locks: strict
71
+ access list:
72
+ keyword substitution: kv
73
+ total revisions: 1; selected revisions: 1
74
+ description:
75
+ ----------------------------
76
+ revision 1.1
77
+ date: 2004/08/29 04:23:36; author: minam; state: Exp;
78
+ New implementation.
79
+ =============================================================================
80
+
81
+ RCS file: /var/cvs/copland/copland/Rakefile,v
82
+ Working file: Rakefile
83
+ head: 1.7
84
+ branch:
85
+ locks: strict
86
+ access list:
87
+ keyword substitution: kv
88
+ total revisions: 7; selected revisions: 1
89
+ description:
90
+ ----------------------------
91
+ revision 1.7
92
+ date: 2004/09/15 16:35:01; author: minam; state: Exp; lines: +2 -1
93
+ Rakefile now publishes package documentation from doc/packages instead of
94
+ doc/packrat. Updated "latest updates" in manual.
95
+ =============================================================================
96
+
97
+ RCS file: /var/cvs/copland/copland/TODO,v
98
+ Working file: TODO
99
+ head: 1.18
100
+ branch:
101
+ locks: strict
102
+ access list:
103
+ keyword substitution: kv
104
+ total revisions: 18; selected revisions: 1
105
+ description:
106
+ ----------------------------
107
+ revision 1.18
108
+ date: 2004/10/12 02:21:02; author: minam; state: Exp; lines: +4 -1
109
+ Added RubyConf 2004 presentation.
110
+ =============================================================================
111
+
112
+ RCS file: /var/cvs/copland/copland/Attic/build-gemspec.rb,v
113
+ Working file: build-gemspec.rb
114
+ head: 1.5
115
+ branch:
116
+ locks: strict
117
+ access list:
118
+ keyword substitution: kv
119
+ total revisions: 5; selected revisions: 1
120
+ description:
121
+ ----------------------------
122
+ revision 1.5
123
+ date: 2004/08/29 04:10:17; author: minam; state: dead; lines: +0 -0
124
+ Here we go -- point of no return. Deleting existing implementation to make
125
+ way for new implementation.
126
+ =============================================================================
127
+
128
+ RCS file: /var/cvs/copland/copland/copland.gemspec,v
129
+ Working file: copland.gemspec
130
+ head: 1.12
131
+ branch:
132
+ locks: strict
133
+ access list:
134
+ keyword substitution: kv
135
+ total revisions: 13; selected revisions: 1
136
+ description:
137
+ ----------------------------
138
+ revision 1.12
139
+ date: 2004/09/11 21:45:58; author: minam; state: Exp; lines: +4 -4
140
+ Minor change in how version is communicated to gemspec.
141
+ =============================================================================
142
+ MSG
143
+ @scm.story = [ @log_msg ]
144
+ end
145
+
146
+ def test_latest_revision
147
+ @scm.story = [ @log_msg ]
148
+ assert_equal "2004-10-12 02:21:02", @scm.latest_revision
149
+ assert_equal "/hello/world", @scm.last_path
150
+ end
151
+
152
+ def test_checkout
153
+ @actor.story = []
154
+ assert_nothing_raised { @scm.checkout(@actor) }
155
+ assert_nil @actor.channels.last.sent_data
156
+ assert_match %r{/path/to/cvs}, @actor.command
157
+ end
158
+
159
+ def test_checkout_needs_ssh_password
160
+ @actor.story = [[:out, "joetester@rubyforge.org's password: "]]
161
+ assert_nothing_raised { @scm.checkout(@actor) }
162
+ assert_equal ["chocolatebrownies\n"], @actor.channels.last.sent_data
163
+ end
164
+ end
@@ -0,0 +1,100 @@
1
+ $:.unshift File.dirname(__FILE__) + "/../../lib"
2
+
3
+ require File.dirname(__FILE__) + "/../utils"
4
+ require 'test/unit'
5
+ require 'switchtower/scm/subversion'
6
+
7
+ class ScmSubversionTest < Test::Unit::TestCase
8
+ class SubversionTest < SwitchTower::SCM::Subversion
9
+ attr_accessor :story
10
+ attr_reader :last_path
11
+
12
+ def svn_log(path)
13
+ @last_path = path
14
+ story.shift
15
+ end
16
+ end
17
+
18
+ class MockChannel
19
+ attr_reader :sent_data
20
+
21
+ def send_data(data)
22
+ @sent_data ||= []
23
+ @sent_data << data
24
+ end
25
+
26
+ def [](name)
27
+ "value"
28
+ end
29
+ end
30
+
31
+ class MockActor
32
+ attr_reader :command
33
+ attr_reader :channels
34
+ attr_accessor :story
35
+
36
+ def initialize(config)
37
+ @config = config
38
+ end
39
+
40
+ def run(command)
41
+ @command = command
42
+ @channels ||= []
43
+ @channels << MockChannel.new
44
+ story.each { |stream, line| yield @channels.last, stream, line }
45
+ end
46
+
47
+ def method_missing(sym, *args)
48
+ @config.send(sym, *args)
49
+ end
50
+ end
51
+
52
+ def setup
53
+ @config = MockConfiguration.new
54
+ @config[:repository] = "/hello/world"
55
+ @config[:svn] = "/path/to/svn"
56
+ @config[:password] = "chocolatebrownies"
57
+ @scm = SubversionTest.new(@config)
58
+ @actor = MockActor.new(@config)
59
+ @log_msg = <<MSG.strip
60
+ ------------------------------------------------------------------------
61
+ r1967 | minam | 2005-08-03 06:59:03 -0600 (Wed, 03 Aug 2005) | 2 lines
62
+
63
+ Initial commit of the new switchtower utility
64
+
65
+ ------------------------------------------------------------------------
66
+ MSG
67
+ @scm.story = [ @log_msg ]
68
+ end
69
+
70
+ def test_latest_revision
71
+ @scm.story = [ @log_msg ]
72
+ assert_equal "1967", @scm.latest_revision
73
+ assert_equal "/hello/world", @scm.last_path
74
+ end
75
+
76
+ def test_latest_revision_searching_upwards
77
+ @scm.story = [ "-----------------------------\n", @log_msg ]
78
+ assert_equal "1967", @scm.latest_revision
79
+ assert_equal "/hello", @scm.last_path
80
+ end
81
+
82
+ def test_checkout
83
+ @actor.story = []
84
+ assert_nothing_raised { @scm.checkout(@actor) }
85
+ assert_nil @actor.channels.last.sent_data
86
+ assert_match %r{/path/to/svn}, @actor.command
87
+ end
88
+
89
+ def test_checkout_needs_ssh_password
90
+ @actor.story = [[:out, "Password: "]]
91
+ assert_nothing_raised { @scm.checkout(@actor) }
92
+ assert_equal ["chocolatebrownies\n"], @actor.channels.last.sent_data
93
+ end
94
+
95
+ def test_checkout_needs_http_password
96
+ @actor.story = [[:out, "Password for (something): "]]
97
+ assert_nothing_raised { @scm.checkout(@actor) }
98
+ assert_equal ["chocolatebrownies\n"], @actor.channels.last.sent_data
99
+ end
100
+ end