sunshine 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,19 @@
1
+ === 1.0.3 / 2010
2
+
3
+ * Improvements:
4
+
5
+ * Added App#call method.
6
+
7
+ * Added App#with_session and Shell#with_session to reduce login prompts.
8
+
9
+ * Bugfixes:
10
+
11
+ * Geminstaller now always installs with sudo.
12
+
13
+ * Fixed permissions issues with running servers on ports < 1024.
14
+
15
+ * Fixed healthcheck middleware.
16
+
1
17
  === 1.0.2 / 2010-03-25
2
18
 
3
19
  * Bugfixes:
@@ -97,7 +97,7 @@ Sunshine is an object oriented deploy tool for rack applications.
97
97
  start Start a deployed app
98
98
  stop Stop a deployed app
99
99
 
100
- Options:
100
+ Options:
101
101
  EOF
102
102
 
103
103
  opt.on('--rakefile [PATH]',
@@ -54,20 +54,20 @@ module Sunshine
54
54
  success = true
55
55
 
56
56
  shells.each do |shell|
57
- shell.connect
57
+ shell.with_session do
58
58
 
59
- begin
60
- state, response = yield(shell)
61
- rescue => e
62
- state = false
63
- response = "#{e.class}: #{e.message}\n#{e.backtrace.join("\n")}"
64
- end
59
+ begin
60
+ state, response = yield(shell)
65
61
 
66
- host = shell.host
67
- success = state if success
68
- responses[host] = build_response state, response
62
+ rescue => e
63
+ state = false
64
+ response = "#{e.class}: #{e.message}\n#{e.backtrace.join("\n")}"
65
+ end
69
66
 
70
- shell.disconnect
67
+ host = shell.host
68
+ success = state if success
69
+ responses[host] = build_response state, response
70
+ end
71
71
  end
72
72
 
73
73
  output = format ? self.send(format, responses) : responses
@@ -74,7 +74,7 @@ module Sunshine
74
74
 
75
75
  ##
76
76
  # Sunshine version.
77
- VERSION = '1.0.2'
77
+ VERSION = '1.0.3'
78
78
 
79
79
 
80
80
  ##
@@ -90,7 +90,18 @@ module Sunshine
90
90
 
91
91
 
92
92
  ##
93
- # Connect server apps.
93
+ # Call a command on specified server apps.
94
+ # Supports any App#find and Shell#call options.
95
+
96
+ def call cmd, options=nil, &block
97
+ with_server_apps options, :msg => "Running #{cmd}" do |server_app|
98
+ server_app.shell.call cmd, options, &block
99
+ end
100
+ end
101
+
102
+
103
+ ##
104
+ # Connect server apps. Supports any App#find options.
94
105
 
95
106
  def connect options=nil
96
107
  with_server_apps options,
@@ -101,7 +112,7 @@ module Sunshine
101
112
 
102
113
 
103
114
  ##
104
- # Check if server apps are connected.
115
+ # Check if server apps are connected. Supports any App#find options.
105
116
 
106
117
  def connected? options=nil
107
118
  with_server_apps options, :no_threads => true do |server_app|
@@ -113,7 +124,7 @@ module Sunshine
113
124
 
114
125
 
115
126
  ##
116
- # Disconnect server apps.
127
+ # Disconnect server apps. Supports any App#find options.
117
128
 
118
129
  def disconnect options=nil
119
130
  with_server_apps options,
@@ -128,53 +139,61 @@ module Sunshine
128
139
  # call user's post-deploy code. Supports any App#find options.
129
140
 
130
141
  def deploy options=nil
131
- Sunshine.logger.info :app, "Beginning deploy of #{@name}" do
132
- connect options
133
- end
142
+ prev_connection = connected?
134
143
 
135
144
  deploy_trap = Sunshine.add_trap "Reverting deploy of #{@name}" do
136
145
  revert! options
146
+ start options
147
+ disconnect options unless prev_connection
137
148
  end
138
149
 
139
- with_filter options do |app|
140
- make_app_directories
141
- checkout_codebase
142
- symlink_current_dir
150
+ Sunshine.logger.info :app, "Beginning deploy of #{@name}"
151
+
152
+ with_session options do
153
+
154
+ with_filter options do |app|
155
+ make_app_directories
156
+ checkout_codebase
143
157
 
144
- yield(self) if block_given?
158
+ stop
145
159
 
146
- run_post_user_lambdas
160
+ symlink_current_dir
147
161
 
148
- health :enable
162
+ yield(self) if block_given?
149
163
 
150
- build_control_scripts
151
- build_deploy_info_file
152
- build_crontab
164
+ run_post_user_lambdas
153
165
 
154
- register_as_deployed
155
- remove_old_deploys
166
+ health :enable
167
+
168
+ build_control_scripts
169
+ build_deploy_info_file
170
+ build_crontab
171
+
172
+ register_as_deployed
173
+ remove_old_deploys
174
+ end
156
175
  end
157
176
 
177
+ Sunshine.logger.info :app, "Ending deploy of #{@name}"
178
+
158
179
  rescue => e
159
180
  message = "#{e.class}: #{e.message}"
160
181
 
161
182
  Sunshine.logger.error :app, message do
162
183
  Sunshine.logger.error '>>', e.backtrace.join("\n")
163
- revert!
184
+ revert! options
185
+ start options
186
+ disconnect options unless prev_connection
164
187
  end
165
188
 
166
189
  ensure
167
190
  Sunshine.delete_trap deploy_trap
168
-
169
- Sunshine.logger.info :app, "Ending deploy of #{@name}" do
170
- disconnect options
171
- end
172
191
  end
173
192
 
174
193
 
175
194
  ##
176
195
  # Symlink current directory to previous checkout and remove
177
- # the current deploy directory.
196
+ # the current deploy directory. Supports any App#find options.
178
197
 
179
198
  def revert!(options=nil)
180
199
  with_server_apps options,
@@ -775,6 +794,21 @@ module Sunshine
775
794
  end
776
795
 
777
796
 
797
+ ##
798
+ # Runs block ensuring a connection to remote_shells.
799
+ # Connecting and disconnecting will be ignored if a session
800
+ # already exists. Supports all App#find options.
801
+
802
+ def with_session options=nil
803
+ prev_connection = connected? options
804
+ connect options unless prev_connection
805
+
806
+ yield
807
+
808
+ disconnect options unless prev_connection
809
+ end
810
+
811
+
778
812
  private
779
813
 
780
814
 
@@ -138,8 +138,8 @@ module Sunshine
138
138
  # Build erb binding
139
139
  binder = config_binding server_app.shell
140
140
 
141
- server_app.shell.call "mkdir -p #{remote_dirs.join(" ")}",
142
- :sudo => binder.sudo
141
+ configure_remote_dirs server_app.shell
142
+ touch_log_files server_app.shell
143
143
 
144
144
  yield(server_app, binder) if block_given?
145
145
 
@@ -277,7 +277,7 @@ module Sunshine
277
277
  # Append or override daemon log file paths:
278
278
  # daemon.log_files :stderr => "/all_logs/stderr.log"
279
279
 
280
- def log_files(hash)
280
+ def log_files hash
281
281
  @log_files.merge!(hash)
282
282
  end
283
283
 
@@ -287,7 +287,7 @@ module Sunshine
287
287
  # daemon.log_file(:stderr)
288
288
  # #=> "/all_logs/stderr.log"
289
289
 
290
- def log_file(key)
290
+ def log_file key
291
291
  @log_files[key]
292
292
  end
293
293
 
@@ -327,7 +327,8 @@ module Sunshine
327
327
  end
328
328
 
329
329
 
330
- private
330
+ ##
331
+ # Create and setup a binding for a given shell.
331
332
 
332
333
  def config_binding shell
333
334
  binder = Binder.new self
@@ -350,33 +351,70 @@ module Sunshine
350
351
  end
351
352
 
352
353
 
354
+ ##
355
+ # Pick which sudo to use between the daemon sudo and shell sudo.
356
+ # (Useful when running servers on ports < 1024)
357
+
353
358
  def pick_sudo shell
354
- case shell.sudo
355
- when true
356
- self.sudo || shell.sudo
357
- when String
358
- String === self.sudo ? self.sudo : shell.sudo
359
- else
360
- self.sudo
361
- end
359
+ self.sudo.nil? ? shell.sudo : self.sudo
362
360
  end
363
361
 
364
362
 
365
- def remote_dirs
363
+ ##
364
+ # Make sure all the remote directories needed by the daemon exist.
365
+
366
+ def configure_remote_dirs shell
366
367
  dirs = @log_files.values.map{|f| File.dirname(f)}
367
- dirs.concat [@config_path, File.dirname(@pid)]
368
+
369
+ dirs << File.dirname(@pid)
370
+ dirs << @config_path
368
371
  dirs.delete_if{|d| d == "."}
369
- dirs
372
+ dirs = dirs.join(" ")
373
+
374
+ shell.call "mkdir -p #{dirs}"
375
+ end
376
+
377
+
378
+ ##
379
+ # Make sure log files are owned by the daemon's user.
380
+
381
+ def touch_log_files shell
382
+ files = @log_files.values.join(" ")
383
+
384
+ sudo = pick_sudo(shell)
385
+ user = case sudo
386
+ when true then 'root'
387
+ when String then sudo
388
+ else
389
+ nil
390
+ end
391
+
392
+ shell.call "touch #{files}", :sudo => true
393
+ shell.call "chown #{user} #{files}", :sudo => true if user
370
394
  end
371
395
 
372
396
 
397
+ ##
398
+ # Setup what should be run after the user block on App#deploy.
399
+
373
400
  def register_after_user_script
374
401
  @app.after_user_script do |app|
375
402
  each_server_app do |sa|
376
- sa.scripts[:start] << start_cmd
377
- sa.scripts[:stop] << stop_cmd
378
- sa.scripts[:restart] << restart_cmd
379
- sa.scripts[:status] << status_cmd
403
+ sudo = pick_sudo sa.shell
404
+
405
+ %w{start stop restart status}.each do |script|
406
+ script_file = "#{@config_path}/#{script}"
407
+
408
+ cmd = send "#{script}_cmd".to_sym
409
+
410
+ sa.shell.make_file script_file, cmd,
411
+ :flags => '--chmod=ugo=rwx'
412
+
413
+
414
+ cmd = sa.shell.sudo_cmd script_file, sudo
415
+
416
+ sa.scripts[script.to_sym] << [*cmd].join(" ")
417
+ end
380
418
  end
381
419
  end
382
420
  end
@@ -10,8 +10,6 @@ module Sunshine
10
10
 
11
11
  @bin = options[:bin] || 'apachectl'
12
12
 
13
- @sudo = options[:sudo] || @port < 1024
14
-
15
13
  @sigkill = 'WINCH'
16
14
 
17
15
  # TODO: have a separate max_clients and processes
@@ -8,8 +8,6 @@ module Sunshine
8
8
  def initialize app, options={}
9
9
  super
10
10
 
11
- @sudo = options[:sudo] || @port < 1024
12
-
13
11
  @dep_name = options[:dep_name] ||
14
12
  use_passenger? ? 'passenger-nginx' : 'nginx'
15
13
  end
@@ -37,6 +37,7 @@ module Sunshine
37
37
  super app, options
38
38
 
39
39
  @port = options[:port] || 80
40
+ @sudo = options[:sudo] || @port < 1024 || nil
40
41
  @server_name = options[:server_name]
41
42
  @sigkill = 'QUIT'
42
43
  @supports_rack = false
@@ -15,8 +15,8 @@ module Sunshine
15
15
 
16
16
 
17
17
  def start_cmd
18
- "cd #{@app.current_path} && #{@bin} -D -E"+
19
- " #{@app.deploy_env} -p #{@port} -c #{self.config_file_path};"
18
+ "cd #{@app.current_path} && #{@bin} -D -E #{@app.deploy_env} "+
19
+ "-p #{@port} -c #{self.config_file_path};"
20
20
  end
21
21
  end
22
22
  end
@@ -102,11 +102,10 @@ Sunshine.dependencies.instance_eval do
102
102
  end
103
103
 
104
104
  check do |shell, sudo|
105
- passenger_dir = Server.passenger_root shell
105
+ passenger_dir = Sunshine::Server.passenger_root shell
106
106
  passenger_mod = File.join passenger_dir, 'ext/apache2/mod_passenger.so'
107
107
 
108
- shell.call("test -f #{passenger_mod}", :sudo => true) &&
109
- shell.call("apachectl -v")
108
+ shell.call("test -f #{passenger_mod} && apachectl -v")
110
109
  end
111
110
  end
112
111
 
@@ -11,6 +11,8 @@ module Sunshine
11
11
 
12
12
  class Apt < Dependency
13
13
 
14
+ self.sudo = true
15
+
14
16
  def initialize(name, options={}, &block)
15
17
  super(name, options) do
16
18
  pkg_name = build_pkg_name @pkg.dup, options
@@ -228,7 +228,9 @@ module Sunshine
228
228
  end
229
229
 
230
230
 
231
- def ssh_cmd string, options={}
231
+ def ssh_cmd string, options=nil
232
+ options ||= {}
233
+
232
234
  cmd = sh_cmd string
233
235
  cmd = env_cmd cmd
234
236
  cmd = sudo_cmd cmd, options
@@ -348,7 +348,7 @@ fi
348
348
  rm_deploys = deploys[0..-lim]
349
349
  rm_deploys.map!{|d| "#{self.deploys_path}/#{d}"}
350
350
 
351
- @shell.call("rm -rf #{rm_deploys.join(" ")}")
351
+ @shell.call "rm -rf #{rm_deploys.join(" ")}"
352
352
  end
353
353
 
354
354
 
@@ -375,10 +375,6 @@ fi
375
375
 
376
376
  Sunshine.logger.info @shell.host, "Reverted to #{last_deploy}"
377
377
 
378
- unless start :force => true
379
- Sunshine.logger.error @shell.host, "Failed #{@name} startup"
380
- end
381
-
382
378
  else
383
379
  @crontab.delete!
384
380
 
@@ -402,7 +398,8 @@ fi
402
398
 
403
399
  def run_geminstaller
404
400
  install_deps 'geminstaller', :type => Gem
405
- @shell.call "cd #{self.checkout_path} && geminstaller -e"
401
+ # Without sudo gems get installed to ~user/.gems
402
+ @shell.call "cd #{self.checkout_path} && geminstaller -e", :sudo => true
406
403
  end
407
404
 
408
405
 
@@ -411,7 +408,8 @@ fi
411
408
  # Post-deploy only.
412
409
 
413
410
  def running?
414
- @shell.call "#{self.root_path}/status" rescue false
411
+ # Permissions are handled by the script, use: :sudo => false
412
+ @shell.call "#{self.root_path}/status", :sudo => false rescue false
415
413
  end
416
414
 
417
415
 
@@ -451,7 +449,8 @@ fi
451
449
  stop
452
450
  end
453
451
 
454
- @shell.call "#{self.root_path}/start" rescue false
452
+ # Permissions are handled by the script, use: :sudo => false
453
+ @shell.call "#{self.root_path}/start", :sudo => false rescue false
455
454
  end
456
455
 
457
456
 
@@ -468,7 +467,8 @@ fi
468
467
  # Post-deploy only.
469
468
 
470
469
  def stop
471
- @shell.call "#{self.root_path}/stop" rescue false
470
+ # Permissions are handled by the script, use: :sudo => false
471
+ @shell.call "#{self.root_path}/stop", :sudo => false rescue false
472
472
  end
473
473
 
474
474
 
@@ -254,6 +254,23 @@ module Sunshine
254
254
  end
255
255
 
256
256
 
257
+ ##
258
+ # Runs the passed block within a connection session.
259
+ # If the shell is already connected, connecting and disconnecting
260
+ # is ignored; otherwise, the session method will ensure that
261
+ # the shell's connection gets closed after the block has been
262
+ # executed.
263
+
264
+ def with_session
265
+ prev_connection = connected?
266
+ connect unless prev_connection
267
+
268
+ yield
269
+
270
+ disconnect unless prev_connection
271
+ end
272
+
273
+
257
274
  ##
258
275
  # Write string to stdout (by default).
259
276
 
@@ -17,6 +17,7 @@ events {
17
17
  http {
18
18
 
19
19
  <% if use_passenger? %>
20
+ passenger_default_user nobody;
20
21
  passenger_root <%= passenger_root %>;
21
22
  passenger_ruby <%= shell.call "which ruby" %>;
22
23
  <% end %>
@@ -35,7 +35,7 @@ module Sunshine
35
35
  # Given the rack env, do we need to perform a health check?
36
36
 
37
37
  def check_health? env
38
- env['REQUEST_PATH'] == @uri_path
38
+ env['PATH_INFO'] == @uri_path
39
39
  end
40
40
 
41
41
 
@@ -29,6 +29,18 @@ namespace :sunshine do
29
29
  task :deploy => :app do
30
30
  Sunshine.setup 'trace' => true
31
31
 
32
+ # If you're not able to add your public key to remote servers,
33
+ # you can setup your tasks to use the App#with_session method
34
+ # to avoid having to login multiple times:
35
+ #
36
+ # @app.with_session do
37
+ # @app.deploy do |app|
38
+ # ...
39
+ # end
40
+ #
41
+ # @app.start :force => true
42
+ # end
43
+
32
44
  @app.deploy do |app|
33
45
 
34
46
  # Do deploy-specific stuff here, e.g.
@@ -1,180 +1,18 @@
1
1
  require 'sunshine'
2
2
  require 'test/unit'
3
3
 
4
- def no_mocks
5
- ENV['mocks'] == "false"
6
- end
4
+ require 'helper_methods'
5
+ include HelperMethods
7
6
 
8
- unless no_mocks
9
- require 'test/mocks/mock_object'
10
- require 'test/mocks/mock_open4'
11
- end
7
+
8
+ require 'test/mocks/mock_object'
9
+ require 'test/mocks/mock_open4'
12
10
 
13
11
  unless defined? TEST_APP_CONFIG_FILE
14
12
  TEST_APP_CONFIG_FILE = "test/fixtures/app_configs/test_app.yml"
15
13
  end
16
14
 
17
15
 
18
- def mock_app
19
- Sunshine::App.new(TEST_APP_CONFIG_FILE).extend MockObject
20
- end
21
-
22
-
23
- def mock_remote_shell host=nil
24
- host ||= "user@some_server.com"
25
- remote_shell = Sunshine::RemoteShell.new host
26
-
27
- remote_shell.extend MockOpen4
28
- remote_shell.extend MockObject
29
-
30
- use_remote_shell remote_shell
31
-
32
- remote_shell.connect
33
- remote_shell
34
- end
35
-
36
-
37
- def mock_svn_response url=nil
38
- url ||= "svn://subversion/path/to/my_app/trunk"
39
-
40
- svn_response = <<-STR
41
- <?xml version="1.0"?>
42
- <log>
43
- <logentry
44
- revision="777">
45
- <author>user</author>
46
- <date>2010-01-26T01:49:17.372152Z</date>
47
- <msg>finished testing server.rb</msg>
48
- </logentry>
49
- </log>
50
- STR
51
-
52
- Sunshine::SvnRepo.extend(MockObject) unless
53
- Sunshine::SvnRepo.is_a?(MockObject)
54
-
55
- Sunshine::SvnRepo.mock :svn_log, :return => svn_response
56
- Sunshine::SvnRepo.mock :get_svn_url, :return => url
57
- end
58
-
59
-
60
- def mock_remote_shell_popen4
61
- return if no_mocks
62
- Sunshine::RemoteShell.class_eval{ include MockOpen4 }
63
- end
64
-
65
-
66
- def set_mock_response_for obj, code, stream_vals={}, options={}
67
- case obj
68
- when Sunshine::App then
69
- obj.each do |sa|
70
- sa.shell.set_mock_response code, stream_vals, options
71
- end
72
- when Sunshine::ServerApp then
73
- obj.shell.set_mock_response code, stream_vals, options
74
- when Sunshine::RemoteShell then
75
- obj.set_mock_response code, stream_vals, options
76
- end
77
- end
78
-
79
-
80
- def assert_dep_install dep_name, type=Sunshine::Yum
81
- prefered = type rescue nil
82
- args = [{:call => @remote_shell, :prefer => prefered}]
83
-
84
- dep = if Sunshine::Dependency === dep_name
85
- dep_name
86
- else
87
- Sunshine.dependencies.get(dep_name, :prefer => prefered)
88
- end
89
-
90
-
91
- assert dep.method_called?(:install!, :args => args),
92
- "Dependency '#{dep_name}' install was not called."
93
- end
94
-
95
-
96
- def assert_not_called *args
97
- assert !@remote_shell.method_called?(:call, :args => [*args]),
98
- "Command called by #{@remote_shell.host} but should't have:\n #{args[0]}"
99
- end
100
-
101
-
102
- def assert_server_call *args
103
- assert @remote_shell.method_called?(:call, :args => [*args]),
104
- "Command was not called by #{@remote_shell.host}:\n #{args[0]}"
105
- end
106
-
107
-
108
- def assert_bash_script name, cmds, check_value
109
- cmds = cmds.map{|cmd| "(#{cmd})" }
110
- cmds << "echo true"
111
-
112
- bash = <<-STR
113
- #!/bin/bash
114
- if [ "$1" == "--no-env" ]; then
115
- #{cmds.flatten.join(" && ")}
116
- else
117
- #{@app.root_path}/env #{@app.root_path}/#{name} --no-env
118
- fi
119
- STR
120
-
121
- assert_equal bash, check_value
122
- end
123
-
124
-
125
- def assert_ssh_call expected, ds=@remote_shell, options={}
126
- expected = ds.send(:ssh_cmd, expected, options).join(" ")
127
-
128
- error_msg = "No such command in remote_shell log [#{ds.host}]\n#{expected}"
129
- error_msg << "\n\n#{ds.cmd_log.select{|c| c =~ /^ssh/}.join("\n\n")}"
130
-
131
- assert ds.cmd_log.include?(expected), error_msg
132
- end
133
-
134
-
135
- def assert_rsync from, to, ds=@remote_shell, sudo=false
136
- received = ds.cmd_log.last
137
-
138
- rsync_path = if sudo
139
- path = ds.sudo_cmd('rsync', sudo).join(' ')
140
- "--rsync-path='#{ path }' "
141
- end
142
-
143
- rsync_cmd = "rsync -azP #{rsync_path}-e \"ssh #{ds.ssh_flags.join(' ')}\""
144
-
145
- error_msg = "No such command in remote_shell log [#{ds.host}]\n#{rsync_cmd}"
146
- error_msg << "#{from.inspect} #{to.inspect}"
147
- error_msg << "\n\n#{ds.cmd_log.select{|c| c =~ /^rsync/}.join("\n\n")}"
148
-
149
- if Regexp === from
150
- found = ds.cmd_log.select do |cmd|
151
-
152
- cmd_from = cmd.split(" ")[-2]
153
- cmd_to = cmd.split(" ").last
154
-
155
- cmd_from =~ from && cmd_to == to && cmd.index(rsync_cmd) == 0
156
- end
157
-
158
- assert !found.empty?, error_msg
159
- else
160
- expected = "#{rsync_cmd} #{from} #{to}"
161
- assert ds.cmd_log.include?(expected), error_msg
162
- end
163
- end
164
-
165
-
166
- def use_remote_shell remote_shell
167
- @remote_shell = remote_shell
168
- end
169
-
170
-
171
- def each_remote_shell app=@app
172
- app.server_apps.each do |sa|
173
- use_remote_shell sa.shell
174
- yield(sa.shell) if block_given?
175
- end
176
- end
177
-
178
16
  Sunshine.setup({}, true)
179
17
 
180
18
  unless MockObject === Sunshine.shell
@@ -233,6 +233,23 @@ class TestApp < Test::Unit::TestCase
233
233
  end
234
234
 
235
235
 
236
+ def test_call
237
+ calls = 0
238
+
239
+ @app.call "test call", :sudo => true do |type, data, inn|
240
+ calls += 1
241
+ end
242
+
243
+ assert_equal calls, @app.server_apps.length
244
+
245
+ args = ["test call", {:sudo => true}]
246
+
247
+ @app.each do |server_app|
248
+ assert server_app.shell.method_called?(:call, :args => args)
249
+ end
250
+ end
251
+
252
+
236
253
  def test_checkout_codebase
237
254
  @app.checkout_codebase
238
255
 
@@ -252,15 +269,25 @@ class TestApp < Test::Unit::TestCase
252
269
 
253
270
 
254
271
  def test_deployed?
272
+ set_mock_response_for @app, 0,
273
+ "cat #{@app.current_path}/info" => [:out,
274
+ "---\n:deploy_name: '#{@app.deploy_name}'"]
275
+
255
276
  deployed = @app.deployed?
256
277
 
257
278
  state = true
258
279
  @app.server_apps.each do |sa|
259
280
  assert sa.method_called? :deployed?
281
+
282
+ set_mock_response_for sa.shell, 0,
283
+ "cat #{@app.current_path}/info" => [:out,
284
+ "---\n:deploy_name: '#{@app.deploy_name}'"]
285
+
260
286
  state = false unless sa.deployed?
261
287
  end
262
288
 
263
289
  assert_equal state, deployed
290
+ assert deployed
264
291
  end
265
292
 
266
293
 
@@ -327,6 +354,43 @@ class TestApp < Test::Unit::TestCase
327
354
  end
328
355
 
329
356
 
357
+ def test_find_all
358
+ app = Sunshine::App.new :repo => {:type => "svn", :url => @svn_url},
359
+ :remote_shells => [
360
+ "user@some_server.com",
361
+ ["server2.com", {:roles => "web db"}]
362
+ ]
363
+
364
+ server_apps = app.server_apps
365
+
366
+ assert_equal server_apps, app.find
367
+ assert_equal server_apps, app.find({})
368
+ assert_equal server_apps, app.find(:all)
369
+ assert_equal server_apps, app.find(nil)
370
+ end
371
+
372
+
373
+ def test_find
374
+ app = Sunshine::App.new :repo => {:type => "svn", :url => @svn_url},
375
+ :remote_shells => [
376
+ "user@some_server.com",
377
+ ["server2.com", {:roles => "web db"}]
378
+ ]
379
+
380
+ server_apps = app.server_apps
381
+
382
+ assert_equal server_apps, app.find(:role => :web)
383
+ assert_equal server_apps, app.find(:role => :db)
384
+
385
+ assert_equal [server_apps[0]], app.find(:role => :all)
386
+ assert_equal [server_apps[0]], app.find(:role => :blarg)
387
+ assert_equal [server_apps[0]], app.find(:user => 'user')
388
+ assert_equal [server_apps[0]], app.find(:host => 'some_server.com')
389
+
390
+ assert_equal [server_apps[1]], app.find(:host => 'server2.com')
391
+ end
392
+
393
+
330
394
  def test_make_app_directories
331
395
  @app.make_app_directories
332
396
 
@@ -65,14 +65,14 @@ class TestServer < Test::Unit::TestCase
65
65
  assert_equal @rainbows.send(:pick_sudo, sa.shell), binder.sudo
66
66
  end
67
67
 
68
- args = ["rainbows"]
69
68
  server.each_server_app do |sa|
70
- assert sa.method_called?(:install_deps, :args => args)
71
- end
69
+ assert sa.method_called?(:install_deps, :args => ["rainbows"])
72
70
 
73
- assert server.method_called?(:upload_config_files)
71
+ assert server.method_called?(:configure_remote_dirs, :args => [sa.shell])
72
+ assert server.method_called?(:touch_log_files, :args => [sa.shell])
73
+ assert server.method_called?(:upload_config_files, :args => [sa.shell])
74
+ end
74
75
 
75
- assert_ssh_call "mkdir -p #{server.send(:remote_dirs).join(" ")}"
76
76
 
77
77
  assert_rsync(/rainbows\.conf/, "some_server.com:"+
78
78
  "/usr/local/my_user/other_app/current/daemons/rainbows/rainbows.conf")
@@ -103,13 +103,12 @@ class TestServer < Test::Unit::TestCase
103
103
  @server_app.shell.mock :file?, :args => [server.config_file_path],
104
104
  :return => false
105
105
 
106
- server.start do |ds|
107
- assert_equal @server_app, ds
106
+ server.start do |sa|
107
+ assert_equal @server_app, sa
108
+ assert_ssh_call server.start_cmd, sa.shell, :sudo => true
108
109
  end
109
110
 
110
111
  assert server.method_called?(:setup)
111
-
112
- assert_ssh_call server.start_cmd
113
112
  end
114
113
 
115
114
 
@@ -118,31 +117,32 @@ class TestServer < Test::Unit::TestCase
118
117
  @server_app.shell.mock :file?, :args => [server.config_file_path],
119
118
  :return => true
120
119
 
121
- server.start
120
+ server.start do |sa|
121
+ assert_equal @server_app, sa
122
+ assert_ssh_call server.start_cmd, sa.shell, :sudo => true
123
+ end
122
124
 
123
125
  assert !server.method_called?(:setup)
124
-
125
- assert_ssh_call server.start_cmd
126
126
  end
127
127
 
128
128
 
129
129
  def test_stop
130
130
  server = @rainbows
131
131
 
132
- server.stop do |ds|
133
- assert_equal @server_app, ds
132
+ server.stop do |sa|
133
+ assert_equal @server_app, sa
134
+ assert_ssh_call server.stop_cmd, sa.shell, :sudo => true
134
135
  end
135
-
136
- assert_ssh_call server.stop_cmd
137
136
  end
138
137
 
139
138
 
140
139
  def test_restart
141
140
  server = @rainbows
142
141
 
143
- server.restart
144
-
145
- assert_ssh_call server.restart_cmd
142
+ server.restart do |sa|
143
+ assert_equal @server_app, sa
144
+ assert_ssh_call server.restart_cmd, sa.shell, :sudo => true
145
+ end
146
146
  end
147
147
 
148
148
 
@@ -152,10 +152,7 @@ class TestServer < Test::Unit::TestCase
152
152
  :return => true
153
153
 
154
154
  server.restart
155
-
156
155
  assert !server.method_called?(:setup)
157
-
158
- assert_ssh_call server.restart_cmd
159
156
  end
160
157
 
161
158
 
@@ -166,10 +163,12 @@ class TestServer < Test::Unit::TestCase
166
163
  @server_app.shell.mock :file?, :args => [server.config_file_path],
167
164
  :return => false
168
165
 
169
- server.restart
166
+ server.restart do |sa|
167
+ assert_equal @server_app, sa
168
+ assert_ssh_call server.restart_cmd, sa.shell, :sudo => true
169
+ end
170
170
 
171
171
  assert server.method_called?(:setup)
172
- assert_ssh_call server.restart_cmd
173
172
  end
174
173
 
175
174
 
@@ -207,18 +206,6 @@ class TestServer < Test::Unit::TestCase
207
206
  end
208
207
 
209
208
 
210
- def test_remote_dirs
211
- server = @rainbows
212
-
213
- dirs = server.send :remote_dirs
214
-
215
- assert_dir_in dirs, server.pid
216
- assert_dir_in dirs, server.config_file_path
217
- assert_dir_in dirs, server.log_file(:stderr)
218
- assert_dir_in dirs, server.log_file(:stdout)
219
- end
220
-
221
-
222
209
  def test_register_after_user_script
223
210
  server = @rainbows
224
211
 
@@ -227,11 +214,12 @@ class TestServer < Test::Unit::TestCase
227
214
  @app.run_post_user_lambdas
228
215
 
229
216
  server.each_server_app do |sa|
217
+ %w{start stop restart status}.each do |script|
218
+ script_file = "#{server.config_path}/#{script}"
219
+ cmd = sa.shell.sudo_cmd script_file, server.send(:pick_sudo, sa.shell)
230
220
 
231
- assert sa.scripts[:start].include?(server.start_cmd)
232
- assert sa.scripts[:stop].include?(server.stop_cmd)
233
- assert sa.scripts[:status].include?(server.status_cmd)
234
- assert sa.scripts[:restart].include?(server.restart_cmd)
221
+ assert sa.scripts[script.to_sym].include?(cmd.join(" "))
222
+ end
235
223
 
236
224
  assert_equal server.port, sa.info[:ports][server.pid]
237
225
  end
@@ -240,18 +228,18 @@ class TestServer < Test::Unit::TestCase
240
228
 
241
229
  def test_pick_sudo
242
230
  ds = @rainbows.app.server_apps.first.shell
243
- assert_equal nil, @rainbows.send(:pick_sudo, ds)
231
+ assert_equal true, @rainbows.send(:pick_sudo, ds)
244
232
 
245
233
  @rainbows.sudo = true
246
234
  assert_equal true, @rainbows.send(:pick_sudo, ds)
247
235
 
248
236
  ds.sudo = true
249
237
  @rainbows.sudo = false
250
- assert_equal true, @rainbows.send(:pick_sudo, ds)
238
+ assert_equal false, @rainbows.send(:pick_sudo, ds)
251
239
 
252
240
  ds.sudo = "blah"
253
241
  @rainbows.sudo = true
254
- assert_equal "blah", @rainbows.send(:pick_sudo, ds)
242
+ assert_equal true, @rainbows.send(:pick_sudo, ds)
255
243
 
256
244
  @rainbows.sudo = "local"
257
245
  assert_equal "local", @rainbows.send(:pick_sudo, ds)
@@ -280,8 +280,6 @@ class TestServerApp < Test::Unit::TestCase
280
280
 
281
281
  last_deploy = "#{@app.deploys_path}/ploy5"
282
282
  assert_server_call "ln -sfT #{last_deploy} #{@app.current_path}"
283
-
284
- assert @sa.method_called?(:start, :args =>[:force => true])
285
283
  end
286
284
 
287
285
 
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 1
7
7
  - 0
8
- - 2
9
- version: 1.0.2
8
+ - 3
9
+ version: 1.0.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - Jeremie Castagna
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-03-25 00:00:00 -07:00
17
+ date: 2010-03-26 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -74,7 +74,7 @@ dependencies:
74
74
  type: :runtime
75
75
  version_requirements: *id004
76
76
  - !ruby/object:Gem::Dependency
77
- name: rubyforge
77
+ name: hoe
78
78
  prerelease: false
79
79
  requirement: &id005 !ruby/object:Gem::Requirement
80
80
  requirements:
@@ -82,39 +82,11 @@ dependencies:
82
82
  - !ruby/object:Gem::Version
83
83
  segments:
84
84
  - 2
85
- - 0
86
85
  - 3
87
- version: 2.0.3
86
+ - 3
87
+ version: 2.3.3
88
88
  type: :development
89
89
  version_requirements: *id005
90
- - !ruby/object:Gem::Dependency
91
- name: gemcutter
92
- prerelease: false
93
- requirement: &id006 !ruby/object:Gem::Requirement
94
- requirements:
95
- - - ">="
96
- - !ruby/object:Gem::Version
97
- segments:
98
- - 0
99
- - 5
100
- - 0
101
- version: 0.5.0
102
- type: :development
103
- version_requirements: *id006
104
- - !ruby/object:Gem::Dependency
105
- name: hoe
106
- prerelease: false
107
- requirement: &id007 !ruby/object:Gem::Requirement
108
- requirements:
109
- - - ">="
110
- - !ruby/object:Gem::Version
111
- segments:
112
- - 2
113
- - 5
114
- - 0
115
- version: 2.5.0
116
- type: :development
117
- version_requirements: *id007
118
90
  description: |-
119
91
  Sunshine is an object-oriented api for rack application deployment.
120
92