sunshine 1.2.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +26 -0
- data/Manifest.txt +1 -0
- data/bin/sunshine +8 -1
- data/lib/commands/list.rb +11 -6
- data/lib/commands/restart.rb +6 -5
- data/lib/commands/rm.rb +6 -5
- data/lib/commands/script.rb +5 -4
- data/lib/commands/start.rb +7 -6
- data/lib/commands/stop.rb +6 -5
- data/lib/sunshine.rb +68 -50
- data/lib/sunshine/app.rb +269 -55
- data/lib/sunshine/daemon.rb +72 -18
- data/lib/sunshine/dependency_lib.rb +0 -2
- data/lib/sunshine/exceptions.rb +35 -17
- data/lib/sunshine/package_managers/apt.rb +1 -1
- data/lib/sunshine/package_managers/dependency.rb +0 -5
- data/lib/sunshine/package_managers/yum.rb +1 -1
- data/lib/sunshine/remote_shell.rb +21 -5
- data/lib/sunshine/repo.rb +5 -6
- data/lib/sunshine/repos/rsync_repo.rb +1 -1
- data/lib/sunshine/server_app.rb +146 -14
- data/lib/sunshine/shell.rb +49 -24
- data/lib/sunshine/trap_stack.rb +54 -0
- data/templates/nginx/nginx.conf.erb +24 -0
- data/test/helper_methods.rb +1 -1
- data/test/unit/test_app.rb +48 -6
- data/test/unit/test_daemon.rb +3 -3
- data/test/unit/test_nginx.rb +7 -4
- data/test/unit/test_server.rb +6 -6
- data/test/unit/test_server_app.rb +107 -9
- metadata +8 -7
data/lib/sunshine/shell.rb
CHANGED
@@ -7,13 +7,23 @@ module Sunshine
|
|
7
7
|
|
8
8
|
include Open4
|
9
9
|
|
10
|
-
class TimeoutError < CriticalDeployError; end
|
11
|
-
|
12
10
|
LOCAL_USER = `whoami`.chomp
|
13
11
|
LOCAL_HOST = `hostname`.chomp
|
14
12
|
|
15
|
-
|
16
|
-
|
13
|
+
class << self
|
14
|
+
# The message to match in stderr to determine logging in has failed.
|
15
|
+
# Defaults to:
|
16
|
+
# /^Sorry, try again./
|
17
|
+
attr_accessor :sudo_failed_matcher
|
18
|
+
|
19
|
+
# The message to match in stderr to determine a password is required.
|
20
|
+
# Defaults to:
|
21
|
+
# /^Password:/
|
22
|
+
attr_accessor :sudo_prompt_matcher
|
23
|
+
end
|
24
|
+
|
25
|
+
self.sudo_failed_matcher = /^Sorry, try again./
|
26
|
+
self.sudo_prompt_matcher = /^Password:/
|
17
27
|
|
18
28
|
attr_reader :user, :host, :password, :input, :output, :mutex
|
19
29
|
attr_accessor :env, :sudo, :timeout
|
@@ -33,8 +43,6 @@ module Sunshine
|
|
33
43
|
|
34
44
|
@timeout = options[:timeout] || Sunshine.timeout
|
35
45
|
|
36
|
-
@cmd_activity = nil
|
37
|
-
|
38
46
|
@mutex = nil
|
39
47
|
end
|
40
48
|
|
@@ -73,6 +81,14 @@ module Sunshine
|
|
73
81
|
end
|
74
82
|
|
75
83
|
|
84
|
+
##
|
85
|
+
# Prompt the user to make a choice.
|
86
|
+
|
87
|
+
def choose &block
|
88
|
+
sync{ @input.choose(&block) }
|
89
|
+
end
|
90
|
+
|
91
|
+
|
76
92
|
##
|
77
93
|
# Close the output IO. (Required by the Logger class)
|
78
94
|
|
@@ -133,6 +149,21 @@ module Sunshine
|
|
133
149
|
end
|
134
150
|
|
135
151
|
|
152
|
+
##
|
153
|
+
# Start an interactive shell with preset permissions and env.
|
154
|
+
# Optionally pass a command to be run first.
|
155
|
+
|
156
|
+
def tty! cmd=nil
|
157
|
+
sync do
|
158
|
+
cmd = [cmd, "sh -il"].compact.join " && "
|
159
|
+
pid = fork do
|
160
|
+
exec sudo_cmd(env_cmd(cmd)).to_a.join(" ")
|
161
|
+
end
|
162
|
+
Process.waitpid pid
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
|
136
167
|
##
|
137
168
|
# Write a file. Compatibility method with RemoteShell.
|
138
169
|
|
@@ -237,7 +268,7 @@ module Sunshine
|
|
237
268
|
##
|
238
269
|
# Returns true if command was run successfully, otherwise returns false.
|
239
270
|
|
240
|
-
def
|
271
|
+
def system cmd, options=nil
|
241
272
|
call(cmd, options) && true rescue false
|
242
273
|
end
|
243
274
|
|
@@ -245,20 +276,12 @@ module Sunshine
|
|
245
276
|
##
|
246
277
|
# Checks if timeout occurred.
|
247
278
|
|
248
|
-
def timed_out? start_time
|
279
|
+
def timed_out? start_time, max_time=@timeout
|
249
280
|
return unless max_time
|
250
281
|
Time.now.to_i - start_time.to_i > max_time
|
251
282
|
end
|
252
283
|
|
253
284
|
|
254
|
-
##
|
255
|
-
# Update the time of the last command activity
|
256
|
-
|
257
|
-
def update_timeout
|
258
|
-
@cmd_activity = Time.now
|
259
|
-
end
|
260
|
-
|
261
|
-
|
262
285
|
##
|
263
286
|
# Execute a block while setting the shell's mutex.
|
264
287
|
# Sets the mutex to its original value on exit.
|
@@ -319,7 +342,9 @@ module Sunshine
|
|
319
342
|
log_methods = {out => :debug, err => :error}
|
320
343
|
|
321
344
|
result, status = process_streams(pid, out, err) do |stream, data|
|
322
|
-
stream_name = stream == out
|
345
|
+
stream_name = :out if stream == out
|
346
|
+
stream_name = :err if stream == err
|
347
|
+
stream_name = :inn if stream == inn
|
323
348
|
|
324
349
|
|
325
350
|
# User blocks should run with sync threads to avoid badness.
|
@@ -353,18 +378,18 @@ module Sunshine
|
|
353
378
|
private
|
354
379
|
|
355
380
|
def raise_command_failed(status, cmd)
|
356
|
-
|
357
|
-
|
381
|
+
err = CmdError.new status.exitstatus, [*cmd].join(" ")
|
382
|
+
raise err
|
358
383
|
end
|
359
384
|
|
360
385
|
|
361
386
|
def password_required? stream_name, data
|
362
|
-
stream_name == :err && data =~
|
387
|
+
stream_name == :err && data =~ Shell.sudo_prompt_matcher
|
363
388
|
end
|
364
389
|
|
365
390
|
|
366
391
|
def send_password_to_stream inn, data
|
367
|
-
prompt_for_password if data =~
|
392
|
+
prompt_for_password if data =~ Shell.sudo_failed_matcher
|
368
393
|
inn.puts @password || prompt_for_password
|
369
394
|
end
|
370
395
|
|
@@ -380,7 +405,7 @@ module Sunshine
|
|
380
405
|
|
381
406
|
def process_streams pid, *streams
|
382
407
|
result = Hash.new{|h,k| h[k] = []}
|
383
|
-
|
408
|
+
start_time = Time.now
|
384
409
|
|
385
410
|
# Handle process termination ourselves
|
386
411
|
status = nil
|
@@ -392,13 +417,13 @@ module Sunshine
|
|
392
417
|
# don't busy loop
|
393
418
|
selected, = select streams, nil, nil, 0.1
|
394
419
|
|
395
|
-
raise TimeoutError if timed_out?
|
420
|
+
raise TimeoutError if timed_out? start_time
|
396
421
|
|
397
422
|
next if selected.nil? or selected.empty?
|
398
423
|
|
399
424
|
selected.each do |stream|
|
400
425
|
|
401
|
-
|
426
|
+
start_time = Time.now
|
402
427
|
|
403
428
|
if stream.eof? then
|
404
429
|
streams.delete stream if status # we've quit, so no more writing
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Sunshine
|
2
|
+
|
3
|
+
##
|
4
|
+
# The TrapStack class handles setting multiple trap blocks as a stack.
|
5
|
+
# Once a trap block is triggered, it gets popped off the stack.
|
6
|
+
|
7
|
+
class TrapStack
|
8
|
+
|
9
|
+
##
|
10
|
+
# Adds an INT signal trap with its description on the stack.
|
11
|
+
# Returns a trap_item Array.
|
12
|
+
|
13
|
+
def self.add_trap desc=nil, &block
|
14
|
+
@trap_stack.unshift [desc, block]
|
15
|
+
@trap_stack.first
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
##
|
21
|
+
# Call a trap item and display it's message.
|
22
|
+
|
23
|
+
def self.call_trap trap_item
|
24
|
+
return unless trap_item
|
25
|
+
|
26
|
+
msg, trap_block = trap_item
|
27
|
+
|
28
|
+
yield msg if block_given?
|
29
|
+
|
30
|
+
trap_block.call
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
##
|
35
|
+
# Remove a trap_item from the stack.
|
36
|
+
|
37
|
+
def self.delete_trap trap_item
|
38
|
+
@trap_stack.delete trap_item
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
##
|
43
|
+
# Sets the default trap.
|
44
|
+
|
45
|
+
def self.trap_signal sig, &block
|
46
|
+
@trap_stack = []
|
47
|
+
|
48
|
+
trap sig do
|
49
|
+
call_trap @trap_stack.shift, &block
|
50
|
+
exit 1
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -25,7 +25,31 @@ http {
|
|
25
25
|
client_body_temp_path <%= darwin ? '/var/tmp/nginx' : '/dev/shm' %>;
|
26
26
|
proxy_temp_path <%= darwin ? '/var/tmp/nginx' : '/dev/shm' %>;
|
27
27
|
|
28
|
+
<%
|
29
|
+
mime_types = "#{File.dirname(shell.call("which nginx"))}/../conf/mime.types"
|
30
|
+
|
31
|
+
if shell.file? mime_types
|
32
|
+
-%>
|
28
33
|
include <%= File.dirname shell.call("which nginx") %>/../conf/mime.types;
|
34
|
+
|
35
|
+
<% else -%>
|
36
|
+
|
37
|
+
types {
|
38
|
+
application/x-plist plist;
|
39
|
+
application/json json;
|
40
|
+
image/gif gif;
|
41
|
+
image/jpeg jpg;
|
42
|
+
image/png png;
|
43
|
+
image/x-icon ico;
|
44
|
+
text/css css;
|
45
|
+
text/html html;
|
46
|
+
text/plain bob;
|
47
|
+
text/plain txt;
|
48
|
+
application/vnd.android.package-archive apk;
|
49
|
+
}
|
50
|
+
|
51
|
+
<% end -%>
|
52
|
+
|
29
53
|
default_type application/octet-stream;
|
30
54
|
|
31
55
|
log_format sunshine '$remote_addr - $remote_user [$time_local] '
|
data/test/helper_methods.rb
CHANGED
@@ -123,7 +123,7 @@ fi
|
|
123
123
|
"--rsync-path='#{ path }' "
|
124
124
|
end
|
125
125
|
|
126
|
-
rsync_cmd = "rsync -
|
126
|
+
rsync_cmd = "rsync -azrP #{rsync_path}-e \"ssh #{ds.ssh_flags.join(' ')}\""
|
127
127
|
|
128
128
|
error_msg = "No such command in remote_shell log [#{ds.host}]\n#{rsync_cmd}"
|
129
129
|
error_msg << "#{from.inspect} #{to.inspect}"
|
data/test/unit/test_app.rb
CHANGED
@@ -26,6 +26,7 @@ class TestApp < Test::Unit::TestCase
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def teardown
|
29
|
+
Sunshine.exclude_paths.clear
|
29
30
|
FileUtils.rm_rf @tmpdir
|
30
31
|
end
|
31
32
|
|
@@ -159,8 +160,7 @@ class TestApp < Test::Unit::TestCase
|
|
159
160
|
|
160
161
|
def test_app_deploy_error_handling
|
161
162
|
[ MockError,
|
162
|
-
Sunshine::
|
163
|
-
Sunshine::FatalDeployError ].each do |error|
|
163
|
+
Sunshine::DeployError ].each do |error|
|
164
164
|
|
165
165
|
begin
|
166
166
|
app = Sunshine::App.deploy @config do |app|
|
@@ -277,9 +277,51 @@ class TestApp < Test::Unit::TestCase
|
|
277
277
|
end
|
278
278
|
|
279
279
|
|
280
|
+
def test_checkout_local_codebase
|
281
|
+
tmp_path = File.join Sunshine::TMP_DIR, "#{@app.name}_checkout"
|
282
|
+
@app.repo.extend MockObject
|
283
|
+
@app.repo.mock :checkout_to, :args => [tmp_path],
|
284
|
+
:return => {:test => "scm info"}
|
285
|
+
|
286
|
+
@app.each do |sa|
|
287
|
+
sa.mock :upload_codebase
|
288
|
+
end
|
289
|
+
|
290
|
+
@app.checkout_codebase :copy => true
|
291
|
+
|
292
|
+
@app.each do |sa|
|
293
|
+
assert sa.method_called?(:upload_codebase,
|
294
|
+
:args => [tmp_path, {:test => "scm info", :exclude => []}])
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
|
299
|
+
def test_checkout_local_codebase_with_exludes
|
300
|
+
Sunshine.exclude_paths.concat ["path1/", "path2/"]
|
301
|
+
|
302
|
+
tmp_path = File.join Sunshine::TMP_DIR, "#{@app.name}_checkout"
|
303
|
+
@app.repo.extend MockObject
|
304
|
+
|
305
|
+
@app.repo.mock :checkout_to, :args => [tmp_path],
|
306
|
+
:return => {:test => "scm info"}
|
307
|
+
|
308
|
+
@app.each do |sa|
|
309
|
+
sa.mock :upload_codebase
|
310
|
+
end
|
311
|
+
|
312
|
+
@app.checkout_codebase :copy => true, :exclude => ["path3/", "path4/"]
|
313
|
+
|
314
|
+
@app.each do |sa|
|
315
|
+
assert sa.method_called?(:upload_codebase,
|
316
|
+
:args => [tmp_path, {:test => "scm info",
|
317
|
+
:exclude => ["path1/", "path2/", "path3/", "path4/"]}])
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
|
280
322
|
def test_deployed?
|
281
323
|
set_mock_response_for @app, 0,
|
282
|
-
"cat #{@app.
|
324
|
+
"cat #{@app.root_path}/info" => [:out,
|
283
325
|
"---\n:deploy_name: '#{@app.deploy_name}'"]
|
284
326
|
|
285
327
|
deployed = @app.deployed?
|
@@ -437,7 +479,7 @@ class TestApp < Test::Unit::TestCase
|
|
437
479
|
returned_dirs = %w{old_deploy1 old_deploy2 old_deploy3 main_deploy}
|
438
480
|
old_deploys = returned_dirs[0..-2].map{|d| "#{@app.deploys_path}/#{d}"}
|
439
481
|
|
440
|
-
list_cmd = "ls -
|
482
|
+
list_cmd = "ls -rc1 #{@app.deploys_path}"
|
441
483
|
rm_cmd = "rm -rf #{old_deploys.join(" ")}"
|
442
484
|
|
443
485
|
set_mock_response_for @app, 0,
|
@@ -500,7 +542,7 @@ class TestApp < Test::Unit::TestCase
|
|
500
542
|
|
501
543
|
@app.threaded_each do |server_app|
|
502
544
|
if server_app.shell.host == err_host
|
503
|
-
raise Sunshine::
|
545
|
+
raise Sunshine::DeployError, server_app.shell.host
|
504
546
|
else
|
505
547
|
finished = finished.next
|
506
548
|
end
|
@@ -508,7 +550,7 @@ class TestApp < Test::Unit::TestCase
|
|
508
550
|
|
509
551
|
raise "Didn't raise threaded error when it should have"
|
510
552
|
|
511
|
-
rescue Sunshine::
|
553
|
+
rescue Sunshine::DeployError => e
|
512
554
|
host = @app.server_apps.first.shell.host
|
513
555
|
|
514
556
|
assert_equal host, e.message
|
data/test/unit/test_daemon.rb
CHANGED
@@ -17,9 +17,9 @@ class TestDaemon < Test::Unit::TestCase
|
|
17
17
|
|
18
18
|
begin
|
19
19
|
daemon.start_cmd
|
20
|
-
raise "Should have thrown
|
21
|
-
rescue Sunshine::
|
22
|
-
assert_equal "
|
20
|
+
raise "Should have thrown DaemonError but didn't :("
|
21
|
+
rescue Sunshine::DaemonError => e
|
22
|
+
assert_equal "start_cmd undefined for daemon", e.message
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
data/test/unit/test_nginx.rb
CHANGED
@@ -87,13 +87,16 @@ class TestNginx < Test::Unit::TestCase
|
|
87
87
|
## Helper methods
|
88
88
|
|
89
89
|
def start_cmd svr
|
90
|
-
"#{svr.bin} -c #{svr.config_file_path}"
|
90
|
+
svr.exit_on_failure "#{svr.bin} -c #{svr.config_file_path}", 10,
|
91
|
+
"Could not start #{svr.name} for #{svr.app.name}"
|
91
92
|
end
|
92
93
|
|
93
94
|
|
94
95
|
def stop_cmd svr
|
95
|
-
"test -f #{svr.pid} && kill -#{svr.sigkill} $(cat #{svr.pid}) && "+
|
96
|
-
|
97
|
-
|
96
|
+
cmd = "test -f #{svr.pid} && kill -#{svr.sigkill} $(cat #{svr.pid}) && "+
|
97
|
+
"sleep 1 && rm -f #{svr.pid}"
|
98
|
+
|
99
|
+
svr.exit_on_failure cmd, 11,
|
100
|
+
"Could not kill #{svr.name} pid for #{svr.app.name}"
|
98
101
|
end
|
99
102
|
end
|
data/test/unit/test_server.rb
CHANGED
@@ -69,7 +69,7 @@ class TestServer < Test::Unit::TestCase
|
|
69
69
|
assert sa.method_called?(:install_deps, :args => ["rainbows"])
|
70
70
|
|
71
71
|
assert server.method_called?(:configure_remote_dirs, :args => [sa.shell])
|
72
|
-
assert server.method_called?(:
|
72
|
+
assert server.method_called?(:chown_log_files, :args => [sa.shell])
|
73
73
|
assert server.method_called?(:upload_config_files, :args => [sa.shell])
|
74
74
|
end
|
75
75
|
|
@@ -121,7 +121,7 @@ class TestServer < Test::Unit::TestCase
|
|
121
121
|
|
122
122
|
server.start do |sa|
|
123
123
|
assert_equal @server_app, sa
|
124
|
-
assert_ssh_call server.
|
124
|
+
assert_ssh_call server._start_cmd, sa.shell, :sudo => true
|
125
125
|
end
|
126
126
|
|
127
127
|
assert server.method_called?(:setup)
|
@@ -135,7 +135,7 @@ class TestServer < Test::Unit::TestCase
|
|
135
135
|
|
136
136
|
server.start do |sa|
|
137
137
|
assert_equal @server_app, sa
|
138
|
-
assert_ssh_call server.
|
138
|
+
assert_ssh_call server._start_cmd, sa.shell, :sudo => true
|
139
139
|
end
|
140
140
|
|
141
141
|
assert !server.method_called?(:setup)
|
@@ -147,7 +147,7 @@ class TestServer < Test::Unit::TestCase
|
|
147
147
|
|
148
148
|
server.stop do |sa|
|
149
149
|
assert_equal @server_app, sa
|
150
|
-
assert_ssh_call server.
|
150
|
+
assert_ssh_call server._stop_cmd, sa.shell, :sudo => true
|
151
151
|
end
|
152
152
|
end
|
153
153
|
|
@@ -157,7 +157,7 @@ class TestServer < Test::Unit::TestCase
|
|
157
157
|
|
158
158
|
server.restart do |sa|
|
159
159
|
assert_equal @server_app, sa
|
160
|
-
assert_ssh_call server.
|
160
|
+
assert_ssh_call server._restart_cmd, sa.shell, :sudo => true
|
161
161
|
end
|
162
162
|
end
|
163
163
|
|
@@ -181,7 +181,7 @@ class TestServer < Test::Unit::TestCase
|
|
181
181
|
|
182
182
|
server.restart do |sa|
|
183
183
|
assert_equal @server_app, sa
|
184
|
-
assert_ssh_call server.
|
184
|
+
assert_ssh_call server._restart_cmd, sa.shell, :sudo => true
|
185
185
|
end
|
186
186
|
|
187
187
|
assert server.method_called?(:setup)
|
@@ -15,6 +15,27 @@ class TestServerApp < Test::Unit::TestCase
|
|
15
15
|
end
|
16
16
|
|
17
17
|
|
18
|
+
def test_from_info_file
|
19
|
+
info_data = @sa.get_deploy_info.to_yaml
|
20
|
+
@sa.shell.mock :call, :args => "cat info/path", :return => info_data
|
21
|
+
|
22
|
+
server_app = Sunshine::ServerApp.from_info_file "info/path", @sa.shell
|
23
|
+
|
24
|
+
assert_equal @sa.root_path, server_app.root_path
|
25
|
+
assert_equal @sa.checkout_path, server_app.checkout_path
|
26
|
+
assert_equal @sa.current_path, server_app.current_path
|
27
|
+
assert_equal @sa.deploys_path, server_app.deploys_path
|
28
|
+
assert_equal @sa.log_path, server_app.log_path
|
29
|
+
assert_equal @sa.shared_path, server_app.shared_path
|
30
|
+
assert_equal @sa.scripts_path, server_app.scripts_path
|
31
|
+
assert_equal @sa.roles, server_app.roles
|
32
|
+
|
33
|
+
assert_equal @sa.shell.env, server_app.shell_env
|
34
|
+
assert_equal @sa.name, server_app.name
|
35
|
+
assert_equal @sa.deploy_name, server_app.deploy_name
|
36
|
+
end
|
37
|
+
|
38
|
+
|
18
39
|
def test_init
|
19
40
|
default_info = {:ports => {}}
|
20
41
|
assert_equal default_info, @sa.info
|
@@ -119,7 +140,7 @@ class TestServerApp < Test::Unit::TestCase
|
|
119
140
|
deploy_details = {:item => "thing"}
|
120
141
|
other_details = {:key => "value"}
|
121
142
|
|
122
|
-
@sa.shell.mock :call, :args => ["cat #{@sa.
|
143
|
+
@sa.shell.mock :call, :args => ["cat #{@sa.root_path}/info"],
|
123
144
|
:return => other_details.to_yaml
|
124
145
|
|
125
146
|
@sa.instance_variable_set "@deploy_details", deploy_details
|
@@ -158,8 +179,11 @@ class TestServerApp < Test::Unit::TestCase
|
|
158
179
|
:deployed_as => @sa.shell.call("whoami"),
|
159
180
|
:deployed_by => Sunshine.shell.user,
|
160
181
|
:deploy_name => File.basename(@app.checkout_path),
|
182
|
+
:name => @sa.name,
|
183
|
+
:env => @sa.shell_env,
|
161
184
|
:roles => @sa.roles,
|
162
|
-
:path => @app.root_path
|
185
|
+
:path => @app.root_path,
|
186
|
+
:sunshine_version => Sunshine::VERSION
|
163
187
|
}.merge @sa.info
|
164
188
|
|
165
189
|
deploy_info = @sa.get_deploy_info
|
@@ -204,7 +228,7 @@ class TestServerApp < Test::Unit::TestCase
|
|
204
228
|
@sa.install_deps nginx_dep, :type => Sunshine::Gem
|
205
229
|
raise "Didn't raise missing dependency when it should have."
|
206
230
|
|
207
|
-
rescue Sunshine::
|
231
|
+
rescue Sunshine::MissingDependency => e
|
208
232
|
assert_equal "No dependency 'nginx' [Sunshine::Gem]", e.message
|
209
233
|
end
|
210
234
|
|
@@ -257,7 +281,7 @@ class TestServerApp < Test::Unit::TestCase
|
|
257
281
|
deploys = %w{ploy1 ploy2 ploy3 ploy4 ploy5}
|
258
282
|
|
259
283
|
@sa.shell.mock :call,
|
260
|
-
:args => ["ls -
|
284
|
+
:args => ["ls -rc1 #{@app.deploys_path}"],
|
261
285
|
:return => "#{deploys.join("\n")}\n"
|
262
286
|
|
263
287
|
removed = deploys[0..1].map{|d| "#{@app.deploys_path}/#{d}"}
|
@@ -330,6 +354,32 @@ class TestServerApp < Test::Unit::TestCase
|
|
330
354
|
end
|
331
355
|
|
332
356
|
|
357
|
+
def test_running?
|
358
|
+
set_mock_response_for @sa, 0,
|
359
|
+
"#{@sa.root_path}/status" => [:out, "THE SYSTEM OK!"]
|
360
|
+
|
361
|
+
assert_equal true, @sa.running?
|
362
|
+
end
|
363
|
+
|
364
|
+
|
365
|
+
def test_not_running?
|
366
|
+
set_mock_response_for @sa, 13,
|
367
|
+
"#{@sa.root_path}/status" => [:err, "THE SYSTEM IS DOWN!"]
|
368
|
+
|
369
|
+
assert_equal false, @sa.running?
|
370
|
+
end
|
371
|
+
|
372
|
+
|
373
|
+
def test_errored_running?
|
374
|
+
set_mock_response_for @sa, 1,
|
375
|
+
"#{@sa.root_path}/status" => [:err, "KABLAM!"]
|
376
|
+
|
377
|
+
assert_raises Sunshine::CmdError do
|
378
|
+
@sa.running?
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
|
333
383
|
def test_sass
|
334
384
|
sass_files = %w{file1 file2 file3}
|
335
385
|
|
@@ -426,6 +476,50 @@ class TestServerApp < Test::Unit::TestCase
|
|
426
476
|
end
|
427
477
|
|
428
478
|
|
479
|
+
def test_upload_codebase
|
480
|
+
@sa.shell.mock(:upload)
|
481
|
+
|
482
|
+
@sa.upload_codebase "tmp/thing/", :test_scm => "info"
|
483
|
+
assert_equal({:test_scm => "info"} , @sa.info[:scm])
|
484
|
+
assert @sa.shell.method_called?(
|
485
|
+
:upload, :args => ["tmp/thing/", @sa.checkout_path,
|
486
|
+
{:flags => ["--exclude .svn/","--exclude .git/"]}])
|
487
|
+
end
|
488
|
+
|
489
|
+
|
490
|
+
def test_upload_codebase_with_exclude
|
491
|
+
@sa.shell.mock(:upload)
|
492
|
+
|
493
|
+
@sa.upload_codebase "tmp/thing/",
|
494
|
+
:test_scm => "info",
|
495
|
+
:exclude => "bad/path/"
|
496
|
+
|
497
|
+
assert_equal({:test_scm => "info"} , @sa.info[:scm])
|
498
|
+
assert @sa.shell.method_called?(
|
499
|
+
:upload, :args => ["tmp/thing/", @sa.checkout_path,
|
500
|
+
{:flags => ["--exclude bad/path/",
|
501
|
+
"--exclude .svn/",
|
502
|
+
"--exclude .git/"]}])
|
503
|
+
end
|
504
|
+
|
505
|
+
|
506
|
+
def test_upload_codebase_with_excludes
|
507
|
+
@sa.shell.mock(:upload)
|
508
|
+
|
509
|
+
@sa.upload_codebase "tmp/thing/",
|
510
|
+
:test_scm => "info",
|
511
|
+
:exclude => ["bad/path/", "other/exclude/"]
|
512
|
+
|
513
|
+
assert_equal({:test_scm => "info"} , @sa.info[:scm])
|
514
|
+
assert @sa.shell.method_called?(
|
515
|
+
:upload, :args => ["tmp/thing/", @sa.checkout_path,
|
516
|
+
{:flags => ["--exclude bad/path/",
|
517
|
+
"--exclude other/exclude/",
|
518
|
+
"--exclude .svn/",
|
519
|
+
"--exclude .git/"]}])
|
520
|
+
end
|
521
|
+
|
522
|
+
|
429
523
|
def test_write_script
|
430
524
|
@sa.shell.mock :file?, :return => false
|
431
525
|
|
@@ -435,10 +529,19 @@ class TestServerApp < Test::Unit::TestCase
|
|
435
529
|
"script contents", {:flags => "--chmod=ugo=rwx"}]
|
436
530
|
|
437
531
|
assert @sa.shell.method_called?(:make_file, :args => args)
|
532
|
+
end
|
533
|
+
|
534
|
+
|
535
|
+
def test_symlink_scripts_to_root
|
536
|
+
@sa.shell.mock :call,
|
537
|
+
:args => ["ls -1 #{@sa.scripts_path}"],
|
538
|
+
:return => "script_name\n"
|
438
539
|
|
439
540
|
args = ["#{@app.scripts_path}/script_name",
|
440
541
|
"#{@app.root_path}/script_name"]
|
441
542
|
|
543
|
+
@sa.symlink_scripts_to_root
|
544
|
+
|
442
545
|
assert @sa.shell.method_called?(:symlink, :args => args)
|
443
546
|
end
|
444
547
|
|
@@ -452,10 +555,5 @@ class TestServerApp < Test::Unit::TestCase
|
|
452
555
|
"script contents", {:flags => "--chmod=ugo=rwx"}]
|
453
556
|
|
454
557
|
assert !@sa.shell.method_called?(:make_file, :args => args)
|
455
|
-
|
456
|
-
args = ["#{@app.scripts_path}/script_name",
|
457
|
-
"#{@app.root_path}/script_name"]
|
458
|
-
|
459
|
-
assert @sa.shell.method_called?(:symlink, :args => args)
|
460
558
|
end
|
461
559
|
end
|