sunshine 1.0.2 → 1.0.3

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.
@@ -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