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