capricorn 0.2.00

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/app_generators/engine/engine_generator.rb +39 -0
  2. data/app_generators/engine/templates/Gmfile +20 -0
  3. data/app_generators/engine/templates/MIT-LICENSE.txt +20 -0
  4. data/app_generators/engine/templates/README.rdoc +7 -0
  5. data/app_generators/engine/templates/config/routes.rb +2 -0
  6. data/app_generators/engine/templates/gitignore +3 -0
  7. data/app_generators/engine/templates/init.rb +1 -0
  8. data/app_generators/engine/templates/lib/engine.rb +1 -0
  9. data/app_generators/engine/templates/rails/init.rb +1 -0
  10. data/app_generators/engine/templates/tasks/engine_tasks.rake +4 -0
  11. data/bin/capricorn +20 -0
  12. data/lib/capricorn.rb +100 -0
  13. data/lib/capricorn/actor.rb +23 -0
  14. data/lib/capricorn/actor/actions.rb +76 -0
  15. data/lib/capricorn/actors/apache_actor.rb +56 -0
  16. data/lib/capricorn/actors/base_actor.rb +276 -0
  17. data/lib/capricorn/actors/mysql_actor.rb +20 -0
  18. data/lib/capricorn/actors/passenger_actor.rb +19 -0
  19. data/lib/capricorn/actors/plesk_actor.rb +210 -0
  20. data/lib/capricorn/actors/sqlite3_actor.rb +44 -0
  21. data/lib/capricorn/app_runner.rb +119 -0
  22. data/lib/capricorn/apps/dev.rb +15 -0
  23. data/lib/capricorn/apps/engines.rb +33 -0
  24. data/lib/capricorn/apps/jobs.rb +35 -0
  25. data/lib/capricorn/apps/satellite.rb +32 -0
  26. data/lib/capricorn/apps/server.rb +67 -0
  27. data/lib/capricorn/client.rb +48 -0
  28. data/lib/capricorn/client/auth_token.rb +98 -0
  29. data/lib/capricorn/daemon.rb +71 -0
  30. data/lib/capricorn/exception_handler.rb +79 -0
  31. data/lib/capricorn/extentions/rubygems_plugin.rb +27 -0
  32. data/lib/capricorn/extentions/thor_extentions.rb +32 -0
  33. data/lib/capricorn/job_queue.rb +199 -0
  34. data/lib/capricorn/satellite.rb +50 -0
  35. data/lib/capricorn/satellite/actions.rb +35 -0
  36. data/lib/capricorn/satellite/dependency_loader.rb +78 -0
  37. data/lib/capricorn/satellite/persistence.rb +50 -0
  38. data/lib/capricorn/server.rb +122 -0
  39. data/lib/capricorn/server/daemon.rb +88 -0
  40. data/lib/capricorn/server/proxy.rb +25 -0
  41. data/lib/capricorn/server/security.rb +113 -0
  42. data/lib/capricorn/system.rb +184 -0
  43. data/lib/capricorn/system/config.rb +49 -0
  44. data/lib/capricorn/system/helper.rb +21 -0
  45. data/lib/capricorn/system/options.rb +79 -0
  46. data/lib/capricorn/system/process_user.rb +73 -0
  47. data/lib/capricorn/system/satellites.rb +44 -0
  48. data/lib/capricorn/system/shell.rb +80 -0
  49. data/lib/rubygems_plugin.rb +1 -0
  50. data/spec/actor/actions_spec.rb +13 -0
  51. data/spec/spec_helper.rb +1 -0
  52. 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