sunshine 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +16 -0
- data/lib/commands/default.rb +1 -1
- data/lib/commands/list.rb +11 -11
- data/lib/sunshine.rb +1 -1
- data/lib/sunshine/app.rb +58 -24
- data/lib/sunshine/daemon.rb +58 -20
- data/lib/sunshine/daemons/apache.rb +0 -2
- data/lib/sunshine/daemons/nginx.rb +0 -2
- data/lib/sunshine/daemons/server.rb +1 -0
- data/lib/sunshine/daemons/unicorn.rb +2 -2
- data/lib/sunshine/dependencies.rb +2 -3
- data/lib/sunshine/package_managers/apt.rb +2 -0
- data/lib/sunshine/remote_shell.rb +3 -1
- data/lib/sunshine/server_app.rb +9 -9
- data/lib/sunshine/shell.rb +17 -0
- data/templates/nginx/nginx.conf.erb +1 -0
- data/templates/sunshine/middleware/health.rb +1 -1
- data/templates/sunshine/sunshine.rake +12 -0
- data/test/test_helper.rb +5 -167
- data/test/unit/test_app.rb +64 -0
- data/test/unit/test_server.rb +31 -43
- data/test/unit/test_server_app.rb +0 -2
- metadata +6 -34
data/History.txt
CHANGED
@@ -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:
|
data/lib/commands/default.rb
CHANGED
data/lib/commands/list.rb
CHANGED
@@ -54,20 +54,20 @@ module Sunshine
|
|
54
54
|
success = true
|
55
55
|
|
56
56
|
shells.each do |shell|
|
57
|
-
shell.
|
57
|
+
shell.with_session do
|
58
58
|
|
59
|
-
|
60
|
-
|
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
|
-
|
67
|
-
|
68
|
-
|
62
|
+
rescue => e
|
63
|
+
state = false
|
64
|
+
response = "#{e.class}: #{e.message}\n#{e.backtrace.join("\n")}"
|
65
|
+
end
|
69
66
|
|
70
|
-
|
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
|
data/lib/sunshine.rb
CHANGED
data/lib/sunshine/app.rb
CHANGED
@@ -90,7 +90,18 @@ module Sunshine
|
|
90
90
|
|
91
91
|
|
92
92
|
##
|
93
|
-
#
|
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
|
-
|
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
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
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
|
-
|
158
|
+
stop
|
145
159
|
|
146
|
-
|
160
|
+
symlink_current_dir
|
147
161
|
|
148
|
-
|
162
|
+
yield(self) if block_given?
|
149
163
|
|
150
|
-
|
151
|
-
build_deploy_info_file
|
152
|
-
build_crontab
|
164
|
+
run_post_user_lambdas
|
153
165
|
|
154
|
-
|
155
|
-
|
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
|
|
data/lib/sunshine/daemon.rb
CHANGED
@@ -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
|
142
|
-
|
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
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
377
|
-
|
378
|
-
|
379
|
-
|
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
|
@@ -15,8 +15,8 @@ module Sunshine
|
|
15
15
|
|
16
16
|
|
17
17
|
def start_cmd
|
18
|
-
"cd #{@app.current_path} && #{@bin} -D -E"+
|
19
|
-
"
|
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}
|
109
|
-
shell.call("apachectl -v")
|
108
|
+
shell.call("test -f #{passenger_mod} && apachectl -v")
|
110
109
|
end
|
111
110
|
end
|
112
111
|
|
data/lib/sunshine/server_app.rb
CHANGED
@@ -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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
|
data/lib/sunshine/shell.rb
CHANGED
@@ -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
|
|
@@ -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.
|
data/test/test_helper.rb
CHANGED
@@ -1,180 +1,18 @@
|
|
1
1
|
require 'sunshine'
|
2
2
|
require 'test/unit'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
end
|
4
|
+
require 'helper_methods'
|
5
|
+
include HelperMethods
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
data/test/unit/test_app.rb
CHANGED
@@ -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
|
|
data/test/unit/test_server.rb
CHANGED
@@ -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 =>
|
71
|
-
end
|
69
|
+
assert sa.method_called?(:install_deps, :args => ["rainbows"])
|
72
70
|
|
73
|
-
|
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 |
|
107
|
-
assert_equal @server_app,
|
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 |
|
133
|
-
assert_equal @server_app,
|
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
|
-
|
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
|
-
|
232
|
-
|
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
|
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
|
238
|
+
assert_equal false, @rainbows.send(:pick_sudo, ds)
|
251
239
|
|
252
240
|
ds.sudo = "blah"
|
253
241
|
@rainbows.sudo = true
|
254
|
-
assert_equal
|
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)
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 1
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 1.0.
|
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-
|
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:
|
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
|
-
|
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
|
|