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,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