sunshine 1.0.0.pre
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 +237 -0
- data/Manifest.txt +70 -0
- data/README.txt +277 -0
- data/Rakefile +46 -0
- data/bin/sunshine +5 -0
- data/examples/deploy.rb +61 -0
- data/examples/deploy_tasks.rake +112 -0
- data/examples/standalone_deploy.rb +31 -0
- data/lib/commands/add.rb +96 -0
- data/lib/commands/default.rb +169 -0
- data/lib/commands/list.rb +322 -0
- data/lib/commands/restart.rb +62 -0
- data/lib/commands/rm.rb +83 -0
- data/lib/commands/run.rb +151 -0
- data/lib/commands/start.rb +72 -0
- data/lib/commands/stop.rb +61 -0
- data/lib/sunshine/app.rb +876 -0
- data/lib/sunshine/binder.rb +70 -0
- data/lib/sunshine/crontab.rb +143 -0
- data/lib/sunshine/daemon.rb +380 -0
- data/lib/sunshine/daemons/ar_sendmail.rb +28 -0
- data/lib/sunshine/daemons/delayed_job.rb +30 -0
- data/lib/sunshine/daemons/nginx.rb +104 -0
- data/lib/sunshine/daemons/rainbows.rb +35 -0
- data/lib/sunshine/daemons/server.rb +66 -0
- data/lib/sunshine/daemons/unicorn.rb +26 -0
- data/lib/sunshine/dependencies.rb +103 -0
- data/lib/sunshine/dependency_lib.rb +200 -0
- data/lib/sunshine/exceptions.rb +54 -0
- data/lib/sunshine/healthcheck.rb +83 -0
- data/lib/sunshine/output.rb +131 -0
- data/lib/sunshine/package_managers/apt.rb +48 -0
- data/lib/sunshine/package_managers/dependency.rb +349 -0
- data/lib/sunshine/package_managers/gem.rb +54 -0
- data/lib/sunshine/package_managers/yum.rb +62 -0
- data/lib/sunshine/remote_shell.rb +241 -0
- data/lib/sunshine/repo.rb +128 -0
- data/lib/sunshine/repos/git_repo.rb +122 -0
- data/lib/sunshine/repos/rsync_repo.rb +29 -0
- data/lib/sunshine/repos/svn_repo.rb +78 -0
- data/lib/sunshine/server_app.rb +554 -0
- data/lib/sunshine/shell.rb +384 -0
- data/lib/sunshine.rb +391 -0
- data/templates/logrotate/logrotate.conf.erb +11 -0
- data/templates/nginx/nginx.conf.erb +109 -0
- data/templates/nginx/nginx_optimize.conf +23 -0
- data/templates/nginx/nginx_proxy.conf +13 -0
- data/templates/rainbows/rainbows.conf.erb +18 -0
- data/templates/tasks/sunshine.rake +114 -0
- data/templates/unicorn/unicorn.conf.erb +6 -0
- data/test/fixtures/app_configs/test_app.yml +11 -0
- data/test/fixtures/sunshine_test/test_upload +0 -0
- data/test/mocks/mock_object.rb +179 -0
- data/test/mocks/mock_open4.rb +117 -0
- data/test/test_helper.rb +188 -0
- data/test/unit/test_app.rb +489 -0
- data/test/unit/test_binder.rb +20 -0
- data/test/unit/test_crontab.rb +128 -0
- data/test/unit/test_git_repo.rb +26 -0
- data/test/unit/test_healthcheck.rb +70 -0
- data/test/unit/test_nginx.rb +107 -0
- data/test/unit/test_rainbows.rb +26 -0
- data/test/unit/test_remote_shell.rb +102 -0
- data/test/unit/test_repo.rb +42 -0
- data/test/unit/test_server.rb +324 -0
- data/test/unit/test_server_app.rb +425 -0
- data/test/unit/test_shell.rb +97 -0
- data/test/unit/test_sunshine.rb +157 -0
- data/test/unit/test_svn_repo.rb +55 -0
- data/test/unit/test_unicorn.rb +22 -0
- metadata +217 -0
@@ -0,0 +1,489 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class TestApp < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
mock_remote_shell_popen4
|
7
|
+
@svn_url = "svn://subversion/path/to/app_name/trunk"
|
8
|
+
|
9
|
+
@config = {:name => "app_name",
|
10
|
+
:repo => {:type => "svn", :url => @svn_url},
|
11
|
+
:remote_shells => ["user@some_server.com"],
|
12
|
+
:root_path => "/usr/local/my_user/app_name"}
|
13
|
+
|
14
|
+
@app = Sunshine::App.new @config
|
15
|
+
@app.each do |server_app|
|
16
|
+
server_app.extend MockObject
|
17
|
+
server_app.shell.extend MockObject
|
18
|
+
end
|
19
|
+
|
20
|
+
@tmpdir = File.join Dir.tmpdir, "test_sunshine_#{$$}"
|
21
|
+
|
22
|
+
mock_svn_response @app.repo.url
|
23
|
+
end
|
24
|
+
|
25
|
+
def teardown
|
26
|
+
FileUtils.rm_f @tmpdir
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def test_initialize_without_name
|
31
|
+
app = Sunshine::App.new :repo => {:type => "svn", :url => @svn_url},
|
32
|
+
:remote_shells => ["user@some_server.com"]
|
33
|
+
|
34
|
+
assert_equal "app_name", app.name
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def test_initialize_with_config_file
|
39
|
+
app = Sunshine::App.new TEST_APP_CONFIG_FILE
|
40
|
+
config = YAML.load_file(TEST_APP_CONFIG_FILE)[:default]
|
41
|
+
assert_attributes_equal config, app
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
def test_initialize_with_file_object
|
46
|
+
file = File.open TEST_APP_CONFIG_FILE
|
47
|
+
app = Sunshine::App.new file
|
48
|
+
config = YAML.load_file(TEST_APP_CONFIG_FILE)[:default]
|
49
|
+
assert_attributes_equal config, app
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def test_initialize_with_options
|
54
|
+
assert_attributes_equal @config, @app
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def test_initialize_with_options_and_config_file
|
59
|
+
app = Sunshine::App.new TEST_APP_CONFIG_FILE, @config
|
60
|
+
assert_attributes_equal @config, app
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
def test_app_deploy
|
65
|
+
yield_called = false
|
66
|
+
|
67
|
+
@app.deploy do |app|
|
68
|
+
assert app.connected?
|
69
|
+
|
70
|
+
yield_called = true
|
71
|
+
end
|
72
|
+
|
73
|
+
assert !@app.connected?
|
74
|
+
|
75
|
+
setup_cmd =
|
76
|
+
"test -d #{@app.checkout_path} && rm -rf #{@app.checkout_path}"+
|
77
|
+
" || echo false"
|
78
|
+
|
79
|
+
mkdir_cmd = "mkdir -p #{@app.checkout_path}"
|
80
|
+
|
81
|
+
checkout_cmd = "svn checkout " +
|
82
|
+
"#{@app.repo.scm_flags} #{@app.repo.url} #{@app.checkout_path}"
|
83
|
+
|
84
|
+
run_results = [
|
85
|
+
"mkdir -p #{@app.server_apps.first.directories.join(" ")}",
|
86
|
+
setup_cmd,
|
87
|
+
mkdir_cmd,
|
88
|
+
checkout_cmd,
|
89
|
+
"ln -sfT #{@app.checkout_path} #{@app.current_path}"
|
90
|
+
]
|
91
|
+
|
92
|
+
|
93
|
+
@app.each do |server_app|
|
94
|
+
use_remote_shell server_app.shell
|
95
|
+
|
96
|
+
run_results.each_index do |i|
|
97
|
+
assert_ssh_call run_results[i]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
assert yield_called
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
TEST_CONFIG = <<-STR
|
106
|
+
:conf1:
|
107
|
+
:common: "conf1"
|
108
|
+
:from_conf1: true
|
109
|
+
:not_conf4: "conf1"
|
110
|
+
|
111
|
+
:conf2:
|
112
|
+
:inherits: :conf1
|
113
|
+
:common: "conf2"
|
114
|
+
:from_conf2: true
|
115
|
+
:not_conf4: "conf2"
|
116
|
+
|
117
|
+
:conf3:
|
118
|
+
:common: "conf3"
|
119
|
+
:from_conf3: true
|
120
|
+
:not_conf4: "conf3"
|
121
|
+
|
122
|
+
:conf4:
|
123
|
+
:inherits:
|
124
|
+
- :conf2
|
125
|
+
- :conf3
|
126
|
+
:common: "conf4"
|
127
|
+
:from_conf4: true
|
128
|
+
STR
|
129
|
+
|
130
|
+
def test_merge_config_inheritance
|
131
|
+
all_configs = YAML.load TEST_CONFIG
|
132
|
+
main_conf = all_configs[:conf2]
|
133
|
+
|
134
|
+
main_conf = @app.send(:merge_config_inheritance, main_conf, all_configs)
|
135
|
+
|
136
|
+
assert main_conf[:from_conf1]
|
137
|
+
assert_equal "conf2", main_conf[:common]
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
def test_multiple_merge_config_inheritance
|
142
|
+
all_configs = YAML.load TEST_CONFIG
|
143
|
+
main_conf = all_configs[:conf4]
|
144
|
+
|
145
|
+
main_conf = @app.send(:merge_config_inheritance, main_conf, all_configs)
|
146
|
+
|
147
|
+
assert main_conf[:from_conf1]
|
148
|
+
assert main_conf[:from_conf2]
|
149
|
+
assert main_conf[:from_conf3]
|
150
|
+
assert_equal "conf4", main_conf[:common]
|
151
|
+
assert_equal "conf3", main_conf[:not_conf4]
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
class MockError < Exception; end
|
156
|
+
|
157
|
+
def test_app_deploy_error_handling
|
158
|
+
[ MockError,
|
159
|
+
Sunshine::CriticalDeployError,
|
160
|
+
Sunshine::FatalDeployError ].each do |error|
|
161
|
+
|
162
|
+
begin
|
163
|
+
app = Sunshine::App.deploy @config do |app|
|
164
|
+
raise error, "#{error} was not caught"
|
165
|
+
end
|
166
|
+
|
167
|
+
rescue MockError => e
|
168
|
+
assert_equal MockError, e.class
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
|
174
|
+
def test_revert
|
175
|
+
set_mock_response_for @app, 0,
|
176
|
+
"ls -rc1 #{@app.deploys_path}" => [:out, "last_deploy_dir"]
|
177
|
+
|
178
|
+
@app.revert!
|
179
|
+
|
180
|
+
@app.each do |sa|
|
181
|
+
use_remote_shell sa.shell
|
182
|
+
|
183
|
+
assert_ssh_call "rm -rf #{@app.checkout_path}"
|
184
|
+
|
185
|
+
assert_ssh_call "ls -rc1 #{@app.deploys_path}"
|
186
|
+
|
187
|
+
last_deploy = "#{@app.deploys_path}/last_deploy_dir"
|
188
|
+
assert_ssh_call "ln -sfT #{last_deploy} #{@app.current_path}"
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
|
193
|
+
def test_build_control_scripts
|
194
|
+
@app.add_to_script :start, "start script"
|
195
|
+
@app.add_to_script :stop, "stop script"
|
196
|
+
@app.add_to_script :custom, "custom script"
|
197
|
+
|
198
|
+
@app.build_control_scripts
|
199
|
+
|
200
|
+
each_remote_shell do |ds|
|
201
|
+
|
202
|
+
%w{start stop restart custom env}.each do |script|
|
203
|
+
assert_rsync(/#{script}/, "#{ds.host}:#{@app.checkout_path}/#{script}")
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
def test_build_deploy_info_file
|
210
|
+
@app.build_deploy_info_file
|
211
|
+
|
212
|
+
each_remote_shell do |ds|
|
213
|
+
assert_rsync(/info/, "#{ds.host}:#{@app.checkout_path}/info")
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
|
218
|
+
def test_build_erb
|
219
|
+
erb_file = File.join(@tmpdir, "tmp.erb")
|
220
|
+
|
221
|
+
FileUtils.mkdir_p @tmpdir
|
222
|
+
File.open(erb_file, "w+") do |f|
|
223
|
+
f.write "<%= name %>"
|
224
|
+
end
|
225
|
+
|
226
|
+
name = "test name"
|
227
|
+
|
228
|
+
local_name = @app.build_erb(erb_file, binding)
|
229
|
+
app_name = @app.build_erb(erb_file)
|
230
|
+
|
231
|
+
assert_equal name, local_name
|
232
|
+
assert_equal @app.name, app_name
|
233
|
+
end
|
234
|
+
|
235
|
+
|
236
|
+
def test_checkout_codebase
|
237
|
+
@app.checkout_codebase
|
238
|
+
|
239
|
+
each_remote_shell do |ds|
|
240
|
+
path = @app.checkout_path
|
241
|
+
setup_cmd = "test -d #{path} && rm -rf #{path} || echo false"
|
242
|
+
|
243
|
+
url = @app.repo.url
|
244
|
+
flags = @app.repo.scm_flags
|
245
|
+
checkout_cmd =
|
246
|
+
"svn checkout #{flags} #{url} #{path}"
|
247
|
+
|
248
|
+
assert_ssh_call setup_cmd
|
249
|
+
assert_ssh_call checkout_cmd
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
|
254
|
+
def test_deployed?
|
255
|
+
deployed = @app.deployed?
|
256
|
+
|
257
|
+
state = true
|
258
|
+
@app.server_apps.each do |sa|
|
259
|
+
assert sa.method_called? :deployed?
|
260
|
+
state = false unless sa.deployed?
|
261
|
+
end
|
262
|
+
|
263
|
+
assert_equal state, deployed
|
264
|
+
end
|
265
|
+
|
266
|
+
|
267
|
+
def test_install_deps
|
268
|
+
nginx_dep = Sunshine.dependencies.get 'nginx'
|
269
|
+
ruby_dep = Sunshine.dependencies.get 'ruby'
|
270
|
+
|
271
|
+
yum_sudo = Sunshine::Yum.sudo
|
272
|
+
|
273
|
+
check_nginx = "test \"$(yum list installed #{nginx_dep.pkg} | "+
|
274
|
+
"grep -c #{nginx_dep.pkg})\" -ge 1"
|
275
|
+
check_ruby = "test \"$(yum list installed #{ruby_dep.pkg} | "+
|
276
|
+
"grep -c #{ruby_dep.pkg})\" -ge 1"
|
277
|
+
|
278
|
+
|
279
|
+
set_mock_response_for @app, 1,
|
280
|
+
{check_nginx => [:err, ""],
|
281
|
+
check_ruby => [:err, ""]},
|
282
|
+
{:sudo => yum_sudo}
|
283
|
+
|
284
|
+
@app.install_deps 'ruby', nginx_dep
|
285
|
+
|
286
|
+
|
287
|
+
each_remote_shell do |ds|
|
288
|
+
[nginx_dep, ruby_dep].each do |dep|
|
289
|
+
check =
|
290
|
+
"test \"$(yum list installed #{dep.pkg} | grep -c #{dep.pkg})\" -ge 1"
|
291
|
+
install = dep.instance_variable_get "@install"
|
292
|
+
|
293
|
+
assert_ssh_call check, ds, :sudo => yum_sudo
|
294
|
+
assert_ssh_call install, ds, :sudo => yum_sudo
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
|
300
|
+
def test_install_gem_deps
|
301
|
+
rake_dep = Sunshine.dependencies.get 'rake'
|
302
|
+
bundler_dep = Sunshine.dependencies.get 'bundler'
|
303
|
+
|
304
|
+
gem_sudo = Sunshine::Gem.sudo
|
305
|
+
|
306
|
+
checks = {
|
307
|
+
rake_dep => "gem list #{rake_dep.pkg} -i --version '>=0.8'",
|
308
|
+
bundler_dep => "gem list #{bundler_dep.pkg} -i --version '>=0.9'"
|
309
|
+
}
|
310
|
+
|
311
|
+
checks.values.each do |check|
|
312
|
+
set_mock_response_for @app, 1, {check => [:err, ""]}, {:sudo => gem_sudo}
|
313
|
+
end
|
314
|
+
|
315
|
+
@app.install_deps 'rake', bundler_dep
|
316
|
+
|
317
|
+
|
318
|
+
each_remote_shell do |ds|
|
319
|
+
[rake_dep, bundler_dep].each do |dep|
|
320
|
+
|
321
|
+
install = dep.instance_variable_get "@install"
|
322
|
+
|
323
|
+
assert_ssh_call checks[dep], ds, :sudo => gem_sudo
|
324
|
+
assert_ssh_call install, ds, :sudo => gem_sudo
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
|
330
|
+
def test_make_app_directories
|
331
|
+
@app.make_app_directories
|
332
|
+
|
333
|
+
each_remote_shell do |ds|
|
334
|
+
assert_ssh_call "mkdir -p #{@app.server_apps.first.directories.join(" ")}"
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
|
339
|
+
def test_rake
|
340
|
+
@app.rake("test:task")
|
341
|
+
|
342
|
+
each_remote_shell do |ds|
|
343
|
+
assert_ssh_call "cd #{@app.checkout_path} && rake test:task"
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
|
348
|
+
def test_register_as_deployed
|
349
|
+
@app.register_as_deployed
|
350
|
+
|
351
|
+
each_remote_shell do |ds|
|
352
|
+
assert_ssh_call "test -d #{@app.root_path}"
|
353
|
+
|
354
|
+
yml_list = {@app.name => @app.root_path}.to_yaml
|
355
|
+
path = ds.expand_path(Sunshine::APP_LIST_PATH)
|
356
|
+
|
357
|
+
assert ds.method_called?(:make_file, :args => [path, yml_list])
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
|
362
|
+
def test_remove_old_deploys
|
363
|
+
returned_dirs = %w{old_deploy1 old_deploy2 old_deploy3 main_deploy}
|
364
|
+
old_deploys = returned_dirs[0..-2].map{|d| "#{@app.deploys_path}/#{d}"}
|
365
|
+
|
366
|
+
list_cmd = "ls -1 #{@app.deploys_path}"
|
367
|
+
rm_cmd = "rm -rf #{old_deploys.join(" ")}"
|
368
|
+
|
369
|
+
set_mock_response_for @app, 0,
|
370
|
+
list_cmd => [:out, returned_dirs.join("\n")]
|
371
|
+
|
372
|
+
Sunshine.setup 'max_deploy_versions' => 1
|
373
|
+
|
374
|
+
@app.remove_old_deploys
|
375
|
+
|
376
|
+
each_remote_shell do |ds|
|
377
|
+
assert_ssh_call list_cmd
|
378
|
+
assert_ssh_call rm_cmd
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
|
383
|
+
def test_run_post_user_lambdas
|
384
|
+
lambdas_ran = 0
|
385
|
+
count = 5
|
386
|
+
|
387
|
+
count.times do
|
388
|
+
@app.after_user_script do |app|
|
389
|
+
lambdas_ran = lambdas_ran.next
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
assert_equal 0, lambdas_ran
|
394
|
+
|
395
|
+
@app.run_post_user_lambdas
|
396
|
+
|
397
|
+
assert_equal count, lambdas_ran
|
398
|
+
end
|
399
|
+
|
400
|
+
|
401
|
+
def test_shell_env
|
402
|
+
new_env = {
|
403
|
+
"PATH" => "/etc/lib:$PATH",
|
404
|
+
"RACK_ENV" => "test",
|
405
|
+
"RAILS_ENV" => "test"
|
406
|
+
}
|
407
|
+
|
408
|
+
@app.shell_env new_env
|
409
|
+
|
410
|
+
assert_equal new_env, @app.shell_env
|
411
|
+
end
|
412
|
+
|
413
|
+
|
414
|
+
def test_symlink_current_dir
|
415
|
+
@app.symlink_current_dir
|
416
|
+
|
417
|
+
each_remote_shell do |ds|
|
418
|
+
assert_ssh_call "ln -sfT #{@app.checkout_path} #{@app.current_path}"
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
|
423
|
+
def test_upload_tasks
|
424
|
+
path = "/path/to/tasks"
|
425
|
+
|
426
|
+
@app.upload_tasks 'common', 'tpkg',
|
427
|
+
:host => 'some_server.com',
|
428
|
+
:remote_path => path
|
429
|
+
|
430
|
+
each_remote_shell do |ds|
|
431
|
+
assert_ssh_call "mkdir -p /path/to/tasks"
|
432
|
+
|
433
|
+
%w{common tpkg}.each do |task|
|
434
|
+
from = "#{Sunshine::ROOT}/templates/tasks/#{task}.rake"
|
435
|
+
to = "#{ds.host}:#{path}/#{task}.rake"
|
436
|
+
|
437
|
+
assert_rsync from, to
|
438
|
+
end
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
442
|
+
|
443
|
+
def test_upload_tasks_simple
|
444
|
+
@app.upload_tasks
|
445
|
+
|
446
|
+
path = "#{@app.checkout_path}/lib/tasks"
|
447
|
+
|
448
|
+
tasks =
|
449
|
+
Dir.glob("#{Sunshine::ROOT}/templates/tasks/*").map{|t| File.basename t}
|
450
|
+
|
451
|
+
each_remote_shell do |ds|
|
452
|
+
assert_ssh_call "mkdir -p #{path}"
|
453
|
+
|
454
|
+
tasks.each do |task|
|
455
|
+
from = "#{Sunshine::ROOT}/templates/tasks/#{task}"
|
456
|
+
to = "#{ds.host}:#{path}/#{task}"
|
457
|
+
|
458
|
+
assert_rsync from, to
|
459
|
+
end
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
|
464
|
+
def test_sudo_assignment
|
465
|
+
@app.sudo = "someuser"
|
466
|
+
|
467
|
+
@app.each do |server_app|
|
468
|
+
assert_equal "someuser", server_app.shell.sudo
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
|
473
|
+
private
|
474
|
+
|
475
|
+
|
476
|
+
def assert_attributes_equal(attr_hash, app)
|
477
|
+
assert_equal attr_hash[:name], app.name
|
478
|
+
assert_equal attr_hash[:repo][:url], app.repo.url
|
479
|
+
assert_equal attr_hash[:root_path], app.root_path
|
480
|
+
|
481
|
+
attr_hash[:remote_shells].each_with_index do |server_def, i|
|
482
|
+
server_def = server_def.first if Array === server_def
|
483
|
+
user, host = server_def.split("@")
|
484
|
+
assert_equal host, app.server_apps[i].shell.host
|
485
|
+
assert_equal user, app.server_apps[i].shell.user
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class TestBinder < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@target = [1,2,3]
|
7
|
+
@binder = Sunshine::Binder.new @target
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_set
|
11
|
+
@binder.set :blah, "somevalue"
|
12
|
+
assert_equal "somevalue", @binder.blah
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_forward
|
16
|
+
@binder.forward :join, :length
|
17
|
+
assert_equal @target.join(" "), @binder.join(" ")
|
18
|
+
assert_equal @target.length, @binder.length
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class TestCrontab < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@crontab_str = <<-STR
|
7
|
+
# sunshine crontest:job1:begin
|
8
|
+
this job should stay
|
9
|
+
# sunshine crontest:job1:end
|
10
|
+
|
11
|
+
# sunshine crontest:job2:begin
|
12
|
+
job2 part 1
|
13
|
+
# sunshine crontest:job2:end
|
14
|
+
|
15
|
+
# sunshine otherapp:blah:begin
|
16
|
+
otherapp blah job
|
17
|
+
# sunshine otherapp:blah:end
|
18
|
+
|
19
|
+
# sunshine crontest:job2:begin
|
20
|
+
job2 part 2
|
21
|
+
# sunshine crontest:job2:end
|
22
|
+
|
23
|
+
# sunshine otherapp:job1:begin
|
24
|
+
job for otherapp
|
25
|
+
# sunshine otherapp:job1:end
|
26
|
+
STR
|
27
|
+
|
28
|
+
@shell = mock_remote_shell
|
29
|
+
|
30
|
+
@cron = Sunshine::Crontab.new "crontest", @shell
|
31
|
+
|
32
|
+
@othercron = Sunshine::Crontab.new "otherapp", @shell
|
33
|
+
|
34
|
+
@shell.set_mock_response 0, "crontab -l" => [:out, @crontab_str]
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def test_parse
|
39
|
+
jobs = @cron.parse @crontab_str
|
40
|
+
assert_equal "this job should stay\n", jobs['job1']
|
41
|
+
assert_equal "job2 part 1\njob2 part 2\n", jobs['job2']
|
42
|
+
assert jobs['blah'].nil?
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
def test_build
|
47
|
+
@cron.jobs["job2"] << "new job2"
|
48
|
+
@cron.jobs["job3"] = "new job3"
|
49
|
+
|
50
|
+
@cron.build @crontab_str
|
51
|
+
|
52
|
+
assert_cronjob "job1", "this job should stay"
|
53
|
+
assert_cronjob "job2", "job2 part 1\njob2 part 2\nnew job2"
|
54
|
+
assert_cronjob "job3", "new job3"
|
55
|
+
|
56
|
+
assert_cronjob "blah", "otherapp blah job", @othercron
|
57
|
+
assert_cronjob "job1", "job for otherapp", @othercron
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def test_delete!
|
62
|
+
assert_cronjob "blah", "otherapp blah job", @othercron
|
63
|
+
assert_cronjob "job1", "job for otherapp", @othercron
|
64
|
+
|
65
|
+
@crontab_str = @othercron.delete!
|
66
|
+
|
67
|
+
assert !@crontab_str.include?("job for otherapp")
|
68
|
+
assert !@crontab_str.include?("otherapp blah job")
|
69
|
+
|
70
|
+
assert_cronjob "job1", "this job should stay"
|
71
|
+
assert_cronjob "job2", "job2 part 1"
|
72
|
+
assert_cronjob "job2", "job2 part 2"
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
def test_write!
|
77
|
+
@cron.jobs["job2"] << "new job2"
|
78
|
+
@cron.jobs["job3"] = "new job3"
|
79
|
+
|
80
|
+
@shell.set_mock_response 0, "crontab -l" => [:out, @crontab_str]
|
81
|
+
|
82
|
+
@crontab_str = @cron.write!
|
83
|
+
|
84
|
+
assert_cronjob "job1", "this job should stay"
|
85
|
+
assert_cronjob "job2", "job2 part 1\njob2 part 2\nnew job2"
|
86
|
+
assert_cronjob "job3", "new job3"
|
87
|
+
|
88
|
+
assert_cronjob "blah", "otherapp blah job", @othercron
|
89
|
+
assert_cronjob "job1", "job for otherapp", @othercron
|
90
|
+
|
91
|
+
cmd = "echo '#{@crontab_str.gsub(/'/){|s| "'\\''"}}' | crontab"
|
92
|
+
|
93
|
+
assert_ssh_call cmd
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
def test_deleted_jobs_write!
|
98
|
+
@cron.jobs.delete "job1"
|
99
|
+
|
100
|
+
@shell.set_mock_response 0, "crontab -l" => [:out, @crontab_str]
|
101
|
+
|
102
|
+
@crontab_str = @cron.write!
|
103
|
+
|
104
|
+
assert !@crontab_str.include?("this job should stay")
|
105
|
+
assert_cronjob "job2", "job2 part 1\njob2 part 2"
|
106
|
+
|
107
|
+
assert_cronjob "blah", "otherapp blah job", @othercron
|
108
|
+
assert_cronjob "job1", "job for otherapp", @othercron
|
109
|
+
|
110
|
+
cmd = "echo '#{@crontab_str.gsub(/'/){|s| "'\\''"}}' | crontab"
|
111
|
+
|
112
|
+
assert_ssh_call cmd
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
def assert_cronjob namespace, job, crontab=@cron
|
117
|
+
assert @crontab_str.include?(cronjob(namespace, job, crontab))
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
def cronjob namespace, job, crontab
|
122
|
+
<<-STR
|
123
|
+
# sunshine #{crontab.name}:#{namespace}:begin
|
124
|
+
#{job}
|
125
|
+
# sunshine #{crontab.name}:#{namespace}:end
|
126
|
+
STR
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class TestGitRepo < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def test_name
|
6
|
+
git = Sunshine::GitRepo.new "git://myrepo/project.git"
|
7
|
+
assert_equal "project", git.name
|
8
|
+
|
9
|
+
git = Sunshine::GitRepo.new "ssh://user@host.xz:456/path/to/project.git"
|
10
|
+
assert_equal "project", git.name
|
11
|
+
|
12
|
+
git = Sunshine::GitRepo.new "user@host.xz:~user/path/to/project.git"
|
13
|
+
assert_equal "project", git.name
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def test_invalid_name
|
18
|
+
git = Sunshine::GitRepo.new "project.git"
|
19
|
+
git.name
|
20
|
+
raise "GitRepo didn't catch invalid naming scheme: #{git.url}"
|
21
|
+
rescue => e
|
22
|
+
assert_equal "Git url must match #{Sunshine::GitRepo::NAME_MATCH.inspect}",
|
23
|
+
e.message
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|