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,20 @@
1
+
2
+ module Capricorn
3
+ module Actors # :nodoc:
4
+ class MysqlActor < Capricorn::Actor
5
+
6
+ on_install_satellite :create_database
7
+ before_uninstall_satellite :backup_database
8
+ on_uninstall_satellite :drop_database
9
+
10
+ def create_database
11
+
12
+ end
13
+
14
+ def drop_database
15
+
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+
2
+ module Capricorn
3
+ module Actors # :nodoc:
4
+ class PassengerActor < Capricorn::Actor
5
+
6
+ after_install_satellite :restart
7
+ after_link_satellite :restart
8
+
9
+ # restart the current satellite.
10
+ def restart
11
+ system.as_user(system.web_user, system.web_group) do
12
+ tmp_restart = File.join(system.satellite_root, 'tmp', 'restart.txt')
13
+ FileUtils.touch tmp_restart, :verbose => true
14
+ end
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,210 @@
1
+
2
+ module Capricorn
3
+ module Actors # :nodoc:
4
+ class PleskActor < Capricorn::Actor
5
+
6
+ before_install_satellite :create_client
7
+ before_install_satellite :create_domain
8
+ after_install_satellite :link_htdocs
9
+ after_install_satellite :reload_subdomains
10
+ after_install_satellite :restart_apache
11
+ on_install_satellite :create_database
12
+ on_uninstall_satellite :drop_databases
13
+
14
+ def create_client
15
+ # only do this if this is needed
16
+ if false
17
+ unless system.client?(system.plesk_client)
18
+ system.create_client(system.plesk_client, system.plesk_client, 'mypwd')
19
+ end
20
+ end
21
+ end
22
+
23
+ def create_domain
24
+ unless system.domain?(satellite.basedomain)
25
+ system.create_domain(system.plesk_client, satellite.basedomain,
26
+ system.web_user[0,20], (rand(1_000_000_000) + 10_000).to_s)
27
+ else
28
+ httpdocs_path = "/var/www/vhosts/#{satellite.basedomain}/httpdocs"
29
+ system.set_satellite_option(:web_user,
30
+ system.get_user_name(File.stat(httpdocs_path).uid))
31
+ end
32
+
33
+ if satellite.subdomain? and !system.subdomain?(satellite.basedomain, satellite.subdomain)
34
+ system.create_subdomain(satellite.basedomain, satellite.subdomain)
35
+ end
36
+
37
+ FileUtils.mkdir_p(system.satellite_root)
38
+ FileUtils.mkdir_p(system.shared_root)
39
+ FileUtils.chown_R(system.web_user, system.web_group, system.satellite_root)
40
+ FileUtils.chown_R(system.web_user, system.web_group, system.shared_root)
41
+ end
42
+
43
+ def link_htdocs
44
+ httpdocs_path = File.join(File.dirname(system.satellite_root), 'httpdocs')
45
+ FileUtils.rm_rf(httpdocs_path)
46
+ FileUtils.ln_s(system.satellite_root, httpdocs_path)
47
+ FileUtils.chown_R(system.web_user, system.web_group, httpdocs_path)
48
+
49
+ File.open(File.join(system.satellite_root, '../conf/vhost.conf'), 'w+') do |f|
50
+ f.puts "DocumentRoot #{httpdocs_path}/public"
51
+ end
52
+ end
53
+
54
+ def reload_subdomains
55
+ system.run("#{system.plesk_websrvmng_bin} --reconfigure-vhost --vhost-name=#{satellite.basedomain}")
56
+ end
57
+
58
+ def restart_apache
59
+ system.run("#{system.plesk_httpd_bin} restart")
60
+ end
61
+
62
+ def create_database
63
+ db_name = satellite.domain.downcase.gsub(/[^a-z]+/, '_')[0,63]
64
+ db_user = db_name[0,13]
65
+ db_pswd = (rand(1_000_000_000) + 10_000).to_s
66
+
67
+ system.create_database(satellite.basedomain, "#{db_name}_d", "#{db_user}_ud", db_pswd)
68
+ system.create_database(satellite.basedomain, "#{db_name}_t", "#{db_user}_ut", db_pswd)
69
+ system.create_database(satellite.basedomain, "#{db_name}_p", "#{db_user}_up", db_pswd)
70
+
71
+
72
+ system.as_user(system.web_user, system.web_group) do
73
+ config = %{
74
+ development:
75
+ adapter: mysql
76
+ database: #{db_name}_d
77
+ username: #{db_user}_ud
78
+ password: #{db_pswd}
79
+ host: localhost
80
+ encoding: utf8
81
+ socket: /var/lib/mysql/mysql.sock
82
+
83
+ test:
84
+ adapter: mysql
85
+ database: #{db_name}_t
86
+ username: #{db_user}_ut
87
+ password: #{db_pswd}
88
+ host: localhost
89
+ encoding: utf8
90
+ socket: /var/lib/mysql/mysql.sock
91
+
92
+ production:
93
+ adapter: mysql
94
+ database: #{db_name}_p
95
+ username: #{db_user}_up
96
+ password: #{db_pswd}
97
+ host: localhost
98
+ encoding: utf8
99
+ socket: /var/lib/mysql/mysql.sock
100
+ }
101
+
102
+ db_file = File.join(system.satellite_root, 'config', 'database.yml')
103
+ File.open(db_file, 'w+') { |f| f.write config }
104
+ end
105
+ end
106
+
107
+ def drop_databases
108
+ db_name = satellite.domain.downcase.gsub(/[^a-z]+/, '_')[0,63]
109
+
110
+ system.drop_database("#{db_name}_d")
111
+ system.drop_database("#{db_name}_t")
112
+ system.drop_database("#{db_name}_p")
113
+ end
114
+
115
+ module Helper
116
+
117
+ def create_client(name, login, pwd)
118
+
119
+ end
120
+
121
+ # check is the client exists
122
+ def client?(login)
123
+ !(run("#{plesk_client_bin} -i #{login}") =~ /Object not found: Client/)
124
+ end
125
+
126
+ # create a domain through plesk
127
+ def create_domain(client, domain, user, passwd)
128
+ run("#{plesk_domain_bin} -c #{domain} -clogin #{client} -status enabled -hosting true -hst_type phys -dns true -www true -login #{user} -passwd #{passwd} -shell /bin/bash")
129
+ end
130
+
131
+ # check if a domain exists with plesk
132
+ def domain?(domain)
133
+ !(run("#{plesk_domain_bin} -i #{domain}") =~ /Object not found: Domain/)
134
+ end
135
+
136
+ # create a subdomain through plesk
137
+ def create_subdomain(basedomain, subdomain)
138
+ run("#{plesk_subdomain_bin} -c #{subdomain} -d #{basedomain}")
139
+ end
140
+
141
+ # check if a subdomain exists with plesk
142
+ def subdomain?(basedomain, subdomain)
143
+ run("#{plesk_subdomain_bin} -i -s #{subdomain} -d #{basedomain}") =~ /SUCCESS: Gathering/
144
+ end
145
+
146
+ # create a database through plesk
147
+ def create_database(basedomain, db_name, db_user, pwd)
148
+ o = run("#{plesk_database_bin} -c #{db_name} -domain #{basedomain} -server #{plesk_database_server} -add_user #{db_user} -passwd #{pwd}")
149
+ if o =~ /Database with requested name already exists/
150
+ o = run("#{plesk_database_bin} -u #{db_name} -add_user #{db_user} -passwd #{pwd}")
151
+ if o =~ /Unable to create database user: User/
152
+ o = run("#{plesk_database_bin} -u #{db_name} -update_user #{db_user} -passwd #{pwd}")
153
+ end
154
+ end
155
+ end
156
+
157
+ # drop a database through plesk
158
+ def drop_database(db_name)
159
+ run("#{plesk_database_bin} -r #{db_name}")
160
+ end
161
+
162
+ end
163
+
164
+ module Config
165
+
166
+ # set the plesk client to be used for this satellite.
167
+ def plesk_client(&block)
168
+ satellite_option(:plesk_client, block)
169
+ end
170
+
171
+ # path to the client tool.
172
+ def plesk_client_bin(&block)
173
+ option(:plesk_client_bin, block) { |v| v or '/usr/local/psa/bin/client' }
174
+ end
175
+
176
+ # path to the domain tool.
177
+ def plesk_domain_bin(&block)
178
+ option(:plesk_domain_bin, block) { |v| v or '/usr/local/psa/bin/domain' }
179
+ end
180
+
181
+ # path to the subdomain tool.
182
+ def plesk_subdomain_bin(&block)
183
+ option(:plesk_subdomain_bin, block) { |v| v or '/usr/local/psa/bin/subdomain' }
184
+ end
185
+
186
+ # path to the database tool.
187
+ def plesk_database_bin(&block)
188
+ option(:plesk_database_bin, block) { |v| v or '/usr/local/psa/bin/database' }
189
+ end
190
+
191
+ # path to the websrvmng tool.
192
+ def plesk_websrvmng_bin(&block)
193
+ option(:plesk_websrvmng_bin, block) { |v| v or '/usr/local/psa/admin/sbin/websrvmng' }
194
+ end
195
+
196
+ # path to the httpd tool.
197
+ def plesk_httpd_bin(&block)
198
+ option(:plesk_httpd_bin, block) { |v| v or '/etc/init.d/httpd' }
199
+ end
200
+
201
+ # host and port of database server.
202
+ def plesk_database_server(&block)
203
+ option(:plesk_database_server, block)
204
+ end
205
+
206
+ end
207
+
208
+ end
209
+ end
210
+ end
@@ -0,0 +1,44 @@
1
+
2
+ module Capricorn
3
+ module Actors # :nodoc:
4
+ class Sqlite3Actor < Capricorn::Actor
5
+
6
+ after_install_satellite :write_config_file
7
+
8
+ # write the +database.yml+ config file.
9
+ def write_config_file
10
+ system.as_user(system.web_user, system.web_group) do
11
+
12
+ config = %{# SQLite version 3.x
13
+ # gem install sqlite3-ruby (not necessary on OS X Leopard)
14
+ development:
15
+ adapter: sqlite3
16
+ database: db/system/development.sqlite3
17
+ pool: 5
18
+ timeout: 5000
19
+
20
+ # Warning: The database defined as "test" will be erased and
21
+ # re-generated from your development database when you run "rake".
22
+ # Do not set this db to the same as development or production.
23
+ test:
24
+ adapter: sqlite3
25
+ database: db/system/test.sqlite3
26
+ pool: 5
27
+ timeout: 5000
28
+
29
+ production:
30
+ adapter: sqlite3
31
+ database: db/system/production.sqlite3
32
+ pool: 5
33
+ timeout: 5000
34
+ }
35
+
36
+ db_file = File.join(system.satellite_root, 'config', 'database.yml')
37
+ File.open(db_file, 'w+') { |f| f.write config }
38
+
39
+ end
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,119 @@
1
+ Capricorn.runtime_gem('thor', Capricorn::THOR_VERSION)
2
+
3
+ require File.dirname(__FILE__)+'/extentions/thor_extentions'
4
+
5
+ module Capricorn
6
+
7
+ # AppRunner allows us to have multiple apps in different namespaces
8
+ class AppRunner < Thor
9
+
10
+ # register a subapplication with the app runner.
11
+ def self.use(app)
12
+ Capricorn::Apps.const_get(app)
13
+ end
14
+
15
+ # Override Thor#help so we can give info about not-yet-loaded tasks
16
+ def help(task = nil)
17
+ super
18
+
19
+ unless task
20
+ search = ".*#{search}" if options["substring"]
21
+ search = /^#{search}.*/i
22
+ group = options[:group] || "standard"
23
+
24
+ classes = Thor.subclasses.select do |k|
25
+ (options[:all] || k.group_name == group) &&
26
+ Thor::Util.constant_to_thor_path(k.name) =~ search
27
+ end
28
+ display_klasses(false, classes)
29
+ end
30
+ end
31
+
32
+ # forward actions to the sub apps
33
+ def method_missing(meth, *args)
34
+ meth = meth.to_s
35
+ super(meth.to_sym, *args) unless meth.include?(?:)
36
+
37
+ begin
38
+ task = Thor[meth]
39
+ task.parse(task.klass.new, ARGV[1..-1])
40
+ rescue => e
41
+ puts e.message
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def display_klasses(with_modules = false, klasses = Thor.subclasses)
48
+ klasses -= [Thor, Capricorn::AppRunner] unless with_modules
49
+ raise Error, "No Thor tasks available" if klasses.empty?
50
+
51
+ if with_modules && !thor_yaml.empty?
52
+ max_name = thor_yaml.max { |(xk, xv), (yk, yv)| xk.to_s.size <=> yk.to_s.size }.first.size
53
+ modules_label = "Modules"
54
+ namespaces_label = "Namespaces"
55
+ column_width = [max_name + 4, modules_label.size + 1].max
56
+
57
+ print "%-#{column_width}s" % modules_label
58
+ puts namespaces_label
59
+ print "%-#{column_width}s" % ("-" * modules_label.size)
60
+ puts "-" * namespaces_label.size
61
+
62
+ thor_yaml.each do |name, info|
63
+ print "%-#{column_width}s" % name
64
+ puts info[:constants].map { |c| Thor::Util.constant_to_thor_path(c) }.join(", ")
65
+ end
66
+
67
+ puts
68
+ end
69
+
70
+ # Calculate the largest base class name
71
+ max_base = klasses.max do |x,y|
72
+ Thor::Util.constant_to_thor_path(x.name).size <=> Thor::Util.constant_to_thor_path(y.name).size
73
+ end.name.size
74
+
75
+ # Calculate the size of the largest option description
76
+ max_left_item = klasses.max do |x,y|
77
+ (x.maxima.usage + x.maxima.opt).to_i <=> (y.maxima.usage + y.maxima.opt).to_i
78
+ end
79
+
80
+ max_left = max_left_item.maxima.usage + max_left_item.maxima.opt
81
+
82
+ unless klasses.empty?
83
+ puts # add some spacing
84
+ klasses.each { |k| display_tasks(k, max_base, max_left); }
85
+ else
86
+ puts "\033[1;34mNo Thor tasks available\033[0m"
87
+ end
88
+ end
89
+
90
+ def display_tasks(klass, max_base, max_left)
91
+ if klass.tasks.values.length > 1
92
+
93
+ base = Thor::Util.constant_to_thor_path(klass.name)
94
+
95
+ if base.to_a.empty?
96
+ base = 'default'
97
+ puts "\033[1;35m#{base}\033[0m"
98
+ else
99
+ puts "\033[1;34m#{base}\033[0m"
100
+ end
101
+
102
+ puts "-" * base.length
103
+
104
+ klass.tasks.each true do |name, task|
105
+ format_string = "%-#{max_left + max_base + 5}s"
106
+ print format_string % task.formatted_usage(true)
107
+ puts task.description
108
+ end
109
+
110
+ unless klass.opts.empty?
111
+ puts "\nglobal options: #{Options.new(klass.opts)}"
112
+ end
113
+
114
+ puts # add some spacing
115
+ end
116
+ end
117
+
118
+ end
119
+ end
@@ -0,0 +1,15 @@
1
+ Capricorn.runtime_gem('thor', Capricorn::THOR_VERSION)
2
+
3
+ module Capricorn
4
+ module Apps # :nodoc:
5
+
6
+ class Dev < Thor
7
+ desc "activate DOMAIN", "turn an existing satelite into a development satelite"
8
+ def activate(domain)
9
+ Capricorn.runtime_gem('rubigen', Capricorn::RUBIGEN_VERSION)
10
+ Capricorn.client.make_development_satellite(domain)
11
+ end
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,33 @@
1
+ Capricorn.runtime_gem('thor', Capricorn::THOR_VERSION)
2
+
3
+ module Capricorn
4
+ module Apps # :nodoc:
5
+
6
+ class Engines < Thor
7
+ desc 'install DOMAIN NAME', 'install an engine'
8
+ method_options :version => :required, :lib => :optional, :source => :optional, :token => :optional
9
+ def install(domain, name)
10
+ desc = { :version => options[:version] }
11
+ desc[:lib] = options[:lib] if options[:lib]
12
+ desc[:source] = options[:source] if options[:source]
13
+ Capricorn.client(options[:token]).install_engine(domain, name, desc)
14
+ end
15
+
16
+ desc 'update DOMAIN NAME', 'update an engine'
17
+ method_options :version => :required, :lib => :optional, :source => :optional, :token => :optional
18
+ def update(domain, name)
19
+ desc = { :version => options[:version] }
20
+ desc[:lib] = options[:lib] if options[:lib]
21
+ desc[:source] = options[:source] if options[:source]
22
+ Capricorn.client(options[:token]).update_engine(domain, name, desc)
23
+ end
24
+
25
+ desc 'uninstall DOMAIN NAME', 'uninstall an engine'
26
+ method_options :token => :optional
27
+ def uninstall(domain, name)
28
+ Capricorn.client(options[:token]).uninstall_engine(domain, name)
29
+ end
30
+ end
31
+
32
+ end
33
+ end