sunshine 1.0.0.pre → 1.0.0
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 +6 -0
- data/Manifest.txt +5 -1
- data/lib/commands/default.rb +32 -4
- data/lib/sunshine.rb +14 -4
- data/lib/sunshine/daemon.rb +4 -0
- data/lib/sunshine/daemons/apache.rb +37 -0
- data/lib/sunshine/daemons/nginx.rb +3 -85
- data/lib/sunshine/daemons/server.rb +62 -2
- data/lib/sunshine/daemons/unicorn.rb +3 -7
- data/lib/sunshine/dependencies.rb +40 -10
- data/lib/sunshine/healthcheck.rb +15 -0
- data/lib/sunshine/repo.rb +1 -4
- data/lib/sunshine/server_app.rb +4 -1
- data/templates/apache/apache.conf.erb +54 -0
- data/templates/nginx/nginx.conf.erb +3 -3
- data/templates/sunshine/middleware/health.rb +58 -0
- data/templates/{tasks → sunshine}/sunshine.rake +0 -0
- data/test/test_helper.rb +2 -0
- data/test/unit/test_daemon.rb +33 -0
- data/test/unit/test_nginx.rb +13 -9
- data/test/unit/test_server.rb +0 -19
- data/test/unit/test_sunshine.rb +7 -1
- metadata +43 -13
data/History.txt
CHANGED
@@ -2,6 +2,12 @@
|
|
2
2
|
|
3
3
|
* Improvements:
|
4
4
|
|
5
|
+
* Added auto_dependencies config to turn on/off auto installing things.
|
6
|
+
|
7
|
+
* Added healthcheck middleware support.
|
8
|
+
|
9
|
+
* Added support for Apache2 and its passenger implementation.
|
10
|
+
|
5
11
|
* Removed all Atti-specific code for public release.
|
6
12
|
|
7
13
|
* Bugfixes:
|
data/Manifest.txt
CHANGED
@@ -19,6 +19,7 @@ lib/sunshine/app.rb
|
|
19
19
|
lib/sunshine/binder.rb
|
20
20
|
lib/sunshine/crontab.rb
|
21
21
|
lib/sunshine/daemon.rb
|
22
|
+
lib/sunshine/daemons/apache.rb
|
22
23
|
lib/sunshine/daemons/ar_sendmail.rb
|
23
24
|
lib/sunshine/daemons/delayed_job.rb
|
24
25
|
lib/sunshine/daemons/nginx.rb
|
@@ -41,12 +42,14 @@ lib/sunshine/repos/rsync_repo.rb
|
|
41
42
|
lib/sunshine/repos/svn_repo.rb
|
42
43
|
lib/sunshine/server_app.rb
|
43
44
|
lib/sunshine/shell.rb
|
45
|
+
templates/apache/apache.conf.erb
|
44
46
|
templates/logrotate/logrotate.conf.erb
|
45
47
|
templates/nginx/nginx.conf.erb
|
46
48
|
templates/nginx/nginx_optimize.conf
|
47
49
|
templates/nginx/nginx_proxy.conf
|
48
50
|
templates/rainbows/rainbows.conf.erb
|
49
|
-
templates/
|
51
|
+
templates/sunshine/middleware/health.rb
|
52
|
+
templates/sunshine/sunshine.rake
|
50
53
|
templates/unicorn/unicorn.conf.erb
|
51
54
|
test/fixtures/app_configs/test_app.yml
|
52
55
|
test/fixtures/sunshine_test/test_upload
|
@@ -56,6 +59,7 @@ test/test_helper.rb
|
|
56
59
|
test/unit/test_app.rb
|
57
60
|
test/unit/test_binder.rb
|
58
61
|
test/unit/test_crontab.rb
|
62
|
+
test/unit/test_daemon.rb
|
59
63
|
test/unit/test_git_repo.rb
|
60
64
|
test/unit/test_healthcheck.rb
|
61
65
|
test/unit/test_nginx.rb
|
data/lib/commands/default.rb
CHANGED
@@ -15,13 +15,35 @@ module Sunshine
|
|
15
15
|
# and optionally an accompanying message.
|
16
16
|
|
17
17
|
def self.exec argv, config
|
18
|
-
template_rakefile = "#{Sunshine::ROOT}/templates/tasks/sunshine.rake"
|
19
18
|
|
20
|
-
|
19
|
+
copy_rakefile(config['rakefile']) if config.has_key? 'rakefile'
|
20
|
+
copy_middleware(config['middleware']) if config.has_key? 'middleware'
|
21
21
|
|
22
|
-
|
22
|
+
return true
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
##
|
27
|
+
# Copy template rakefile to specified location.
|
23
28
|
|
24
|
-
|
29
|
+
def self.copy_rakefile path
|
30
|
+
template_rakefile = "#{Sunshine::ROOT}/templates/sunshine/sunshine.rake"
|
31
|
+
|
32
|
+
FileUtils.cp template_rakefile, path
|
33
|
+
|
34
|
+
puts "Copied Sunshine template rakefile to #{path}"
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
##
|
39
|
+
# Copy middleware to specified location.
|
40
|
+
|
41
|
+
def self.copy_middleware path
|
42
|
+
middleware_dir = "#{Sunshine::ROOT}/templates/sunshine/middleware/."
|
43
|
+
|
44
|
+
FileUtils.cp_r middleware_dir, path
|
45
|
+
|
46
|
+
puts "Copied Sunshine middleware to #{path}"
|
25
47
|
end
|
26
48
|
|
27
49
|
|
@@ -83,6 +105,12 @@ Sunshine is an object oriented deploy tool for rack applications.
|
|
83
105
|
options['rakefile'] = path || File.join(Dir.pwd, "sunshine.rake")
|
84
106
|
end
|
85
107
|
|
108
|
+
opt.on('--middleware [PATH]',
|
109
|
+
'Copy Sunshine rack middleware files.') do |path|
|
110
|
+
options['middleware'] =
|
111
|
+
path || File.join(Dir.pwd, ".")
|
112
|
+
end
|
113
|
+
|
86
114
|
opt.separator nil
|
87
115
|
opt.separator "For more help on sunshine commands, "+
|
88
116
|
"use '#{opt.program_name} COMMAND --help'"
|
data/lib/sunshine.rb
CHANGED
@@ -72,7 +72,7 @@ module Sunshine
|
|
72
72
|
|
73
73
|
##
|
74
74
|
# Sunshine version.
|
75
|
-
VERSION = '1.0.0
|
75
|
+
VERSION = '1.0.0'
|
76
76
|
|
77
77
|
|
78
78
|
##
|
@@ -91,6 +91,14 @@ module Sunshine
|
|
91
91
|
end
|
92
92
|
|
93
93
|
|
94
|
+
##
|
95
|
+
# Automatically install dependencies as needed. Defaults to true.
|
96
|
+
# Overridden in the ~/.sunshine config file or at setup time.
|
97
|
+
|
98
|
+
def self.auto_dependencies?
|
99
|
+
@config['auto_dependencies']
|
100
|
+
end
|
101
|
+
|
94
102
|
##
|
95
103
|
# Returns the main Sunshine dependencies library.
|
96
104
|
|
@@ -101,8 +109,8 @@ module Sunshine
|
|
101
109
|
|
102
110
|
##
|
103
111
|
# The default directory where apps should be deployed to:
|
104
|
-
# '/var/www' by default. Overridden in the ~/.sunshine config file
|
105
|
-
# See also App#deploy_path.
|
112
|
+
# '/var/www' by default. Overridden in the ~/.sunshine config file
|
113
|
+
# or at setup time. See also App#deploy_path.
|
106
114
|
|
107
115
|
def self.web_directory
|
108
116
|
@config['web_directory']
|
@@ -226,7 +234,8 @@ module Sunshine
|
|
226
234
|
'deploy_env' => :development,
|
227
235
|
'auto' => false,
|
228
236
|
'max_deploy_versions' => 5,
|
229
|
-
'web_directory' => '/var/www'
|
237
|
+
'web_directory' => '/var/www',
|
238
|
+
'auto_dependencies' => true
|
230
239
|
}
|
231
240
|
|
232
241
|
##
|
@@ -361,6 +370,7 @@ module Sunshine
|
|
361
370
|
|
362
371
|
require 'sunshine/daemon'
|
363
372
|
require 'sunshine/daemons/server'
|
373
|
+
require 'sunshine/daemons/apache'
|
364
374
|
require 'sunshine/daemons/nginx'
|
365
375
|
require 'sunshine/daemons/unicorn'
|
366
376
|
require 'sunshine/daemons/rainbows'
|
data/lib/sunshine/daemon.rb
CHANGED
@@ -0,0 +1,37 @@
|
|
1
|
+
module Sunshine
|
2
|
+
|
3
|
+
##
|
4
|
+
# A wrapper for configuring the apache2 server.
|
5
|
+
|
6
|
+
class Apache < Server
|
7
|
+
|
8
|
+
def initialize app, options={}
|
9
|
+
super
|
10
|
+
|
11
|
+
@bin = options[:bin] || 'apachectl'
|
12
|
+
|
13
|
+
@sudo = options[:sudo] || @port < 1024
|
14
|
+
|
15
|
+
@sigkill = 'WINCH'
|
16
|
+
|
17
|
+
# TODO: have a separate max_clients and processes
|
18
|
+
@max_clients = options[:max_clients] || options[:processes] || 128
|
19
|
+
|
20
|
+
@dep_name = options[:dep_name] ||
|
21
|
+
use_passenger? ? 'passenger-apache' : 'apache2'
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
def start_cmd
|
26
|
+
"#{@bin} -f #{self.config_file_path} -E #{log_file :stderr}"
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def setup
|
31
|
+
super do |server_app, binder|
|
32
|
+
binder.set :max_clients, @max_clients
|
33
|
+
yield(server_app, binder) if block_given?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -8,97 +8,15 @@ module Sunshine
|
|
8
8
|
def initialize app, options={}
|
9
9
|
super
|
10
10
|
|
11
|
-
@sudo
|
11
|
+
@sudo = options[:sudo] || @port < 1024
|
12
12
|
|
13
|
-
@dep_name =
|
13
|
+
@dep_name = options[:dep_name] ||
|
14
|
+
use_passenger? ? 'passenger-nginx' : 'nginx'
|
14
15
|
end
|
15
16
|
|
16
17
|
|
17
18
|
def start_cmd
|
18
19
|
"#{@bin} -c #{self.config_file_path}"
|
19
20
|
end
|
20
|
-
|
21
|
-
|
22
|
-
def stop_cmd
|
23
|
-
cmd = "test -f #{@pid} && kill -QUIT $(cat #{@pid})"+
|
24
|
-
" || echo 'No #{@name} process to stop for #{@app.name}';"
|
25
|
-
cmd << "sleep 2 ; rm -f #{@pid};"
|
26
|
-
end
|
27
|
-
|
28
|
-
|
29
|
-
def setup
|
30
|
-
super do |server_app, binder|
|
31
|
-
|
32
|
-
binder.forward :use_passenger?
|
33
|
-
|
34
|
-
binder.set :passenger_root do
|
35
|
-
passenger_root server_app.shell
|
36
|
-
end
|
37
|
-
|
38
|
-
binder.set :nginx_conf_path do
|
39
|
-
nginx_bin = server_app.shell.call "which nginx"
|
40
|
-
File.join File.dirname(nginx_bin), '..', 'conf'
|
41
|
-
end
|
42
|
-
|
43
|
-
yield(server_app, binder) if block_given?
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
|
48
|
-
##
|
49
|
-
# Check if passenger is required to run the application.
|
50
|
-
# Returns true if the server's target is a Sunshine::App
|
51
|
-
|
52
|
-
def use_passenger?
|
53
|
-
Sunshine::App === @target
|
54
|
-
end
|
55
|
-
|
56
|
-
|
57
|
-
##
|
58
|
-
# Gets the root of the installer passenger gem.
|
59
|
-
|
60
|
-
def passenger_root shell
|
61
|
-
str = shell.call "gem list passenger -d"
|
62
|
-
version = $1 if str =~ /passenger\s\((.*)\)$/
|
63
|
-
gempath = $1 if str =~ /Installed\sat:\s(.*)$/
|
64
|
-
|
65
|
-
return unless version && gempath
|
66
|
-
|
67
|
-
File.join(gempath, "gems/passenger-#{version}")
|
68
|
-
end
|
69
|
-
|
70
|
-
|
71
|
-
##
|
72
|
-
# Run passenger installation for nginx
|
73
|
-
|
74
|
-
def setup_passenger server_app
|
75
|
-
server_app.install_deps 'passenger'
|
76
|
-
|
77
|
-
server_app.shell.call \
|
78
|
-
'passenger-install-nginx-module --auto --auto-download',
|
79
|
-
:sudo => true do |stream, data, inn|
|
80
|
-
|
81
|
-
if data =~ /Please specify a prefix directory \[(.*)\]:/
|
82
|
-
|
83
|
-
dir = $1
|
84
|
-
inn.puts dir
|
85
|
-
|
86
|
-
required_dirs = [
|
87
|
-
File.join(dir, 'fastcgi_temp'),
|
88
|
-
File.join(dir, 'proxy_temp')
|
89
|
-
]
|
90
|
-
|
91
|
-
server_app.shell.call \
|
92
|
-
"mkdir -p #{required_dirs.join(" ")}", :sudo => true
|
93
|
-
|
94
|
-
error_log = File.join(dir, "logs/error.log")
|
95
|
-
|
96
|
-
server_app.shell.call \
|
97
|
-
"touch #{error_log} && chmod a+rw #{error_log}", :sudo => true
|
98
|
-
|
99
|
-
server_app.add_shell_paths File.join(dir, 'sbin')
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
21
|
end
|
104
22
|
end
|
@@ -17,6 +17,7 @@ module Sunshine
|
|
17
17
|
|
18
18
|
|
19
19
|
attr_reader :server_name, :port
|
20
|
+
attr_accessor :sigkill
|
20
21
|
|
21
22
|
|
22
23
|
# Server objects need only an App object to be instantiated.
|
@@ -35,8 +36,67 @@ module Sunshine
|
|
35
36
|
|
36
37
|
super app, options
|
37
38
|
|
38
|
-
@port
|
39
|
-
@server_name
|
39
|
+
@port = options[:port] || 80
|
40
|
+
@server_name = options[:server_name]
|
41
|
+
@sigkill = 'QUIT'
|
42
|
+
@supports_rack = false
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
##
|
47
|
+
# Check if passenger is required to run the application.
|
48
|
+
# Returns true if the server's target is a Sunshine::App
|
49
|
+
|
50
|
+
def use_passenger?
|
51
|
+
Sunshine::App === @target && !supports_rack?
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
##
|
56
|
+
# Gets the root of the installer passenger gem.
|
57
|
+
|
58
|
+
def self.passenger_root shell
|
59
|
+
str = shell.call "gem list passenger -d"
|
60
|
+
version = $1 if str =~ /passenger\s\((.*)\)$/
|
61
|
+
gempath = $1 if str =~ /Installed\sat:\s(.*)$/
|
62
|
+
|
63
|
+
return unless version && gempath
|
64
|
+
|
65
|
+
File.join(gempath, "gems/passenger-#{version}")
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
##
|
70
|
+
# Add passenger information to the binder at setup time.
|
71
|
+
|
72
|
+
def setup
|
73
|
+
super do |server_app, binder|
|
74
|
+
|
75
|
+
binder.forward :use_passenger?
|
76
|
+
|
77
|
+
binder.set :passenger_root do
|
78
|
+
Server.passenger_root server_app.shell
|
79
|
+
end
|
80
|
+
|
81
|
+
yield(server_app, binder) if block_given?
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
##
|
87
|
+
# Default server stop command.
|
88
|
+
|
89
|
+
def stop_cmd
|
90
|
+
"test -f #{@pid} && kill -#{@sigkill} $(cat #{@pid}) && sleep 1 && "+
|
91
|
+
"rm -f #{@pid} || echo 'No #{@name} process to stop for #{@app.name}';"
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
##
|
96
|
+
# Defines if this server supports interfacing with rack.
|
97
|
+
|
98
|
+
def supports_rack?
|
99
|
+
@supports_rack
|
40
100
|
end
|
41
101
|
|
42
102
|
|
@@ -7,7 +7,10 @@ module Sunshine
|
|
7
7
|
|
8
8
|
def initialize app, options={}
|
9
9
|
super
|
10
|
+
|
10
11
|
@timeout = options[:timeout] || 3.0
|
12
|
+
|
13
|
+
@supports_rack = true
|
11
14
|
end
|
12
15
|
|
13
16
|
|
@@ -15,12 +18,5 @@ module Sunshine
|
|
15
18
|
"cd #{@app.current_path} && #{@bin} -D -E"+
|
16
19
|
" #{@app.deploy_env} -p #{@port} -c #{self.config_file_path};"
|
17
20
|
end
|
18
|
-
|
19
|
-
|
20
|
-
def stop_cmd
|
21
|
-
"test -f #{@pid} && kill -QUIT $(cat #{@pid})"+
|
22
|
-
" || echo 'No #{@name} process to stop for #{@app.name}';"+
|
23
|
-
"sleep 2; rm -f #{@pid};"
|
24
|
-
end
|
25
21
|
end
|
26
22
|
end
|
@@ -4,14 +4,17 @@
|
|
4
4
|
#class Sunshine::Dependencies < Settler
|
5
5
|
Sunshine.dependencies.instance_eval do
|
6
6
|
|
7
|
-
yum 'tpkg'
|
8
|
-
|
9
7
|
apt 'svn', :pkg => 'subversion'
|
10
8
|
yum 'svn', :pkg => 'subversion'
|
11
9
|
|
12
10
|
apt 'git', :pkg => 'git-core'
|
13
11
|
yum 'git', :pkg => 'git-core'
|
14
12
|
|
13
|
+
yum 'httpd-devel'
|
14
|
+
|
15
|
+
apt 'apache2', :pkg => 'apache2-mpm-prefork'
|
16
|
+
yum 'apache2', :pkg => 'httpd', :requires => 'httpd-devel'
|
17
|
+
|
15
18
|
apt 'nginx'
|
16
19
|
yum 'nginx'
|
17
20
|
|
@@ -53,19 +56,16 @@ Sunshine.dependencies.instance_eval do
|
|
53
56
|
yum 'sqlite-devel'
|
54
57
|
|
55
58
|
|
56
|
-
|
59
|
+
##
|
60
|
+
# Define phusion passenger dependencies
|
57
61
|
|
58
|
-
gem '
|
59
|
-
|
60
|
-
gem 'isolate', :version => ">=1.3.0"
|
62
|
+
gem 'passenger', :version => ">=2.2.11"
|
61
63
|
|
62
|
-
|
64
|
+
dependency 'passenger-nginx' do
|
65
|
+
requires 'passenger'
|
63
66
|
|
64
|
-
gem 'passenger-nginx', :pkg => 'passenger' do
|
65
67
|
install do |shell, sudo|
|
66
68
|
|
67
|
-
shell.call "gem install passenger --no-ri --no-rdoc", :sudo => sudo
|
68
|
-
|
69
69
|
shell.call 'passenger-install-nginx-module --auto --auto-download',
|
70
70
|
:sudo => true do |stream, data, inn|
|
71
71
|
|
@@ -86,8 +86,38 @@ Sunshine.dependencies.instance_eval do
|
|
86
86
|
end
|
87
87
|
end
|
88
88
|
end
|
89
|
+
|
90
|
+
|
91
|
+
check do |shell, sudo|
|
92
|
+
shell.call("nginx -V 2>&1") =~ /gems\/passenger-\d+(\.\d+)+\/ext\/nginx/
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
dependency 'passenger-apache' do
|
98
|
+
requires 'passenger', 'apache2'
|
99
|
+
|
100
|
+
install 'passenger-install-apache2-module --auto'
|
101
|
+
|
102
|
+
check do |shell, sudo|
|
103
|
+
passenger_dir = Server.passenger_root shell
|
104
|
+
passenger_mod = File.join passenger_dir, 'ext/apache2/mod_passenger.so'
|
105
|
+
|
106
|
+
shell.call("test -f #{passenger_mod}", :sudo => true) &&
|
107
|
+
shell.call("apachectl -v")
|
108
|
+
end
|
89
109
|
end
|
90
110
|
|
111
|
+
|
112
|
+
##
|
113
|
+
# Define gems used by Sunshine
|
114
|
+
|
115
|
+
gem 'bundler', :version => ">=0.9"
|
116
|
+
|
117
|
+
gem 'isolate', :version => ">=1.3.0"
|
118
|
+
|
119
|
+
gem 'rake', :version => ">=0.8"
|
120
|
+
|
91
121
|
gem 'geminstaller', :version => ">=0.5"
|
92
122
|
|
93
123
|
gem 'unicorn', :version => ">=0.9"
|
data/lib/sunshine/healthcheck.rb
CHANGED
@@ -4,6 +4,21 @@ module Sunshine
|
|
4
4
|
# Healthcheck objects handle enabling and disabling health checking for
|
5
5
|
# load balancers by touching health.enabled and health.disabled files on
|
6
6
|
# an app's shell.
|
7
|
+
#
|
8
|
+
# If you would like to use Sunshine's healthcheck rack middleware, use
|
9
|
+
# the following command:
|
10
|
+
# sunshine --middleware your_middleware_dir
|
11
|
+
#
|
12
|
+
# Then simply specify the following in your config.ru:
|
13
|
+
# require 'your_middleware_dir/health'
|
14
|
+
# use Sunshine::Health
|
15
|
+
#
|
16
|
+
# Sunshine::Health supports the following options:
|
17
|
+
# :uri_path:: The path that healthcheck will be used on.
|
18
|
+
# :health_file:: The file to check for health.
|
19
|
+
#
|
20
|
+
# use SunshineHealth, :uri_path => "/health.txt",
|
21
|
+
# :health_file => "health.txt"
|
7
22
|
|
8
23
|
class Healthcheck
|
9
24
|
|
data/lib/sunshine/repo.rb
CHANGED
@@ -57,7 +57,7 @@ module Sunshine
|
|
57
57
|
end
|
58
58
|
|
59
59
|
|
60
|
-
attr_reader :url
|
60
|
+
attr_reader :url, :scm
|
61
61
|
|
62
62
|
def initialize url, options={}
|
63
63
|
@scm = self.class.name.split("::").last.sub('Repo', '').downcase
|
@@ -78,9 +78,6 @@ module Sunshine
|
|
78
78
|
Sunshine.logger.info @scm,
|
79
79
|
"Checking out to #{shell.host} #{path}" do
|
80
80
|
|
81
|
-
Sunshine.dependencies.install @scm, :call => shell if
|
82
|
-
Sunshine.dependencies.exist? @scm
|
83
|
-
|
84
81
|
shell.call "test -d #{path} && rm -rf #{path} || echo false"
|
85
82
|
shell.call "mkdir -p #{path}"
|
86
83
|
|
data/lib/sunshine/server_app.rb
CHANGED
@@ -142,11 +142,11 @@ module Sunshine
|
|
142
142
|
end
|
143
143
|
|
144
144
|
|
145
|
-
|
146
145
|
##
|
147
146
|
# Checks out the app's codebase to the checkout path.
|
148
147
|
|
149
148
|
def checkout_repo repo
|
149
|
+
install_deps repo.scm
|
150
150
|
@info[:scm] = repo.checkout_to self.checkout_path, @shell
|
151
151
|
end
|
152
152
|
|
@@ -257,8 +257,11 @@ module Sunshine
|
|
257
257
|
|
258
258
|
##
|
259
259
|
# Install dependencies previously defined in Sunshine.dependencies.
|
260
|
+
# Will not execute if Sunshine.auto_dependencies? is false.
|
260
261
|
|
261
262
|
def install_deps(*deps)
|
263
|
+
return unless Sunshine.auto_dependencies?
|
264
|
+
|
262
265
|
options = {:call => @shell, :prefer => pkg_manager}
|
263
266
|
options.merge! deps.delete_at(-1) if Hash === deps.last
|
264
267
|
|
@@ -0,0 +1,54 @@
|
|
1
|
+
LoadModule log_config_module modules/mod_log_config.so
|
2
|
+
LoadModule authz_host_module modules/mod_authz_host.so
|
3
|
+
|
4
|
+
ErrorLog <%= expand_path log_file(:stderr) %>
|
5
|
+
TransferLog <%= expand_path log_file(:stdout) %>
|
6
|
+
|
7
|
+
<% if use_passenger? %>
|
8
|
+
LoadModule passenger_module <%= passenger_root %>/ext/apache2/mod_passenger.so
|
9
|
+
|
10
|
+
PassengerRuby <%= shell.call "which ruby" %>
|
11
|
+
PassengerRoot <%= passenger_root %>
|
12
|
+
PassengerMaxPoolSize <%= processes %>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<% unless Sunshine::App === target %>
|
16
|
+
LoadModule proxy_module modules/mod_proxy.so
|
17
|
+
LoadModule proxy_connect_module modules/mod_proxy_connect.so
|
18
|
+
LoadModule proxy_http_module modules/mod_proxy_http.so
|
19
|
+
<% end %>
|
20
|
+
|
21
|
+
|
22
|
+
PidFile <%= expand_path pid %>
|
23
|
+
MaxClients <%= max_clients %>
|
24
|
+
|
25
|
+
<% if sudo == true || sudo == 'root' %>
|
26
|
+
User nobody
|
27
|
+
Group nobody
|
28
|
+
<% end %>
|
29
|
+
|
30
|
+
Listen <%= port %>
|
31
|
+
|
32
|
+
|
33
|
+
NameVirtualHost *:<%= port %>
|
34
|
+
|
35
|
+
<VirtualHost *:<%= port %>>
|
36
|
+
ServerName <%= server_name %>
|
37
|
+
ServerAlias www.<%= server_name %>
|
38
|
+
|
39
|
+
<% if Sunshine::App === target %>
|
40
|
+
|
41
|
+
DocumentRoot <%= expand_path app.current_path %>/public
|
42
|
+
|
43
|
+
<Directory <%= app.current_path %>/public>
|
44
|
+
Allow from all
|
45
|
+
Options -MultiViews
|
46
|
+
</Directory>
|
47
|
+
|
48
|
+
<% else %>
|
49
|
+
|
50
|
+
ProxyPass / http://0.0.0.0:<%= target.port %>/
|
51
|
+
ProxyPassReverse / http://0.0.0.0:<%= target.port %>/
|
52
|
+
|
53
|
+
<% end %>
|
54
|
+
</VirtualHost>
|
@@ -18,12 +18,12 @@ http {
|
|
18
18
|
|
19
19
|
<% if use_passenger? %>
|
20
20
|
passenger_root <%= passenger_root %>;
|
21
|
+
passenger_ruby <%= shell.call "which ruby" %>;
|
21
22
|
<% end %>
|
22
23
|
|
23
24
|
client_body_temp_path <%= darwin ? '/var/tmp/nginx' : '/dev/shm' %>;
|
24
25
|
proxy_temp_path <%= darwin ? '/var/tmp/nginx' : '/dev/shm' %>;
|
25
26
|
|
26
|
-
include <%= File.join nginx_conf_path, 'mime.types' %>;
|
27
27
|
default_type application/octet-stream;
|
28
28
|
|
29
29
|
log_format sunshine '$remote_addr - $remote_user [$time_local] '
|
@@ -48,7 +48,7 @@ http {
|
|
48
48
|
gzip_proxied any;
|
49
49
|
gzip_types text/plain text/html text/css application/x-javascript application/xml application/xml+rss text/javascript;
|
50
50
|
|
51
|
-
<% if
|
51
|
+
<% if Sunshine::Server === target %>
|
52
52
|
upstream app_server {
|
53
53
|
server 0:<%= target.port %> fail_timeout=<%= timeout %>;
|
54
54
|
}
|
@@ -91,7 +91,7 @@ http {
|
|
91
91
|
include <%= expand_path config_path %>/nginx_proxy.conf;
|
92
92
|
expires -1;
|
93
93
|
|
94
|
-
<% if
|
94
|
+
<% if Sunshine::Server === target %>
|
95
95
|
if (!-f $request_filename) {
|
96
96
|
proxy_pass http://app_server;
|
97
97
|
break;
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Sunshine
|
2
|
+
|
3
|
+
class Health
|
4
|
+
|
5
|
+
##
|
6
|
+
# Default healthcheck request path.
|
7
|
+
|
8
|
+
DEFAULT_REQUEST_PATH = '/_health'
|
9
|
+
|
10
|
+
|
11
|
+
##
|
12
|
+
# The healthcheck-enabled file.
|
13
|
+
|
14
|
+
HEALTHCHECK_FILE = 'health.enabled'
|
15
|
+
|
16
|
+
|
17
|
+
##
|
18
|
+
# Creates a new SunshineHealth middleware. Supported options are:
|
19
|
+
# :uri_path:: The path that healthcheck will be used on.
|
20
|
+
# :health_file:: The file to check for health.
|
21
|
+
|
22
|
+
def initialize app, options={}
|
23
|
+
@app = app
|
24
|
+
@uri_path = options[:uri_path] || DEFAULT_REQUEST_PATH
|
25
|
+
@healthcheck_file = options[:health_file] || HEALTHCHECK_FILE
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def call env
|
30
|
+
check_health?(env) ? health_response : @app.call(env)
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
##
|
35
|
+
# Given the rack env, do we need to perform a health check?
|
36
|
+
|
37
|
+
def check_health? env
|
38
|
+
env['REQUEST_PATH'] == @uri_path
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
##
|
43
|
+
# Check if healthcheck is enabled.
|
44
|
+
|
45
|
+
def health_enabled?
|
46
|
+
File.file? @healthcheck_file
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
##
|
51
|
+
# Get a rack response for the current health status.
|
52
|
+
|
53
|
+
def health_response
|
54
|
+
status, body = health_enabled? ? [200, "OK"] : [404, "404"]
|
55
|
+
[status, {'Content-Type' => 'text/html'}, body]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
File without changes
|
data/test/test_helper.rb
CHANGED
@@ -183,6 +183,8 @@ unless MockObject === Sunshine.shell
|
|
183
183
|
Sunshine.shell.mock :write, :return => nil
|
184
184
|
end
|
185
185
|
|
186
|
+
YAML.extend MockObject unless MockObject === YAML
|
187
|
+
|
186
188
|
unless Sunshine::Dependency.include? MockObject
|
187
189
|
Sunshine::Dependency.send(:include, MockObject)
|
188
190
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'test/test_helper'
|
2
|
+
|
3
|
+
class TestDaemon < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
mock_remote_shell_popen4
|
7
|
+
@app = Sunshine::App.new(TEST_APP_CONFIG_FILE).extend MockObject
|
8
|
+
@server_app = @app.server_apps.first.extend MockObject
|
9
|
+
@app.server_apps.first.shell.extend MockObject
|
10
|
+
|
11
|
+
use_remote_shell @server_app.shell
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def test_missing_start_stop_cmd
|
16
|
+
daemon = Sunshine::Daemon.new @app
|
17
|
+
|
18
|
+
begin
|
19
|
+
daemon.start_cmd
|
20
|
+
raise "Should have thrown CriticalDeployError but didn't :("
|
21
|
+
rescue Sunshine::CriticalDeployError => e
|
22
|
+
assert_equal "@start_cmd undefined. Can't start daemon", e.message
|
23
|
+
end
|
24
|
+
|
25
|
+
begin
|
26
|
+
daemon.stop_cmd
|
27
|
+
raise "Should have thrown CriticalDeployError but didn't :("
|
28
|
+
rescue Sunshine::CriticalDeployError => e
|
29
|
+
assert_equal "@stop_cmd undefined. Can't stop daemon", e.message
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
data/test/unit/test_nginx.rb
CHANGED
@@ -22,6 +22,9 @@ passenger (2.2.4)
|
|
22
22
|
|
23
23
|
Apache module for Ruby on Rails support.
|
24
24
|
STR
|
25
|
+
|
26
|
+
@nginx_passenger_check =
|
27
|
+
"/opt/ruby-ypc/lib/ruby/gems/1.8/gems/passenger-2.2.11/ext/nginx"
|
25
28
|
end
|
26
29
|
|
27
30
|
|
@@ -66,7 +69,10 @@ passenger (2.2.4)
|
|
66
69
|
|
67
70
|
def test_setup_passenger
|
68
71
|
ds = @passenger.app.server_apps.first.shell
|
69
|
-
|
72
|
+
|
73
|
+
ds.set_mock_response 0,
|
74
|
+
"gem list passenger -d" => [:out, @gemout],
|
75
|
+
"nginx -V 2>&1" => [:out, @nginx_passenger_check]
|
70
76
|
|
71
77
|
@passenger.setup do |ds, binder|
|
72
78
|
assert binder.sudo
|
@@ -92,16 +98,14 @@ passenger (2.2.4)
|
|
92
98
|
|
93
99
|
## Helper methods
|
94
100
|
|
95
|
-
def start_cmd svr
|
96
|
-
|
97
|
-
"#{sudo}#{svr.bin} -c #{svr.config_file_path}"
|
101
|
+
def start_cmd svr
|
102
|
+
"#{svr.bin} -c #{svr.config_file_path}"
|
98
103
|
end
|
99
104
|
|
100
105
|
|
101
|
-
def stop_cmd svr
|
102
|
-
|
103
|
-
|
104
|
-
"
|
105
|
-
cmd << "sleep 2 ; rm -f #{svr.pid};"
|
106
|
+
def stop_cmd svr
|
107
|
+
"test -f #{svr.pid} && kill -#{svr.sigkill} $(cat #{svr.pid}) && "+
|
108
|
+
"sleep 1 && rm -f #{svr.pid} || "+
|
109
|
+
"echo 'No #{svr.name} process to stop for #{svr.app.name}';"
|
106
110
|
end
|
107
111
|
end
|
data/test/unit/test_server.rb
CHANGED
@@ -173,25 +173,6 @@ class TestServer < Test::Unit::TestCase
|
|
173
173
|
end
|
174
174
|
|
175
175
|
|
176
|
-
def test_missing_start_stop_cmd
|
177
|
-
server = Sunshine::Server.new @app
|
178
|
-
|
179
|
-
begin
|
180
|
-
server.start_cmd
|
181
|
-
raise "Should have thrown CriticalDeployError but didn't :("
|
182
|
-
rescue Sunshine::CriticalDeployError => e
|
183
|
-
assert_equal "@start_cmd undefined. Can't start server", e.message
|
184
|
-
end
|
185
|
-
|
186
|
-
begin
|
187
|
-
server.stop_cmd
|
188
|
-
raise "Should have thrown CriticalDeployError but didn't :("
|
189
|
-
rescue Sunshine::CriticalDeployError => e
|
190
|
-
assert_equal "@stop_cmd undefined. Can't stop server", e.message
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
|
195
176
|
def test_log_files
|
196
177
|
@server.log_files :test_log => "/path/test_log.log",
|
197
178
|
:another_test => "/path/another_test.log"
|
data/test/unit/test_sunshine.rb
CHANGED
@@ -3,6 +3,7 @@ require 'test/test_helper'
|
|
3
3
|
class TestSunshine < Test::Unit::TestCase
|
4
4
|
|
5
5
|
def setup
|
6
|
+
mock_yaml_load_file
|
6
7
|
end
|
7
8
|
|
8
9
|
|
@@ -64,10 +65,10 @@ class TestSunshine < Test::Unit::TestCase
|
|
64
65
|
|
65
66
|
assert_equal servers, Sunshine.setup['servers']
|
66
67
|
|
67
|
-
|
68
68
|
Sunshine.run %w{thing1 thing2 -v}.unshift(name)
|
69
69
|
servers = [Sunshine.shell]
|
70
70
|
|
71
|
+
args = [%w{thing1 thing2}, Sunshine.setup]
|
71
72
|
assert_command cmd, args
|
72
73
|
|
73
74
|
assert_equal servers, Sunshine.setup['servers']
|
@@ -154,4 +155,9 @@ class TestSunshine < Test::Unit::TestCase
|
|
154
155
|
end
|
155
156
|
end
|
156
157
|
|
158
|
+
def mock_yaml_load_file
|
159
|
+
YAML.mock :load_file, :args => [Sunshine::USER_CONFIG_FILE],
|
160
|
+
:return => Sunshine::DEFAULT_CONFIG
|
161
|
+
end
|
162
|
+
|
157
163
|
end
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sunshine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
4
|
+
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 1
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
|
10
|
-
version: 1.0.0.pre
|
9
|
+
version: 1.0.0
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Jeremie Castagna
|
@@ -15,7 +14,7 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date: 2010-03-
|
17
|
+
date: 2010-03-25 00:00:00 -07:00
|
19
18
|
default_executable:
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
@@ -61,7 +60,7 @@ dependencies:
|
|
61
60
|
type: :runtime
|
62
61
|
version_requirements: *id003
|
63
62
|
- !ruby/object:Gem::Dependency
|
64
|
-
name:
|
63
|
+
name: rubyforge
|
65
64
|
prerelease: false
|
66
65
|
requirement: &id004 !ruby/object:Gem::Requirement
|
67
66
|
requirements:
|
@@ -69,11 +68,39 @@ dependencies:
|
|
69
68
|
- !ruby/object:Gem::Version
|
70
69
|
segments:
|
71
70
|
- 2
|
71
|
+
- 0
|
72
72
|
- 3
|
73
|
-
|
74
|
-
version: 2.3.3
|
73
|
+
version: 2.0.3
|
75
74
|
type: :development
|
76
75
|
version_requirements: *id004
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: gemcutter
|
78
|
+
prerelease: false
|
79
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
segments:
|
84
|
+
- 0
|
85
|
+
- 5
|
86
|
+
- 0
|
87
|
+
version: 0.5.0
|
88
|
+
type: :development
|
89
|
+
version_requirements: *id005
|
90
|
+
- !ruby/object:Gem::Dependency
|
91
|
+
name: hoe
|
92
|
+
prerelease: false
|
93
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
segments:
|
98
|
+
- 2
|
99
|
+
- 5
|
100
|
+
- 0
|
101
|
+
version: 2.5.0
|
102
|
+
type: :development
|
103
|
+
version_requirements: *id006
|
77
104
|
description: |-
|
78
105
|
Sunshine is an object-oriented api for rack application deployment.
|
79
106
|
|
@@ -116,6 +143,7 @@ files:
|
|
116
143
|
- lib/sunshine/binder.rb
|
117
144
|
- lib/sunshine/crontab.rb
|
118
145
|
- lib/sunshine/daemon.rb
|
146
|
+
- lib/sunshine/daemons/apache.rb
|
119
147
|
- lib/sunshine/daemons/ar_sendmail.rb
|
120
148
|
- lib/sunshine/daemons/delayed_job.rb
|
121
149
|
- lib/sunshine/daemons/nginx.rb
|
@@ -138,12 +166,14 @@ files:
|
|
138
166
|
- lib/sunshine/repos/svn_repo.rb
|
139
167
|
- lib/sunshine/server_app.rb
|
140
168
|
- lib/sunshine/shell.rb
|
169
|
+
- templates/apache/apache.conf.erb
|
141
170
|
- templates/logrotate/logrotate.conf.erb
|
142
171
|
- templates/nginx/nginx.conf.erb
|
143
172
|
- templates/nginx/nginx_optimize.conf
|
144
173
|
- templates/nginx/nginx_proxy.conf
|
145
174
|
- templates/rainbows/rainbows.conf.erb
|
146
|
-
- templates/
|
175
|
+
- templates/sunshine/middleware/health.rb
|
176
|
+
- templates/sunshine/sunshine.rake
|
147
177
|
- templates/unicorn/unicorn.conf.erb
|
148
178
|
- test/fixtures/app_configs/test_app.yml
|
149
179
|
- test/fixtures/sunshine_test/test_upload
|
@@ -153,6 +183,7 @@ files:
|
|
153
183
|
- test/unit/test_app.rb
|
154
184
|
- test/unit/test_binder.rb
|
155
185
|
- test/unit/test_crontab.rb
|
186
|
+
- test/unit/test_daemon.rb
|
156
187
|
- test/unit/test_git_repo.rb
|
157
188
|
- test/unit/test_healthcheck.rb
|
158
189
|
- test/unit/test_nginx.rb
|
@@ -184,13 +215,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
184
215
|
version: "0"
|
185
216
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
186
217
|
requirements:
|
187
|
-
- - "
|
218
|
+
- - ">="
|
188
219
|
- !ruby/object:Gem::Version
|
189
220
|
segments:
|
190
|
-
-
|
191
|
-
|
192
|
-
- 1
|
193
|
-
version: 1.3.1
|
221
|
+
- 0
|
222
|
+
version: "0"
|
194
223
|
requirements: []
|
195
224
|
|
196
225
|
rubyforge_project: sunshine
|
@@ -203,6 +232,7 @@ test_files:
|
|
203
232
|
- test/unit/test_app.rb
|
204
233
|
- test/unit/test_binder.rb
|
205
234
|
- test/unit/test_crontab.rb
|
235
|
+
- test/unit/test_daemon.rb
|
206
236
|
- test/unit/test_git_repo.rb
|
207
237
|
- test/unit/test_healthcheck.rb
|
208
238
|
- test/unit/test_nginx.rb
|