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,122 @@
1
+
2
+ module Capricorn
3
+
4
+ # the Server is supposed to be a simple DRb interface to the System.
5
+ class Server < Capricorn::Daemon::Base
6
+ include DRbUndumped
7
+
8
+ autoload :Proxy, File.dirname(__FILE__)+'/server/proxy'
9
+ autoload :Daemon, File.dirname(__FILE__)+'/server/daemon'
10
+ autoload :Security, File.dirname(__FILE__)+'/server/security'
11
+
12
+ include Capricorn::Server::Daemon
13
+ include Capricorn::Server::Security
14
+
15
+ def self.shared
16
+ @shared ||= new
17
+ end
18
+
19
+ def self.proxy
20
+ @proxy ||= Capricorn::Server::Proxy.new(self.shared)
21
+ end
22
+
23
+ def stop_server
24
+ Capricorn.log "stopping the server..."
25
+ $exitstatus = Capricorn::STOP_STATUS
26
+ DRb.stop_service
27
+ end
28
+
29
+ def restart_server
30
+ Capricorn.log "restarting the server..."
31
+ $exitstatus = Capricorn::RESTART_STATUS
32
+ DRb.stop_service
33
+ end
34
+
35
+ def reload_server
36
+ Capricorn.log "reloading the server..."
37
+ $exitstatus = Capricorn::RELOAD_STATUS
38
+ DRb.stop_service
39
+ end
40
+
41
+ def server_version
42
+ Capricorn.version
43
+ end
44
+
45
+ def update_server
46
+ if Capricorn.system.gem_update('capricorn', :user => 'root')
47
+ reload_server
48
+ end
49
+ end
50
+
51
+ def install_satellite(domain)
52
+ Capricorn.system.install_satellite(domain)
53
+ end
54
+
55
+ def uninstall_satellite(domain)
56
+ satellite = Capricorn.system.find_satellite(domain)
57
+ if satellite
58
+ Capricorn.system.uninstall_satellite(satellite)
59
+ else
60
+ Capricorn.log "Satellite not found (#{domain})"
61
+ end
62
+ end
63
+
64
+ def make_development_satellite(domain)
65
+ satellite = Capricorn.system.find_satellite(domain)
66
+ if satellite
67
+ Capricorn.system.make_development_satellite(satellite)
68
+ else
69
+ Capricorn.log "Satellite not found (#{domain})"
70
+ end
71
+ end
72
+
73
+ def install_engine(domain, name, options={})
74
+ satellite = Capricorn.system.find_satellite(domain)
75
+ if satellite
76
+ Capricorn.system.install_engine(satellite, name, options)
77
+ else
78
+ Capricorn.log "Satellite not found (#{domain})"
79
+ end
80
+ end
81
+
82
+ def update_engine(domain, name, options={})
83
+ satellite = Capricorn.system.find_satellite(domain)
84
+ if satellite
85
+ Capricorn.system.update_engine(satellite, name, options)
86
+ else
87
+ Capricorn.log "Satellite not found (#{domain})"
88
+ end
89
+ end
90
+
91
+ def uninstall_engine(domain, name)
92
+ satellite = Capricorn.system.find_satellite(domain)
93
+ if satellite
94
+ Capricorn.system.uninstall_engine(satellite, name)
95
+ else
96
+ Capricorn.log "Satellite not found (#{domain})"
97
+ end
98
+ end
99
+
100
+ def satellites
101
+ Capricorn.system.satellites
102
+ end
103
+
104
+ def queued_jobs
105
+ queued_jobs = []
106
+ Capricorn.system.queue.each do |job, canceled, immediated|
107
+ job_delay = job.delay
108
+ queued_jobs.push([job.id, job.name, canceled, immediated, job.running?, job.waiting?, job_delay])
109
+ end
110
+ queued_jobs
111
+ end
112
+
113
+ def cancel_job(id)
114
+ Capricorn.system.queue.cancel(id)
115
+ end
116
+
117
+ def immediate_job(id)
118
+ Capricorn.system.queue.immediate(id)
119
+ end
120
+
121
+ end
122
+ end
@@ -0,0 +1,88 @@
1
+
2
+ module Capricorn
3
+ class Server
4
+
5
+ module Daemon # :nodoc:
6
+
7
+ def self.included(base)
8
+ base.extend Capricorn::Server::Daemon::ClassMethods
9
+ end
10
+
11
+ # all a daemon needs to run
12
+ module ClassMethods
13
+
14
+ # construct a Capricorn uri from a DRb uri
15
+ def construct_uri(uri)
16
+ uri = URI.parse(uri)
17
+ uri.scheme = ( Capricorn.system.use_ssl? ? 'ssl+capricorn' : 'capricorn')
18
+ uri.to_s
19
+ end
20
+
21
+ # stop the server
22
+ def stop
23
+ Capricorn.client.stop_server
24
+ end
25
+
26
+ # start the server
27
+ def start
28
+ start_with_failsafe
29
+ end
30
+
31
+ # start the failsafe runner.
32
+ def start_with_failsafe
33
+ $master = true
34
+ stop_server = false
35
+ wait_before_start = 0
36
+ retries = 0
37
+ until stop_server
38
+ if wait_before_start > 0
39
+ sleep(wait_before_start)
40
+ wait_before_start = 0
41
+ end
42
+
43
+ pid = Process.fork { self.run_server }
44
+ return unless pid
45
+ Process.waitpid(pid, 0)
46
+ case $?.exitstatus
47
+ when Capricorn::STOP_STATUS
48
+ stop_server = true
49
+ retries = 0
50
+ when Capricorn::RESTART_STATUS
51
+ wait_before_start = 2
52
+ retries = 0
53
+ when Capricorn::RELOAD_STATUS
54
+ stop_server = true
55
+ retries = 0
56
+ Capricorn::Daemon::PidFile.destroy
57
+ Capricorn.system.run %{#{Capricorn::BIN_PATH} #{ORIGINAL_ARGV.join(' ')}}
58
+ else
59
+ retries += 1
60
+ stop_server = true if retries >= 3
61
+ end
62
+ end
63
+ end
64
+
65
+ # start the actual DRb server
66
+ def run_server
67
+ $master = false
68
+ Dir.chdir(Capricorn.system.root)
69
+
70
+ Capricorn.log "Server started"
71
+ uri = "druby://#{Capricorn.system.server_hostname}:#{Capricorn.system.server_port}"
72
+ DRb.start_service uri, self.proxy, self.options_for_server
73
+ Capricorn.log "listening at #{self.construct_uri(uri)}"
74
+ make_client_cert_public!
75
+
76
+ at_exit do
77
+ Capricorn.system.queue.stop!
78
+ Capricorn.log "Server stopped"
79
+ end
80
+
81
+ DRb.thread.join
82
+ exit($exitstatus || Capricorn::STOP_STATUS)
83
+ end
84
+
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,25 @@
1
+
2
+ module Capricorn
3
+ class Server
4
+ # the proxy object hides all the server internals from the clients.
5
+ class Proxy
6
+
7
+ def initialize(server)
8
+ @server = server
9
+ end
10
+
11
+ def self.allow(*methods)
12
+ methods.each do |method|
13
+ module_eval %{ def #{method}(*args,&block) ; @server.#{method}(*args,&block) ; end }
14
+ end
15
+ end
16
+
17
+ allow :stop_server, :restart_server, :reload_server, :server_version, :update_server, :install_satellite, :uninstall_satellite, :install_engine, :update_engine, :uninstall_engine, :satellites, :queued_jobs, :cancel_job, :immediate_job, :make_development_satellite
18
+
19
+ class << self
20
+ undef_method :allow
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,113 @@
1
+
2
+ module Capricorn
3
+ class Server
4
+ module Security # :nodoc:
5
+
6
+ def self.included(base)
7
+ base.extend Capricorn::Server::Security::ClassMethods
8
+ end
9
+
10
+ module ClassMethods
11
+
12
+ def options_for_server
13
+
14
+ config = {}
15
+ if Capricorn.system.use_ssl?
16
+ install_quick_cert!
17
+ dump_quick_cert_config!
18
+ run_quick_cert!
19
+
20
+ keypair = Capricorn.system.path('quick_cert', 'capricorn', 'capricorn_keypair.pem')
21
+ cert = Capricorn.system.path('quick_cert', 'capricorn', 'cert_capricorn.pem')
22
+
23
+ config = {
24
+ :SSLPrivateKey => OpenSSL::PKey::RSA.new(File.read(keypair)),
25
+ :SSLCertificate => OpenSSL::X509::Certificate.new(File.read(cert)),
26
+ :SSLVerifyMode => OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT,
27
+ :SSLCACertificateFile => Capricorn.system.path('quick_cert', 'CA', 'cacert.pem')
28
+ }
29
+ end
30
+
31
+ config
32
+ end
33
+
34
+ def install_quick_cert!
35
+ unless Capricorn.system.find_bin('QuickCert')
36
+ FileUtils.mkdir_p('/tmp/quick_cert')
37
+ File.chmod(0700, '/tmp/quick_cert')
38
+
39
+ Dir.chdir('/tmp/quick_cert') do
40
+ Capricorn.system.run "curl -O #{Capricorn::QUICK_CERT}"
41
+ Capricorn.system.run "tar xzf QuickCert-1.0.2.tar.gz"
42
+
43
+ Dir.chdir('/tmp/quick_cert/QuickCert-1.0.2') do
44
+ Capricorn.system.run "#{Capricorn.system.ruby_path} ./setup.rb config"
45
+ Capricorn.system.run "#{Capricorn.system.ruby_path} ./setup.rb setup"
46
+ Capricorn.system.run "#{Capricorn.system.ruby_path} ./setup.rb install"
47
+ end
48
+ end
49
+
50
+ FileUtils.rm_rf('/tmp/quick_cert')
51
+ end
52
+ end
53
+
54
+ def dump_quick_cert_config!
55
+ return if File.file? Capricorn.system.path('quick_cert', 'qc_config')
56
+
57
+ config = %{
58
+ full_hostname = `hostname`.strip
59
+ domainname = full_hostname.split('.')[1..-1].join('.')
60
+ hostname = full_hostname.split('.')[0]
61
+
62
+ CA[:hostname] = hostname
63
+ CA[:domainname] = domainname
64
+ CA[:CA_dir] = File.join Dir.pwd, "CA"
65
+ CA[:password] = '#{rand(100_000)}'
66
+
67
+ CERTS << {
68
+ :type => 'server',
69
+ :hostname => 'capricorn',
70
+ # :password => '#{rand(100_000)}',
71
+ }
72
+
73
+ CERTS << {
74
+ :type => 'client',
75
+ :user => 'core',
76
+ :email => 'core@mrhenry.be',
77
+ }
78
+ }
79
+ FileUtils.mkdir_p(Capricorn.system.path('quick_cert'))
80
+ File.chmod(0700, Capricorn.system.path('quick_cert'))
81
+ File.open(Capricorn.system.path('quick_cert', 'qc_config'), 'w+') { |f| f.write config }
82
+ end
83
+
84
+ def run_quick_cert!
85
+ return if File.directory? Capricorn.system.path('quick_cert', 'CA')
86
+
87
+ Dir.chdir(Capricorn.system.path('quick_cert')) do
88
+ Capricorn.system.run Capricorn.system.find_bin('QuickCert')
89
+ end
90
+ end
91
+
92
+ def make_client_cert_public!
93
+ token = nil
94
+ if Capricorn.system.use_ssl?
95
+ token = Capricorn::Client::AuthToken.new(
96
+ :target_uri => self.construct_uri(DRb.uri),
97
+ :verify_mode => OpenSSL::SSL::VERIFY_PEER,
98
+ :private_key_data => File.read(Capricorn.system.path('quick_cert', 'core', 'core_keypair.pem')),
99
+ :certificate_data => File.read(Capricorn.system.path('quick_cert', 'core', 'cert_core.pem')),
100
+ :ca_certificate_data => File.read(Capricorn.system.path('quick_cert', 'CA', 'cacert.pem'))
101
+ )
102
+ else
103
+ token = Capricorn::Client::AuthToken.new(
104
+ :target_uri => self.construct_uri(DRb.uri))
105
+ end
106
+ token.dump_file(Capricorn.system.path('core.token'))
107
+ FileUtils.chmod_R(0775, Capricorn.system.path('core.token'))
108
+ end
109
+
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,184 @@
1
+
2
+ module Capricorn
3
+ class System
4
+ include DRbUndumped
5
+
6
+ autoload :Shell, File.dirname(__FILE__)+'/system/shell'
7
+ autoload :Config, File.dirname(__FILE__)+'/system/config'
8
+ autoload :Helper, File.dirname(__FILE__)+'/system/helper'
9
+ autoload :Options, File.dirname(__FILE__)+'/system/options'
10
+ autoload :Satellites, File.dirname(__FILE__)+'/system/satellites'
11
+ autoload :ProcessUser, File.dirname(__FILE__)+'/system/process_user'
12
+
13
+ include Capricorn::System::Shell
14
+ include Capricorn::System::Config
15
+ include Capricorn::System::Helper
16
+ include Capricorn::System::Options
17
+ include Capricorn::System::Satellites
18
+ include Capricorn::System::ProcessUser
19
+
20
+ # get the shared system. this will also set the shared system if you pass a new system as its argument.
21
+ def self.shared(system=nil)
22
+ @system = system if system
23
+ @system
24
+ end
25
+
26
+ # load the shared system
27
+ def self.load!(root=nil)
28
+ @system = new(root)
29
+ end
30
+
31
+ def initialize(root=nil)
32
+ unless root
33
+ if get_user_name == 'root'
34
+ root = Capricorn::DEFAULT_ROOT_SYSTEM_DIR
35
+ else
36
+ root = Capricorn::DEFAULT_USER_SYSTEM_DIR
37
+ end
38
+ end
39
+
40
+ @root = File.expand_path(root)
41
+ @actors = []
42
+ @options = {}
43
+ @option_descriptors = []
44
+ @satellite_options = {}
45
+ @satellite_option_descriptors = []
46
+
47
+ system_file = self.path('system.rb')
48
+ unless File.file? system_file
49
+ Capricorn.log "No system file found (#{system_file})"
50
+ exit(1)
51
+ end
52
+
53
+ Capricorn::ExceptionHandler.setup(self.path('ServerNormal.log'), self.path('ServerError.log'))
54
+
55
+ use :BaseActor
56
+ self.instance_eval File.read(system_file)
57
+ self.resolve_options!
58
+ end
59
+
60
+ attr_accessor :current_satellite, :root
61
+
62
+ def queue
63
+ @queue ||= Capricorn::JobQueue.new
64
+ end
65
+
66
+ def path(*args)
67
+ File.join(@root, *args)
68
+ end
69
+
70
+ def install_satellite(domain)
71
+ self.queue.enqueue("install new satellite #{domain}", :domain => domain) do |options|
72
+ satellite = Capricorn::Satellite.new(options[:domain])
73
+
74
+ run_action_on :install_satellite, satellite
75
+ run_action_on :link_satellite, satellite
76
+ save_satellite! satellite
77
+ end
78
+ end
79
+
80
+ def uninstall_satellite(satellite)
81
+ if satellite
82
+ self.queue.enqueue("uninstall #{satellite.domain}", :satellite => satellite) do |options|
83
+ run_action_on :uninstall_satellite, options[:satellite]
84
+ destroy_satellite! options[:satellite]
85
+ end
86
+ else
87
+ false
88
+ end
89
+ end
90
+
91
+ def make_development_satellite(satellite)
92
+ if satellite
93
+ Capricorn.runtime_gem('rubigen', Capricorn::RUBIGEN_VERSION)
94
+ resolve_options_with satellite do
95
+ as_user(web_user, web_group) do
96
+ Dir.chdir(File.dirname(satellite_root)) do
97
+
98
+ name = File.basename(satellite_root)
99
+
100
+ FileUtils.rm_r("#{name}/doc", :verbose => true) rescue nil
101
+ FileUtils.rm_r("#{name}/README", :verbose => true) rescue nil
102
+ FileUtils.rm_r("#{name}/public/javascripts", :verbose => true) rescue nil
103
+
104
+ require 'rubigen/scripts/generate'
105
+ RubiGen::Base.use_application_sources!
106
+ RubiGen::Scripts::Generate.new.run(["-f", name], :generator => 'engine')
107
+
108
+ end
109
+ end
110
+ end
111
+ else
112
+ false
113
+ end
114
+ end
115
+
116
+ def install_engine(satellite, name, options={})
117
+ if satellite
118
+ self.queue.enqueue("install #{satellite.domain}: #{name} #{options.inspect}",
119
+ :satellite => satellite, :name => name, :options => options) do |options|
120
+
121
+ satellite, name, options = options[:satellite], options[:name], options[:options]
122
+ resolve_options_with(satellite) { ensure_presence_of_gem(name, options) }
123
+ if satellite.add_engine(name, options)
124
+ run_action_on :install_engine, satellite
125
+ run_action_on :link_satellite, satellite
126
+ save_satellite! satellite
127
+ end
128
+
129
+ end
130
+ else
131
+ false
132
+ end
133
+ end
134
+
135
+ def update_engine(satellite, name, options={})
136
+ if satellite
137
+ self.queue.enqueue("update #{satellite.domain}: #{name} #{options.inspect}",
138
+ :satellite => satellite, :name => name, :options => options) do |options|
139
+
140
+ satellite, name, options = options[:satellite], options[:name], options[:options]
141
+ resolve_options_with(satellite) { ensure_presence_of_gem(name, options) }
142
+ if satellite.update_engine(name, options)
143
+ run_action_on :update_engine, satellite
144
+ run_action_on :link_satellite, satellite
145
+ save_satellite! satellite
146
+ end
147
+
148
+ end
149
+ else
150
+ false
151
+ end
152
+ end
153
+
154
+ def uninstall_engine(satellite, name)
155
+ if satellite
156
+ self.queue.enqueue("uninstall #{satellite.domain}: #{name}",
157
+ :satellite => satellite, :name => name) do |options|
158
+
159
+ satellite, name = options[:satellite], options[:name]
160
+ if satellite.remove_engine(name)
161
+ run_action_on :uninstall_engine, satellite
162
+ run_action_on :link_satellite, satellite
163
+ save_satellite! satellite
164
+ end
165
+
166
+ end
167
+ else
168
+ false
169
+ end
170
+ end
171
+
172
+ private
173
+
174
+ def run_action_on(action, satellite)
175
+ resolve_options_with satellite do
176
+ actors = @actors.collect { |actor_klass| actor_klass.new(self, satellite) }
177
+ actors.each { |actor| actor.run_callbacks_in_fase! action, :before }
178
+ actors.each { |actor| actor.run_callbacks_in_fase! action, :on }
179
+ actors.each { |actor| actor.run_callbacks_in_fase! action, :after }
180
+ end
181
+ end
182
+
183
+ end
184
+ end