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,32 @@
|
|
1
|
+
Capricorn.runtime_gem('thor', Capricorn::THOR_VERSION)
|
2
|
+
|
3
|
+
class Thor
|
4
|
+
class << self
|
5
|
+
attr_accessor :real_namespace # :nodoc:
|
6
|
+
end
|
7
|
+
def self.namespace=(value)
|
8
|
+
Thor.real_namespace = value
|
9
|
+
end
|
10
|
+
def self.namespace
|
11
|
+
Thor.real_namespace
|
12
|
+
end
|
13
|
+
self.namespace = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
module Thor::Util # :nodoc:
|
17
|
+
class << self
|
18
|
+
alias_method :old_constant_to_thor_path, :constant_to_thor_path
|
19
|
+
alias_method :old_constant_from_thor_path, :constant_from_thor_path
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.constant_to_thor_path(*args) # :nodoc:
|
23
|
+
path = old_constant_to_thor_path(*args)
|
24
|
+
path.sub! /^#{Thor.namespace}:/, '' if Thor.namespace
|
25
|
+
path
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.constant_from_thor_path(path) # :nodoc:
|
29
|
+
path = "#{Thor.namespace}:"+path if Thor.namespace
|
30
|
+
old_constant_from_thor_path(path)
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
module Capricorn
|
4
|
+
class JobQueue
|
5
|
+
include DRbUndumped
|
6
|
+
|
7
|
+
# create a new job queue
|
8
|
+
def initialize
|
9
|
+
@immediated_jobs = Array.new
|
10
|
+
@canceled_jobs = Array.new
|
11
|
+
@job_queue = Array.new
|
12
|
+
@jobs = Hash.new
|
13
|
+
@mutex = Mutex.new
|
14
|
+
@next_id = 1
|
15
|
+
|
16
|
+
@worker = Thread.new(self) do |job_queue|
|
17
|
+
while job_queue.running? or job_queue.peek
|
18
|
+
|
19
|
+
if job = job_queue.peek
|
20
|
+
job.run(job_queue)
|
21
|
+
job_queue.delete(job.id)
|
22
|
+
else
|
23
|
+
sleep(1)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# enqueue a new job with the given +name+, +options+ and +proc+
|
31
|
+
def enqueue(name, options={}, &proc)
|
32
|
+
@mutex.synchronize do
|
33
|
+
job = Job.new(@next_id, name, options, &proc)
|
34
|
+
@next_id += 1
|
35
|
+
@jobs[job.id] = job
|
36
|
+
@job_queue.push job.id
|
37
|
+
return job.id
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# dequeue the next job of the queue.
|
42
|
+
def dequeue
|
43
|
+
@mutex.synchronize do
|
44
|
+
id = @job_queue.shift
|
45
|
+
return @jobs.delete(id) if id
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# delete the job associated with the given +id+.
|
50
|
+
def delete(id)
|
51
|
+
@mutex.synchronize do
|
52
|
+
id = @job_queue.delete(id)
|
53
|
+
return @jobs.delete(id) if id
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# peek at the next job in the queue
|
58
|
+
def peek
|
59
|
+
job = nil
|
60
|
+
@mutex.synchronize do
|
61
|
+
id = @job_queue.first
|
62
|
+
job = @jobs[id] if id
|
63
|
+
end
|
64
|
+
job
|
65
|
+
end
|
66
|
+
|
67
|
+
# get the size of the job queue
|
68
|
+
def size
|
69
|
+
@mutex.synchronize do
|
70
|
+
@job_queue.size
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# cancel the job associated with the given +id+.
|
75
|
+
def cancel(id)
|
76
|
+
@mutex.synchronize do
|
77
|
+
id = @job_queue.delete(id)
|
78
|
+
if id
|
79
|
+
@jobs.delete(id)
|
80
|
+
@canceled_jobs.push(id)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# is the job associated with the given +id+ canceled.
|
86
|
+
def canceled?(id)
|
87
|
+
@mutex.synchronize do
|
88
|
+
return !@canceled_jobs.delete(id).nil?
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# run the job associated with the given +id+ immediately.
|
93
|
+
def immediate(id)
|
94
|
+
@mutex.synchronize do
|
95
|
+
@immediated_jobs.push(id) if @jobs[id]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# should the job associated with the given +id+ be run immediately.
|
100
|
+
def immediated?(id)
|
101
|
+
@mutex.synchronize do
|
102
|
+
return !@immediated_jobs.delete(id).nil?
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# join the worker thread
|
107
|
+
def join!
|
108
|
+
@worker.join
|
109
|
+
end
|
110
|
+
|
111
|
+
# wait until the queue is empty then stop the worker
|
112
|
+
def stop!
|
113
|
+
@mutex.synchronize do
|
114
|
+
@stopped = true
|
115
|
+
end
|
116
|
+
join!
|
117
|
+
end
|
118
|
+
|
119
|
+
# is the queue stopping or stopped?
|
120
|
+
def stopped?
|
121
|
+
@mutex.synchronize do
|
122
|
+
return !!@stopped
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# is the queue running
|
127
|
+
def running?
|
128
|
+
!stopped?
|
129
|
+
end
|
130
|
+
|
131
|
+
# iterate through all the jobs on the queue
|
132
|
+
def each
|
133
|
+
@mutex.synchronize do
|
134
|
+
@job_queue.each do |id|
|
135
|
+
job = @jobs[id]
|
136
|
+
canceled = @canceled_jobs.include?(id)
|
137
|
+
immediated = @immediated_jobs.include?(id)
|
138
|
+
|
139
|
+
yield(job, canceled, immediated)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
class Job
|
145
|
+
include DRbUndumped
|
146
|
+
|
147
|
+
attr_accessor :id, :name, :options, :proc
|
148
|
+
|
149
|
+
def initialize(id, name, options={}, &proc)
|
150
|
+
@id = id.to_i
|
151
|
+
@mutex = Mutex.new
|
152
|
+
@name, @options, @proc = name, options, proc
|
153
|
+
@run_at = Time.now + (options.delete(:delay) || 30)
|
154
|
+
end
|
155
|
+
|
156
|
+
def delay
|
157
|
+
@mutex.synchronize do
|
158
|
+
delay = @run_at - Time.now
|
159
|
+
delay = 0 if delay < 0
|
160
|
+
return delay
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def running?
|
165
|
+
@mutex.synchronize do
|
166
|
+
return @running
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def waiting?
|
171
|
+
@mutex.synchronize do
|
172
|
+
return @waiting
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def run(job_queue)
|
177
|
+
Capricorn.report do
|
178
|
+
@waiting = true
|
179
|
+
immediated = canceled = false
|
180
|
+
Capricorn.log "waiting #{@run_at - Time.now}s."
|
181
|
+
until immediated or canceled or @run_at <= Time.now
|
182
|
+
sleep(1)
|
183
|
+
canceled = job_queue.canceled?(self.id)
|
184
|
+
immediated = job_queue.immediated?(self.id)
|
185
|
+
end
|
186
|
+
|
187
|
+
unless canceled
|
188
|
+
@waiting = false
|
189
|
+
@running = true
|
190
|
+
Capricorn.log("[queue]> #{@name}")
|
191
|
+
@proc.call(@options)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
|
2
|
+
module Capricorn
|
3
|
+
class Satellite
|
4
|
+
include DRbUndumped
|
5
|
+
|
6
|
+
autoload :Actions, File.dirname(__FILE__)+'/satellite/actions'
|
7
|
+
autoload :Persistence, File.dirname(__FILE__)+'/satellite/persistence'
|
8
|
+
autoload :DependencyLoader, File.dirname(__FILE__)+'/satellite/dependency_loader'
|
9
|
+
|
10
|
+
include Capricorn::Satellite::Actions
|
11
|
+
include Capricorn::Satellite::Persistence
|
12
|
+
|
13
|
+
attr_reader :domain, :engines
|
14
|
+
|
15
|
+
def initialize(domain)
|
16
|
+
if Hash === domain
|
17
|
+
domain.each do |name, value|
|
18
|
+
instance_variable_set("@#{name}".to_sym, value)
|
19
|
+
end
|
20
|
+
else
|
21
|
+
@domain = domain
|
22
|
+
@engines = {}
|
23
|
+
end
|
24
|
+
@domain.gsub! /^www\./, ''
|
25
|
+
end
|
26
|
+
|
27
|
+
def basedomain
|
28
|
+
unless @basedomain
|
29
|
+
parts = self.domain.split('.')
|
30
|
+
parts = parts[-2..-1]
|
31
|
+
@basedomain = parts.join('.')
|
32
|
+
end
|
33
|
+
@basedomain
|
34
|
+
end
|
35
|
+
|
36
|
+
def subdomain
|
37
|
+
unless @subdomain
|
38
|
+
parts = self.domain.split('.')
|
39
|
+
parts = parts[0..-3]
|
40
|
+
@subdomain = parts.join('.')
|
41
|
+
end
|
42
|
+
@subdomain unless @subdomain == ''
|
43
|
+
end
|
44
|
+
|
45
|
+
def subdomain?
|
46
|
+
!self.subdomain.nil?
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
module Capricorn
|
3
|
+
class Satellite
|
4
|
+
module Actions
|
5
|
+
|
6
|
+
def add_engine(name, options={})
|
7
|
+
unless @engines.key? name
|
8
|
+
@engines[name] = options
|
9
|
+
true
|
10
|
+
else
|
11
|
+
false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def update_engine(name, options={})
|
16
|
+
if @engines.key? name
|
17
|
+
@engines[name] = options
|
18
|
+
true
|
19
|
+
else
|
20
|
+
false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def remove_engine(name)
|
25
|
+
if @engines.key? name
|
26
|
+
@engines.delete(name)
|
27
|
+
true
|
28
|
+
else
|
29
|
+
false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Capricorn
|
4
|
+
class Satellite
|
5
|
+
class DependencyLoader
|
6
|
+
|
7
|
+
attr_reader :names, :specs, :engines
|
8
|
+
|
9
|
+
def self.load_for(engines)
|
10
|
+
dependency_loader = self.new(engines)
|
11
|
+
dependency_loader.add_dependecies!
|
12
|
+
dependency_loader.order_by_dependecies!
|
13
|
+
|
14
|
+
return dependency_loader
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(engines)
|
18
|
+
specs = engines.collect do |k,r|
|
19
|
+
s = Gem.source_index.find_name(k, Gem::Requirement.new(r[:version] || ">= 0.0.0"))
|
20
|
+
s.last
|
21
|
+
end.compact
|
22
|
+
|
23
|
+
@names = specs.collect { |spec| spec.name }
|
24
|
+
@specs = specs.inject({}) { |h, spec| h[spec.name] = spec ; h }
|
25
|
+
@engines = engines
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_dependecies!
|
29
|
+
@specs.values.each do |spec|
|
30
|
+
add_dependecies_for spec
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def order_by_dependecies!
|
35
|
+
@names = tsort
|
36
|
+
end
|
37
|
+
|
38
|
+
def each
|
39
|
+
@names.each do |name|
|
40
|
+
yield(@specs[name])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def reverse_each
|
45
|
+
@names.reverse.each do |name|
|
46
|
+
yield(@specs[name])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
include TSort
|
53
|
+
|
54
|
+
def add_dependecies_for(spec)
|
55
|
+
engine_dependencies = spec.engine_dependencies || {}
|
56
|
+
engine_dependencies.each do |name, options|
|
57
|
+
gems = Gem.source_index.find_name(name, [options[:version]].compact)
|
58
|
+
next unless gem = gems.last
|
59
|
+
next if @names.include?(name) and gem.version <= @specs[gem.name].version
|
60
|
+
@specs[gem.name] = gem
|
61
|
+
@names.push(gem.name)
|
62
|
+
add_dependecies_for(gem)
|
63
|
+
end
|
64
|
+
@engines = @engines.merge(engine_dependencies)
|
65
|
+
end
|
66
|
+
|
67
|
+
def tsort_each_node(&block)
|
68
|
+
@names.each(&block)
|
69
|
+
end
|
70
|
+
|
71
|
+
def tsort_each_child(node, &block)
|
72
|
+
engine_dependencies = @specs[node].engine_dependencies || {}
|
73
|
+
engine_dependencies.keys.each(&block)
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Capricorn
|
4
|
+
class Satellite
|
5
|
+
module Persistence
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.extend Capricorn::Satellite::Persistence::ClassMethods
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
def load(data)
|
14
|
+
Capricorn::Satellite.new(YAML.load(data))
|
15
|
+
end
|
16
|
+
|
17
|
+
def load_file(path)
|
18
|
+
return nil unless File.exist?(path)
|
19
|
+
Capricorn::Satellite.new(YAML.load_file(path))
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def dump(io=nil)
|
25
|
+
data = {}
|
26
|
+
|
27
|
+
private_vars = %w( basedomain subdomain )
|
28
|
+
instance_variables.each do |ivar_name|
|
29
|
+
ivar_name = ivar_name.to_s
|
30
|
+
ivar_name =~ /^@(.+)$/
|
31
|
+
name = $1
|
32
|
+
unless private_vars.include? name
|
33
|
+
data[name] = instance_variable_get(ivar_name.to_sym)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
if io
|
38
|
+
io.write YAML.dump(data)
|
39
|
+
else
|
40
|
+
YAML.dump(data)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def dump_file(path)
|
45
|
+
File.open(path, 'w+') { |f| dump(f) }
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|