appserver 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/README.md +30 -9
- data/Rakefile +31 -0
- data/bin/appserver +9 -6
- data/lib/appserver.rb +10 -6
- data/lib/appserver/app.rb +106 -65
- data/lib/appserver/appserver.conf.rb +126 -0
- data/lib/appserver/command.rb +38 -10
- data/lib/appserver/configurator.rb +38 -0
- data/lib/appserver/logrotate.rb +46 -0
- data/lib/appserver/monit.rb +45 -0
- data/lib/appserver/nginx.rb +71 -0
- data/lib/appserver/repository.rb +80 -21
- data/lib/appserver/server_dir.rb +100 -0
- data/lib/appserver/unicorn.conf.rb +23 -27
- data/lib/appserver/utils.rb +24 -15
- data/test/apps/rack-simple/config.ru +7 -0
- data/test/apps/sinatra/Gemfile +4 -0
- data/test/apps/sinatra/config.ru +2 -0
- data/test/apps/sinatra/hello.rb +9 -0
- data/test/apps/sinatra/views/index.erb +1 -0
- data/test/helper.rb +49 -0
- data/test/unit/test_app.rb +72 -0
- data/test/unit/test_appserver.rb +26 -0
- data/test/unit/test_command.rb +64 -0
- data/test/unit/test_configurator.rb +116 -0
- data/test/unit/test_logrotate.rb +14 -0
- data/test/unit/test_monit.rb +13 -0
- data/test/unit/test_nginx.rb +13 -0
- data/test/unit/test_repository.rb +50 -0
- data/test/unit/test_server_dir.rb +121 -0
- data/test/unit/test_unicorn_conf.rb +58 -0
- data/test/unit/test_utils.rb +36 -0
- metadata +84 -11
- data/lib/appserver/appserver.yml +0 -85
- data/lib/appserver/server.rb +0 -136
data/lib/appserver/command.rb
CHANGED
@@ -15,25 +15,53 @@ module Appserver
|
|
15
15
|
def run!
|
16
16
|
Dir.chdir(options[:dir]) if options[:dir]
|
17
17
|
|
18
|
-
|
18
|
+
if command == 'init'
|
19
|
+
ServerDir.init(arguments[0], options)
|
20
|
+
Dir.chdir(arguments[0])
|
21
|
+
end
|
19
22
|
|
20
|
-
|
23
|
+
server_dir = ServerDir.discover
|
21
24
|
|
22
25
|
case command
|
23
26
|
when 'init'
|
24
|
-
|
27
|
+
server_dir.write_configs
|
25
28
|
puts 'Initialized appserver directory.'
|
26
|
-
puts 'Wrote
|
27
|
-
puts '
|
29
|
+
puts 'Wrote configuration snippets. Make sure to include them into your'
|
30
|
+
puts 'system\'s Monit/Nginx/Logrotate configuration to become active.'
|
31
|
+
|
32
|
+
when 'update'
|
33
|
+
server_dir.write_configs
|
34
|
+
puts 'Wrote configuration snippets.'
|
28
35
|
|
29
36
|
when 'deploy'
|
30
|
-
repository =
|
31
|
-
# TODO
|
37
|
+
repository = server_dir.repository(arguments[0])
|
32
38
|
repository.install_hook
|
39
|
+
# Second and third arguments are used by git update hooks and contain
|
40
|
+
# the ref name and the new ref that just have been updated
|
41
|
+
ref = repository.app.branch
|
42
|
+
if arguments[1] && arguments[2]
|
43
|
+
return unless arguments[1] =~ %r(refs/heads/#{ref})
|
44
|
+
ref = arguments[2]
|
45
|
+
end
|
46
|
+
puts 'Deploying application...'
|
47
|
+
repository.deploy(ref)
|
48
|
+
puts 'Done.'
|
33
49
|
|
34
|
-
when '
|
35
|
-
|
36
|
-
|
50
|
+
when 'start'
|
51
|
+
app = server_dir.app(arguments[0])
|
52
|
+
app.start_server
|
53
|
+
|
54
|
+
when 'stop'
|
55
|
+
app = server_dir.app(arguments[0])
|
56
|
+
app.stop_server
|
57
|
+
|
58
|
+
when 'restart'
|
59
|
+
app = server_dir.app(arguments[0])
|
60
|
+
app.restart_server
|
61
|
+
|
62
|
+
when 'reopen'
|
63
|
+
app = server_dir.app(arguments[0])
|
64
|
+
app.reopen_server_log
|
37
65
|
|
38
66
|
else
|
39
67
|
raise UnknownCommandError
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Appserver
|
2
|
+
class Configurator < Struct.new(:settings, :global_keys, :context_keys)
|
3
|
+
|
4
|
+
def initialize (config_file, global_keys = nil, context_keys = nil)
|
5
|
+
self.settings = {}
|
6
|
+
self.global_keys = global_keys
|
7
|
+
self.context_keys = context_keys
|
8
|
+
instance_eval(File.read(config_file), config_file) if config_file
|
9
|
+
end
|
10
|
+
|
11
|
+
def apply! (target, context = nil)
|
12
|
+
settings = (self.settings[nil] || {}).dup
|
13
|
+
settings.update(self.settings[context] || {}) if context
|
14
|
+
target.class.const_get(:SETTINGS_DEFAULTS).each do |key, default_value|
|
15
|
+
value = settings[key] || default_value
|
16
|
+
value = File.expand_path(value, target.path) if value && target.class.const_get(:SETTINGS_EXPAND).include?(key)
|
17
|
+
target.send("#{key}=", value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def context (context)
|
22
|
+
saved_context = @context
|
23
|
+
@context = context.to_s
|
24
|
+
yield
|
25
|
+
@context = saved_context
|
26
|
+
end
|
27
|
+
alias_method :app, :context
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def method_missing (method, *args)
|
32
|
+
return super if !@context && global_keys && !global_keys.include?(method)
|
33
|
+
return super if @context && context_keys && !context_keys.include?(method)
|
34
|
+
self.settings[@context] ||= {}
|
35
|
+
self.settings[@context][method] = args[0] if args.size > 0
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Appserver
|
2
|
+
class Logrotate < Struct.new(:server_dir)
|
3
|
+
|
4
|
+
def self.write_config (server_dir)
|
5
|
+
new(server_dir).write_config
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize (server_dir)
|
9
|
+
self.server_dir = server_dir
|
10
|
+
end
|
11
|
+
|
12
|
+
def write_config
|
13
|
+
Utils.safe_replace_file(server_dir.logrotate_conf) do |f|
|
14
|
+
f.puts "# Logrotate configuration automagically generated by the \"appserver\" gem using"
|
15
|
+
f.puts "# the appserver directory config #{server_dir.config_file}"
|
16
|
+
f.puts "# Include this file into your system's logrotate.conf (using an include statement)"
|
17
|
+
f.puts "# to use it. See http://github.com/zargony/appserver for details."
|
18
|
+
# Handle access logs of Nginx in one statement, so Nginx only needs to reopen once
|
19
|
+
access_logs = server_dir.apps.map { |app| app.access_log }.compact
|
20
|
+
f.puts "#{access_logs.join(' ')} {"
|
21
|
+
f.puts " missingok"
|
22
|
+
f.puts " delaycompress"
|
23
|
+
f.puts " sharedscripts"
|
24
|
+
f.puts " postrotate"
|
25
|
+
f.puts " #{server_dir.nginx_reopen}"
|
26
|
+
f.puts " endscript"
|
27
|
+
f.puts "}"
|
28
|
+
# Add application-specific Logrotate configuration
|
29
|
+
server_dir.apps.each do |app|
|
30
|
+
f.puts ""
|
31
|
+
f.puts "# Application: #{app.name}"
|
32
|
+
if app.server_log
|
33
|
+
f.puts "#{app.server_log} {"
|
34
|
+
f.puts " missingok"
|
35
|
+
f.puts " delaycompress"
|
36
|
+
f.puts " sharedscripts"
|
37
|
+
f.puts " postrotate"
|
38
|
+
f.puts " #{server_dir.appserver_cmd('reload', app.name)}"
|
39
|
+
f.puts " endscript"
|
40
|
+
f.puts "}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Appserver
|
2
|
+
class Monit < Struct.new(:server_dir)
|
3
|
+
|
4
|
+
def self.write_config (server_dir)
|
5
|
+
new(server_dir).write_config
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize (server_dir)
|
9
|
+
self.server_dir = server_dir
|
10
|
+
end
|
11
|
+
|
12
|
+
def write_config
|
13
|
+
Utils.safe_replace_file(server_dir.monit_conf) do |f|
|
14
|
+
f.puts "# Monit configuration automagically generated by the \"appserver\" gem using"
|
15
|
+
f.puts "# the appserver directory config #{server_dir.config_file}"
|
16
|
+
f.puts "# Include this file into your system's monitrc (using an include statement)"
|
17
|
+
f.puts "# to use it. See http://github.com/zargony/appserver for details."
|
18
|
+
# Let Monit reload itself if this configuration changes
|
19
|
+
f.puts "check file monit_conf with path #{server_dir.monit_conf}"
|
20
|
+
f.puts " if changed checksum then exec \"#{server_dir.monit_reload}\""
|
21
|
+
# Reload Nginx if its configuration changes
|
22
|
+
f.puts "check file nginx_conf with path #{server_dir.nginx_conf}"
|
23
|
+
f.puts " if changed checksum then exec \"#{server_dir.nginx_reload}\""
|
24
|
+
# Add application-specific Monit configuration
|
25
|
+
server_dir.apps.each do |app|
|
26
|
+
f.puts ""
|
27
|
+
f.puts "# Application: #{app.name}"
|
28
|
+
if app.pid_file && app.start_server?
|
29
|
+
cyclecheck = app.usage_check_cycles ? " for #{app.usage_check_cycles} cycles" : ''
|
30
|
+
f.puts "check process #{app.name} with pidfile #{app.pid_file}"
|
31
|
+
f.puts " start program = \"#{server_dir.appserver_cmd('start', app.name)}\""
|
32
|
+
f.puts " stop program = \"#{server_dir.appserver_cmd('stop', app.name)}\""
|
33
|
+
f.puts " if totalcpu usage > #{app.max_cpu_usage}#{cyclecheck} then restart" if app.max_cpu_usage
|
34
|
+
f.puts " if totalmemory usage > #{app.max_memory_usage}#{cyclecheck} then restart" if app.max_memory_usage
|
35
|
+
f.puts " if failed unixsocket #{app.socket} protocol http request \"/\" timeout #{app.http_check_timeout} seconds then restart" if app.http_check_timeout
|
36
|
+
f.puts " if 5 restarts within 5 cycles then timeout"
|
37
|
+
f.puts " group appserver"
|
38
|
+
f.puts "check file #{app.name}_revision with path #{app.revision_file}"
|
39
|
+
f.puts " if changed checksum then exec \"#{server_dir.appserver_cmd('restart', app.name)}\""
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Appserver
|
2
|
+
class Nginx < Struct.new(:server_dir)
|
3
|
+
|
4
|
+
def self.write_config (server_dir)
|
5
|
+
new(server_dir).write_config
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize (server_dir)
|
9
|
+
self.server_dir = server_dir
|
10
|
+
end
|
11
|
+
|
12
|
+
def write_config
|
13
|
+
Utils.safe_replace_file(server_dir.nginx_conf) do |f|
|
14
|
+
f.puts "# Nginx configuration automagically generated by the \"appserver\" gem using"
|
15
|
+
f.puts "# the appserver directory config #{server_dir.config_file}"
|
16
|
+
f.puts "# Include this file into your system's nginx.conf (using an include statement"
|
17
|
+
f.puts "# inside a http statement) to use it. See http://github.com/zargony/appserver"
|
18
|
+
f.puts "# for details."
|
19
|
+
# The default server always responds with 403 Forbidden
|
20
|
+
f.puts "server {"
|
21
|
+
f.puts " listen 80 default;"
|
22
|
+
f.puts " server_name _;"
|
23
|
+
f.puts " deny all;"
|
24
|
+
f.puts "}"
|
25
|
+
# Add application-specific Nginx configuration
|
26
|
+
server_dir.apps.each do |app|
|
27
|
+
f.puts ""
|
28
|
+
f.puts "# Application: #{app.name}"
|
29
|
+
if app.socket
|
30
|
+
f.puts "upstream #{app.name} {"
|
31
|
+
f.puts " server unix:#{app.socket} fail_timeout=0;"
|
32
|
+
f.puts "}"
|
33
|
+
write_server_definition(f, app)
|
34
|
+
write_server_definition(f, app, true) if app.ssl?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
|
42
|
+
def write_server_definition (f, app, ssl = false)
|
43
|
+
f.puts "server {"
|
44
|
+
f.puts " listen #{ssl ? 443 : 80};"
|
45
|
+
f.puts " server_name #{app.hostname};"
|
46
|
+
if ssl
|
47
|
+
f.puts " ssl on;"
|
48
|
+
f.puts " ssl_certificate #{app.ssl_cert};"
|
49
|
+
f.puts " ssl_certificate_key #{app.ssl_key};"
|
50
|
+
f.puts " ssl_session_timeout 5m;"
|
51
|
+
f.puts " ssl_protocols SSLv2 SSLv3 TLSv1;"
|
52
|
+
f.puts " ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;"
|
53
|
+
f.puts " ssl_prefer_server_ciphers on;"
|
54
|
+
end
|
55
|
+
f.puts " root #{app.public_path};"
|
56
|
+
f.puts " access_log #{app.access_log};"
|
57
|
+
# TODO: maintenance mode rewriting
|
58
|
+
f.puts " try_files $uri/index.html $uri.html $uri @#{app.name};"
|
59
|
+
f.puts " location @#{app.name} {"
|
60
|
+
f.puts " proxy_set_header X-Real-IP $remote_addr;"
|
61
|
+
f.puts " proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;"
|
62
|
+
f.puts " proxy_set_header X-Forwarded-Proto https;" if ssl
|
63
|
+
f.puts " proxy_set_header Host $http_host;"
|
64
|
+
f.puts " proxy_redirect off;"
|
65
|
+
f.puts " proxy_pass http://#{app.name};"
|
66
|
+
f.puts " }"
|
67
|
+
f.puts " error_page 500 502 503 504 /500.html;" if File.exist?(File.join(app.public_path, '500.html'))
|
68
|
+
f.puts "}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/appserver/repository.rb
CHANGED
@@ -1,48 +1,107 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'git'
|
3
|
+
|
1
4
|
module Appserver
|
2
|
-
class
|
3
|
-
|
5
|
+
class InvalidRepositoryError < RuntimeError; end
|
6
|
+
class ExecError < RuntimeError; end
|
4
7
|
|
5
|
-
|
8
|
+
class Repository < Struct.new(:server_dir, :path)
|
6
9
|
|
7
|
-
def initialize (
|
8
|
-
self.
|
10
|
+
def initialize (server_dir, path, config)
|
11
|
+
self.server_dir, self.path = server_dir, path.chomp('/')
|
9
12
|
raise InvalidRepositoryError unless valid?
|
10
13
|
end
|
11
14
|
|
12
15
|
def name
|
13
|
-
File.basename(
|
16
|
+
File.basename(path, '.git')
|
17
|
+
end
|
18
|
+
|
19
|
+
def app
|
20
|
+
# The app for this repository (app of same name)
|
21
|
+
@app ||= server_dir.app(name)
|
14
22
|
end
|
15
23
|
|
16
24
|
def valid?
|
17
|
-
|
25
|
+
name && name != '' &&
|
26
|
+
File.directory?(File.join(path, 'hooks')) &&
|
27
|
+
File.directory?(File.join(path, 'refs'))
|
18
28
|
end
|
19
29
|
|
20
|
-
def
|
21
|
-
File.join(
|
30
|
+
def update_hook
|
31
|
+
File.join(path, 'hooks', 'update')
|
22
32
|
end
|
23
33
|
|
24
34
|
def install_hook
|
25
|
-
deploy_cmd =
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
safe_replace_file(post_receive_hook) do |f|
|
35
|
+
deploy_cmd = server_dir.appserver_cmd('deploy')
|
36
|
+
if !File.exist?(update_hook) || !File.executable?(update_hook)
|
37
|
+
puts "Installing git update hook to repository #{path}..."
|
38
|
+
Utils.safe_replace_file(update_hook) do |f|
|
30
39
|
f.puts '#!/bin/sh'
|
31
|
-
f.puts deploy_cmd
|
32
|
-
f.chown File.stat(
|
40
|
+
f.puts "#{deploy_cmd} #{path} $1 $3"
|
41
|
+
f.chown File.stat(path).uid, File.stat(path).gid
|
33
42
|
f.chmod 0755
|
34
43
|
end
|
35
|
-
elsif !File.readlines(
|
36
|
-
puts "Couldn't install
|
44
|
+
elsif !File.readlines(update_hook).any? { |line| line =~ /^#{Regexp.escape(deploy_cmd)}/ }
|
45
|
+
puts "Couldn't install update hook. Foreign hook script already present in repository #{path}!"
|
37
46
|
else
|
38
|
-
#puts "Hook already installed in repository #{
|
47
|
+
#puts "Hook already installed in repository #{path}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def deploy (ref = nil)
|
52
|
+
# Choose a temporary build directory on the same filesystem so that it
|
53
|
+
# can be easily renamed/moved to be the real application directory later
|
54
|
+
build_path, old_path = "#{app.path}.new", "#{app.path}.old"
|
55
|
+
begin
|
56
|
+
# Check out the current code
|
57
|
+
ref ||= app.branch
|
58
|
+
checkout(build_path, ref)
|
59
|
+
# Install gem bundle if a Gemfile exists
|
60
|
+
install_bundle(build_path)
|
61
|
+
|
62
|
+
# TODO: more deploy setup (write database config, ...)
|
63
|
+
|
64
|
+
# Replace the current application directory with the newly built one
|
65
|
+
FileUtils.rm_rf old_path
|
66
|
+
FileUtils.mv app.path, old_path if File.exist?(app.path)
|
67
|
+
FileUtils.mv build_path, app.path
|
68
|
+
ensure
|
69
|
+
# If anything broke and the build directory still exists, remove it
|
70
|
+
FileUtils.rm_rf build_path
|
71
|
+
# If anything broke and the app directory doesn't exist anymore, put the old directory in place
|
72
|
+
FileUtils.mv old_path, app.path if !File.exist?(app.path) && File.exist?(old_path)
|
39
73
|
end
|
40
74
|
end
|
41
75
|
|
42
76
|
protected
|
43
77
|
|
44
|
-
def
|
45
|
-
|
78
|
+
def checkout (target_path, ref = 'master')
|
79
|
+
# There seem to be two ways to "export" the tip of a branch from a repository
|
80
|
+
# 1. clone the repository, check out the branch and remove the .git directory afterwards
|
81
|
+
#system("git clone --depth 1 --branch master #{path} #{target_path} && rm -rf #{target_path}/.git")
|
82
|
+
# 2. do a hard reset while pointing GIT_DIR to the repository and GIT_WORK_TREE to an empty dir
|
83
|
+
#system("mkdir #{target_path} && git --git-dir=#{path} --work-tree=#{target_path} reset --hard #{branch}")
|
84
|
+
git = Git.clone(path, target_path, :depth => 1)
|
85
|
+
ref = git.revparse(ref)
|
86
|
+
git.checkout(ref)
|
87
|
+
Dir.chdir(target_path) do
|
88
|
+
FileUtils.rm_rf '.git'
|
89
|
+
Utils.safe_replace_file 'REVISION' do |f|
|
90
|
+
f.puts ref
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def install_bundle (target_path)
|
96
|
+
Dir.chdir(target_path) do
|
97
|
+
# Remove any .bundle subdirectory (it shouldn't be in the repository anyway)
|
98
|
+
FileUtils.rm_rf '.bundle'
|
99
|
+
# If there's a Gemfile, run "bundle install"
|
100
|
+
if File.exist?('Gemfile')
|
101
|
+
system "#{app.ruby} -S -- bundle install .bundle --without development test"
|
102
|
+
raise ExecError if $?.exitstatus > 0
|
103
|
+
end
|
104
|
+
end
|
46
105
|
end
|
47
106
|
end
|
48
107
|
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Appserver
|
4
|
+
class DirectoryAlreadyExistError < RuntimeError; end
|
5
|
+
class NotInitializedError < RuntimeError; end
|
6
|
+
|
7
|
+
class ServerDir < Struct.new(:path, :monit_conf, :monit_reload, :nginx_conf, :nginx_reload, :nginx_reopen, :logrotate_conf)
|
8
|
+
|
9
|
+
CONFIG_FILE_NAME = 'appserver.conf.rb'
|
10
|
+
|
11
|
+
SETTINGS_DEFAULTS = {
|
12
|
+
:monit_conf => 'monitrc',
|
13
|
+
:monit_reload => '/usr/sbin/monit reload',
|
14
|
+
:nginx_conf => 'nginx.conf',
|
15
|
+
:nginx_reload => '/usr/sbin/nginx -s reload',
|
16
|
+
:nginx_reopen => '/usr/sbin/nginx -s reopen',
|
17
|
+
:logrotate_conf => 'logrotate.conf',
|
18
|
+
}
|
19
|
+
|
20
|
+
SETTINGS_EXPAND = [ :monit_conf, :nginx_conf, :logrotate_conf ]
|
21
|
+
|
22
|
+
def self.config_file_template
|
23
|
+
File.expand_path("../#{CONFIG_FILE_NAME}", __FILE__)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.discover (path = '.', options = {})
|
27
|
+
if File.exist?(File.join(path, CONFIG_FILE_NAME))
|
28
|
+
new(path, options)
|
29
|
+
elsif path != '/'
|
30
|
+
discover(File.expand_path('..', path), options)
|
31
|
+
else
|
32
|
+
raise NotInitializedError
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.init (path, options = {})
|
37
|
+
raise DirectoryAlreadyExistError if File.exist?(path) && !options[:force]
|
38
|
+
FileUtils.mkdir_p path
|
39
|
+
Dir.chdir(path) do
|
40
|
+
FileUtils.cp config_file_template, CONFIG_FILE_NAME
|
41
|
+
FileUtils.mkdir_p ['apps', 'tmp', 'log']
|
42
|
+
end
|
43
|
+
new(path, options)
|
44
|
+
end
|
45
|
+
|
46
|
+
def initialize (path, options = {})
|
47
|
+
self.path = File.expand_path(path)
|
48
|
+
# Load and apply configuration settings
|
49
|
+
app_keys = App::SETTINGS_DEFAULTS.keys
|
50
|
+
global_keys = SETTINGS_DEFAULTS.keys + App::SETTINGS_DEFAULTS.keys
|
51
|
+
@config = Configurator.new(File.exist?(config_file) ? config_file : nil, global_keys, app_keys)
|
52
|
+
@config.apply!(self)
|
53
|
+
end
|
54
|
+
|
55
|
+
def config_file
|
56
|
+
File.join(path, CONFIG_FILE_NAME)
|
57
|
+
end
|
58
|
+
|
59
|
+
def appserver_cmd (*args)
|
60
|
+
cmd = File.expand_path('../../../bin/appserver', __FILE__)
|
61
|
+
"#{cmd} -d #{path} #{args.join(' ')}"
|
62
|
+
end
|
63
|
+
|
64
|
+
def apps_path
|
65
|
+
File.join(path, 'apps')
|
66
|
+
end
|
67
|
+
|
68
|
+
def tmp_path
|
69
|
+
File.join(path, 'tmp')
|
70
|
+
end
|
71
|
+
|
72
|
+
def log_path
|
73
|
+
File.join(path, 'log')
|
74
|
+
end
|
75
|
+
|
76
|
+
def app (name)
|
77
|
+
@apps ||= {}
|
78
|
+
@apps[name] ||= App.new(self, name, @config)
|
79
|
+
end
|
80
|
+
|
81
|
+
def apps
|
82
|
+
Dir.glob(File.join(apps_path, '*')).
|
83
|
+
select { |f| File.directory?(f) }.
|
84
|
+
map { |f| File.basename(f) }.
|
85
|
+
reject { |f| f =~ /\.(tmp|old|new)$/ }.
|
86
|
+
map { |name| app(name) }
|
87
|
+
end
|
88
|
+
|
89
|
+
def repository (path)
|
90
|
+
@repositories ||= {}
|
91
|
+
@repositories[File.expand_path(path, self.path)] ||= Repository.new(self, path, @config)
|
92
|
+
end
|
93
|
+
|
94
|
+
def write_configs
|
95
|
+
Monit.write_config(self)
|
96
|
+
Nginx.write_config(self)
|
97
|
+
Logrotate.write_config(self)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|