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