appserver 0.0.1 → 0.0.2
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/.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
|