capricorn 0.2.00
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/app_generators/engine/engine_generator.rb +39 -0
- data/app_generators/engine/templates/Gmfile +20 -0
- data/app_generators/engine/templates/MIT-LICENSE.txt +20 -0
- data/app_generators/engine/templates/README.rdoc +7 -0
- data/app_generators/engine/templates/config/routes.rb +2 -0
- data/app_generators/engine/templates/gitignore +3 -0
- data/app_generators/engine/templates/init.rb +1 -0
- data/app_generators/engine/templates/lib/engine.rb +1 -0
- data/app_generators/engine/templates/rails/init.rb +1 -0
- data/app_generators/engine/templates/tasks/engine_tasks.rake +4 -0
- data/bin/capricorn +20 -0
- data/lib/capricorn.rb +100 -0
- data/lib/capricorn/actor.rb +23 -0
- data/lib/capricorn/actor/actions.rb +76 -0
- data/lib/capricorn/actors/apache_actor.rb +56 -0
- data/lib/capricorn/actors/base_actor.rb +276 -0
- data/lib/capricorn/actors/mysql_actor.rb +20 -0
- data/lib/capricorn/actors/passenger_actor.rb +19 -0
- data/lib/capricorn/actors/plesk_actor.rb +210 -0
- data/lib/capricorn/actors/sqlite3_actor.rb +44 -0
- data/lib/capricorn/app_runner.rb +119 -0
- data/lib/capricorn/apps/dev.rb +15 -0
- data/lib/capricorn/apps/engines.rb +33 -0
- data/lib/capricorn/apps/jobs.rb +35 -0
- data/lib/capricorn/apps/satellite.rb +32 -0
- data/lib/capricorn/apps/server.rb +67 -0
- data/lib/capricorn/client.rb +48 -0
- data/lib/capricorn/client/auth_token.rb +98 -0
- data/lib/capricorn/daemon.rb +71 -0
- data/lib/capricorn/exception_handler.rb +79 -0
- data/lib/capricorn/extentions/rubygems_plugin.rb +27 -0
- data/lib/capricorn/extentions/thor_extentions.rb +32 -0
- data/lib/capricorn/job_queue.rb +199 -0
- data/lib/capricorn/satellite.rb +50 -0
- data/lib/capricorn/satellite/actions.rb +35 -0
- data/lib/capricorn/satellite/dependency_loader.rb +78 -0
- data/lib/capricorn/satellite/persistence.rb +50 -0
- data/lib/capricorn/server.rb +122 -0
- data/lib/capricorn/server/daemon.rb +88 -0
- data/lib/capricorn/server/proxy.rb +25 -0
- data/lib/capricorn/server/security.rb +113 -0
- data/lib/capricorn/system.rb +184 -0
- data/lib/capricorn/system/config.rb +49 -0
- data/lib/capricorn/system/helper.rb +21 -0
- data/lib/capricorn/system/options.rb +79 -0
- data/lib/capricorn/system/process_user.rb +73 -0
- data/lib/capricorn/system/satellites.rb +44 -0
- data/lib/capricorn/system/shell.rb +80 -0
- data/lib/rubygems_plugin.rb +1 -0
- data/spec/actor/actions_spec.rb +13 -0
- data/spec/spec_helper.rb +1 -0
- metadata +108 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
Capricorn.runtime_gem('thor', Capricorn::THOR_VERSION)
|
2
|
+
|
3
|
+
module Capricorn
|
4
|
+
module Apps
|
5
|
+
class Jobs < Thor
|
6
|
+
|
7
|
+
desc "list", 'list the jobs in the queue'
|
8
|
+
method_options :token => :optional
|
9
|
+
def list
|
10
|
+
queued_jobs = Capricorn.client(options[:token]).queued_jobs
|
11
|
+
queued_jobs.each do |id, name, canceled, immediated, running, waiting, delay|
|
12
|
+
status = []
|
13
|
+
status.push canceled ? 'c' : ' '
|
14
|
+
status.push immediated ? 'i' : ' '
|
15
|
+
status.push running ? 'r' : ' '
|
16
|
+
status.push waiting ? 'w' : ' '
|
17
|
+
puts("% 8d % 8d % 8s %s" % [id, delay.to_i, status.join, name])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "cancel ID", 'cancel the job with ID'
|
22
|
+
method_options :token => :optional
|
23
|
+
def cancel(id)
|
24
|
+
Capricorn.client(options[:token]).cancel_job(id.to_i)
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "immediate ID", 'immediately run the job with ID'
|
28
|
+
method_options :token => :optional
|
29
|
+
def immediate(id)
|
30
|
+
Capricorn.client(options[:token]).immediate_job(id.to_i)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
Capricorn.runtime_gem('thor', Capricorn::THOR_VERSION)
|
2
|
+
|
3
|
+
module Capricorn
|
4
|
+
module Apps # :nodoc:
|
5
|
+
|
6
|
+
class Satellite < Thor
|
7
|
+
desc 'list', 'show all managed satellites'
|
8
|
+
method_options :token => :optional
|
9
|
+
def list
|
10
|
+
Capricorn.client(options[:token]).satellites.each do |sat|
|
11
|
+
puts sat.domain
|
12
|
+
sat.engines.each do |name, options|
|
13
|
+
puts "- #{name} #{options.inspect}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
desc 'install DOMAIN', 'install a satellite'
|
19
|
+
method_options :token => :optional
|
20
|
+
def install(domain)
|
21
|
+
Capricorn.client(options[:token]).install_satellite(domain)
|
22
|
+
end
|
23
|
+
|
24
|
+
desc 'uninstall DOMAIN', 'uninstall a satellite'
|
25
|
+
method_options :token => :optional
|
26
|
+
def uninstall(domain)
|
27
|
+
Capricorn.client(options[:token]).uninstall_satellite(domain)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
Capricorn.runtime_gem('thor', Capricorn::THOR_VERSION)
|
2
|
+
|
3
|
+
module Capricorn
|
4
|
+
module Apps
|
5
|
+
|
6
|
+
class Server < Thor
|
7
|
+
|
8
|
+
desc "start", 'start the server'
|
9
|
+
method_options :foreground => :boolean, :config => :optional
|
10
|
+
def start
|
11
|
+
Capricorn.server? true
|
12
|
+
Capricorn::System.load!(options[:root_path])
|
13
|
+
|
14
|
+
begin
|
15
|
+
FileUtils.mkdir_p(Capricorn.system.root)
|
16
|
+
rescue Errno::EACCES
|
17
|
+
Capricorn.logger.out.fatal "must be executed as root"
|
18
|
+
exit(1)
|
19
|
+
end
|
20
|
+
|
21
|
+
unless Capricorn.system.is_user('root')
|
22
|
+
Capricorn.logger.out.fatal "must be executed as root"
|
23
|
+
exit(1)
|
24
|
+
end
|
25
|
+
|
26
|
+
if options[:foreground]
|
27
|
+
Capricorn::Server.start
|
28
|
+
else
|
29
|
+
Capricorn::Server.daemonize
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "stop", 'stop the server'
|
34
|
+
method_options :token => :optional
|
35
|
+
def stop
|
36
|
+
Capricorn.client(options[:token]).stop_server
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "restart", 'restart the server'
|
40
|
+
method_options :token => :optional
|
41
|
+
def restart
|
42
|
+
Capricorn.client(options[:token]).restart_server
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "reload", 'reload the server'
|
46
|
+
method_options :token => :optional
|
47
|
+
def reload
|
48
|
+
Capricorn.client(options[:token]).reload_server
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "update", 'update the capricorn'
|
52
|
+
method_options :token => :optional
|
53
|
+
def update
|
54
|
+
Capricorn.client(options[:token]).update_server
|
55
|
+
end
|
56
|
+
|
57
|
+
desc "version", 'version of the server'
|
58
|
+
method_options :token => :optional
|
59
|
+
def version
|
60
|
+
puts "Client: #{Capricorn.version}"
|
61
|
+
puts "Server: #{Capricorn.client(options[:token]).server_version}"
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'drb'
|
2
|
+
require 'drb/ssl'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module Capricorn
|
6
|
+
class Client
|
7
|
+
|
8
|
+
autoload :AuthToken, File.dirname(__FILE__)+'/client/auth_token'
|
9
|
+
|
10
|
+
# return a DRb uri for the given Capricorn uri.
|
11
|
+
def self.parse_uri(uri)
|
12
|
+
uri = URI.parse(uri)
|
13
|
+
use_ssl = (uri.scheme == 'ssl+capricorn')
|
14
|
+
uri.scheme = 'druby'
|
15
|
+
return use_ssl, uri.to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
# return an potentialy initialize the client to the given token.
|
19
|
+
def self.current(token=nil)
|
20
|
+
@client = connect(token) unless @client
|
21
|
+
@client
|
22
|
+
end
|
23
|
+
|
24
|
+
# connect to the server referenced by the given token.
|
25
|
+
def self.connect(token=nil)
|
26
|
+
token ||= 'core.token'
|
27
|
+
|
28
|
+
[Capricorn::DEFAULT_ROOT_SYSTEM_DIR,
|
29
|
+
Capricorn::DEFAULT_USER_SYSTEM_DIR,
|
30
|
+
File.join(Capricorn::DEFAULT_USER_SYSTEM_DIR, 'tokens'),
|
31
|
+
'.'].each do |path|
|
32
|
+
path = File.expand_path(File.join(path, token))
|
33
|
+
if File.file? path
|
34
|
+
token = path
|
35
|
+
break
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
unless File.file? token
|
40
|
+
raise "Unable to read the token at: #{token}"
|
41
|
+
end
|
42
|
+
|
43
|
+
token = Capricorn::Client::AuthToken.load_file(token) if String === token
|
44
|
+
token.connect if token
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Capricorn
|
4
|
+
class Client
|
5
|
+
class AuthToken
|
6
|
+
|
7
|
+
# load a token from the passed IO.
|
8
|
+
def self.load(io)
|
9
|
+
self.new YAML.load(io)
|
10
|
+
end
|
11
|
+
|
12
|
+
# load a token from a file referenced by the given +path+.
|
13
|
+
def self.load_file(path)
|
14
|
+
self.new YAML.load_file(path)
|
15
|
+
end
|
16
|
+
|
17
|
+
# the uri at which the capricorn server can be accessed.
|
18
|
+
attr_reader :target_uri
|
19
|
+
# the SSL verification mode used by the capricorn server
|
20
|
+
attr_reader :verify_mode
|
21
|
+
# the optional CA certificate used by the capricorn server
|
22
|
+
attr_reader :ca_certificate_data
|
23
|
+
# the private key used by the client
|
24
|
+
attr_reader :private_key_data
|
25
|
+
# the certificate used by the client
|
26
|
+
attr_reader :certificate_data
|
27
|
+
|
28
|
+
# create a new token from the given options
|
29
|
+
#
|
30
|
+
# +:target_uri+, +:verify_mode+, +:ca_certificate_data+, +:private_key_data+, +:certificate_data+
|
31
|
+
def initialize(options={})
|
32
|
+
@target_uri = options[:target_uri]
|
33
|
+
@verify_mode = options[:verify_mode]
|
34
|
+
@ca_certificate_data = options[:ca_certificate_data]
|
35
|
+
@private_key_data = options[:private_key_data]
|
36
|
+
@certificate_data = options[:certificate_data]
|
37
|
+
end
|
38
|
+
|
39
|
+
# get the parsed and initialized OpenSSL::X509::Certificate
|
40
|
+
def ca_certificate
|
41
|
+
@ca_certificate ||= OpenSSL::X509::Certificate.new(@ca_certificate_data)
|
42
|
+
end
|
43
|
+
|
44
|
+
# get the parsed and initialized OpenSSL::X509::Certificate
|
45
|
+
def certificate
|
46
|
+
@certificate ||= OpenSSL::X509::Certificate.new(@certificate_data)
|
47
|
+
end
|
48
|
+
|
49
|
+
# get the parsed and initialized OpenSSL::PKey::RSA
|
50
|
+
def private_key
|
51
|
+
@private_key ||= OpenSSL::PKey::RSA.new(@private_key_data)
|
52
|
+
end
|
53
|
+
|
54
|
+
# connect to the server and return the server handle.
|
55
|
+
def connect
|
56
|
+
use_ssl, uri = Capricorn::Client.parse_uri(self.target_uri)
|
57
|
+
if use_ssl
|
58
|
+
DRb.start_service nil, nil, self.options_for_drb
|
59
|
+
else
|
60
|
+
DRb.start_service
|
61
|
+
end
|
62
|
+
DRbObject.new nil, uri
|
63
|
+
end
|
64
|
+
|
65
|
+
# return options for use with DRb
|
66
|
+
def options_for_drb
|
67
|
+
@options_for_drb ||= {
|
68
|
+
:SSLVerifyMode => self.verify_mode,
|
69
|
+
:SSLCACertificate => self.ca_certificate,
|
70
|
+
:SSLPrivateKey => self.private_key,
|
71
|
+
:SSLCertificate => self.certificate
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
# dump this token to the given IO or return the content as a String
|
76
|
+
def dump(io=nil)
|
77
|
+
data = {
|
78
|
+
:target_uri => self.target_uri,
|
79
|
+
:verify_mode => self.verify_mode,
|
80
|
+
:ca_certificate_data => self.ca_certificate_data,
|
81
|
+
:private_key_data => self.private_key_data,
|
82
|
+
:certificate_data => self.certificate_data
|
83
|
+
}
|
84
|
+
if io
|
85
|
+
io.write YAML.dump(data)
|
86
|
+
else
|
87
|
+
YAML.dump(data)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# dump this token to a file at the given +path+.
|
92
|
+
def dump_file(path)
|
93
|
+
File.open(path, 'w+') { |f| dump(f) }
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
|
2
|
+
module Capricorn
|
3
|
+
module Daemon
|
4
|
+
class Base
|
5
|
+
|
6
|
+
def self.daemonize(&block)
|
7
|
+
Capricorn::Daemon::Controller.start(self,&block)
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
module PidFile
|
13
|
+
def self.store(pid)
|
14
|
+
File.open(self.pid_file, 'w') {|f| f << pid}
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.recall
|
18
|
+
IO.read(self.pid_file).to_i rescue nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.destroy
|
22
|
+
FileUtils.rm(self.pid_file) if self.exist?
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.pid_file
|
26
|
+
Capricorn.system.path("Server.pid")
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.exist?
|
30
|
+
File.file?(self.pid_file)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module Controller
|
35
|
+
|
36
|
+
def self.start(daemon, &block)
|
37
|
+
fork do
|
38
|
+
Process.setsid
|
39
|
+
exit if fork
|
40
|
+
if PidFile.exist?
|
41
|
+
puts "Pid file #{PidFile.pid_file} already exists. Not starting."
|
42
|
+
exit 1
|
43
|
+
end
|
44
|
+
Capricorn::Daemon::PidFile.store(Process.pid)
|
45
|
+
Dir.chdir Capricorn.system.root
|
46
|
+
File.umask 0000
|
47
|
+
|
48
|
+
Capricorn::ExceptionHandler.redirect_std
|
49
|
+
|
50
|
+
trap("TERM") { daemon.stop; exit }
|
51
|
+
at_exit { Capricorn::Daemon::PidFile.destroy if $master }
|
52
|
+
at_exit(&block) if block
|
53
|
+
daemon.start
|
54
|
+
end
|
55
|
+
puts "Daemon started."
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.stop
|
59
|
+
if !Capricorn::Daemon::PidFile.exist?
|
60
|
+
puts "Pid file not found. Is the daemon started?"
|
61
|
+
exit
|
62
|
+
end
|
63
|
+
pid = Capricorn::Daemon::PidFile.recall
|
64
|
+
pid && Process.kill("TERM", pid)
|
65
|
+
rescue Errno::ESRCH
|
66
|
+
puts "Pid file found, but process was not running. The daemon may have died."
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
|
2
|
+
module Capricorn
|
3
|
+
module ExceptionHandler
|
4
|
+
|
5
|
+
def self.setup(out=STDOUT, err=STDERR)
|
6
|
+
if String === out
|
7
|
+
@out = Logger.new(out, 'daily')
|
8
|
+
@stdout = @out.instance_variable_get('@logdev').instance_variable_get('@dev')
|
9
|
+
else
|
10
|
+
@out = Logger.new(out)
|
11
|
+
@stdout = out
|
12
|
+
end
|
13
|
+
|
14
|
+
if String === err
|
15
|
+
@err = Logger.new(err, 'daily')
|
16
|
+
@stderr = @err.instance_variable_get('@logdev').instance_variable_get('@dev')
|
17
|
+
else
|
18
|
+
@err = Logger.new(err)
|
19
|
+
@stderr = err
|
20
|
+
end
|
21
|
+
|
22
|
+
@out.level = Logger::DEBUG
|
23
|
+
@err.level = Logger::DEBUG
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.err
|
27
|
+
@err
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.out
|
31
|
+
@out
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.stderr
|
35
|
+
@stderr
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.stdout
|
39
|
+
@stdout
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.redirect_std
|
43
|
+
if STDOUT != self.stdout
|
44
|
+
STDOUT.reopen self.stdout
|
45
|
+
end
|
46
|
+
|
47
|
+
if STDERR != self.stderr
|
48
|
+
STDERR.reopen self.stderr
|
49
|
+
end
|
50
|
+
|
51
|
+
STDIN.reopen "/dev/null"
|
52
|
+
end
|
53
|
+
|
54
|
+
def logger
|
55
|
+
Capricorn::ExceptionHandler
|
56
|
+
end
|
57
|
+
|
58
|
+
def log(*args, &block)
|
59
|
+
args = [args.inspect] if args.size == 1 and Array === args.first
|
60
|
+
logger.out.info(*args, &block)
|
61
|
+
end
|
62
|
+
|
63
|
+
def report
|
64
|
+
yield
|
65
|
+
rescue Exception => e
|
66
|
+
if StandardError === e
|
67
|
+
logger.err.error(e)
|
68
|
+
else
|
69
|
+
logger.err.fatal(e)
|
70
|
+
end
|
71
|
+
raise e
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def FileUtils.fu_output_message(msg)
|
78
|
+
Capricorn::ExceptionHandler.out.info(msg)
|
79
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rubygems/specification'
|
2
|
+
|
3
|
+
module Gem # :nodoc:
|
4
|
+
class Specification
|
5
|
+
attribute :engine_dependencies, {}
|
6
|
+
|
7
|
+
def add_engine_dependency(name, options={})
|
8
|
+
name = name.to_s
|
9
|
+
add_runtime_dependency(name, *[options[:version]].compact)
|
10
|
+
@engine_dependencies ||= {}
|
11
|
+
@engine_dependencies[name] = options
|
12
|
+
end
|
13
|
+
|
14
|
+
alias_method :ruby_code_without_engines, :ruby_code # :nodoc:
|
15
|
+
def ruby_code(obj) # :nodoc:
|
16
|
+
return obj.inspect if Hash === obj
|
17
|
+
return ruby_code_without_engines(obj)
|
18
|
+
end
|
19
|
+
|
20
|
+
alias_method :to_ruby_without_engines, :to_ruby # :nodoc:
|
21
|
+
def to_ruby # :nodoc:
|
22
|
+
code = to_ruby_without_engines
|
23
|
+
code.gsub! /s\.engine_dependencies\s+[=]([^\n]+)/, 's.instance_variable_set(:@engine_dependencies,\1)'
|
24
|
+
code
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|