simonmenke-shuttle 0.1.07

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 (48) hide show
  1. data/app_generators/engine/engine_generator.rb +39 -0
  2. data/app_generators/engine/templates/config/routes.rb +2 -0
  3. data/app_generators/engine/templates/init.rb +1 -0
  4. data/app_generators/engine/templates/lib/engine.rb +1 -0
  5. data/app_generators/engine/templates/rails/init.rb +1 -0
  6. data/bin/shuttle +20 -0
  7. data/lib/rubygems_plugin.rb +1 -0
  8. data/lib/shuttle/actor/actions.rb +76 -0
  9. data/lib/shuttle/actor.rb +23 -0
  10. data/lib/shuttle/actors/apache_actor.rb +56 -0
  11. data/lib/shuttle/actors/base_actor.rb +276 -0
  12. data/lib/shuttle/actors/mysql_actor.rb +20 -0
  13. data/lib/shuttle/actors/passenger_actor.rb +19 -0
  14. data/lib/shuttle/actors/plesk_actor.rb +210 -0
  15. data/lib/shuttle/actors/sqlite3_actor.rb +44 -0
  16. data/lib/shuttle/app_runner.rb +118 -0
  17. data/lib/shuttle/apps/dev.rb +27 -0
  18. data/lib/shuttle/apps/engines.rb +33 -0
  19. data/lib/shuttle/apps/jobs.rb +35 -0
  20. data/lib/shuttle/apps/satellite.rb +32 -0
  21. data/lib/shuttle/apps/server.rb +70 -0
  22. data/lib/shuttle/client/auth_token.rb +98 -0
  23. data/lib/shuttle/client.rb +48 -0
  24. data/lib/shuttle/exception_handler.rb +53 -0
  25. data/lib/shuttle/extentions/rubygems_plugin.rb +27 -0
  26. data/lib/shuttle/extentions/thor_extentions.rb +32 -0
  27. data/lib/shuttle/job_queue.rb +199 -0
  28. data/lib/shuttle/satellite/actions.rb +35 -0
  29. data/lib/shuttle/satellite/dependency_loader.rb +79 -0
  30. data/lib/shuttle/satellite/persistence.rb +50 -0
  31. data/lib/shuttle/satellite.rb +49 -0
  32. data/lib/shuttle/server/daemon.rb +85 -0
  33. data/lib/shuttle/server/proxy.rb +25 -0
  34. data/lib/shuttle/server/security.rb +113 -0
  35. data/lib/shuttle/server.rb +113 -0
  36. data/lib/shuttle/system/config.rb +36 -0
  37. data/lib/shuttle/system/helper.rb +21 -0
  38. data/lib/shuttle/system/options.rb +79 -0
  39. data/lib/shuttle/system/process_user.rb +75 -0
  40. data/lib/shuttle/system/satellites.rb +44 -0
  41. data/lib/shuttle/system/shell.rb +80 -0
  42. data/lib/shuttle/system.rb +159 -0
  43. data/lib/shuttle/systems/centos_plesk_system.rb +28 -0
  44. data/lib/shuttle/systems/macports_system.rb +14 -0
  45. data/lib/shuttle.rb +82 -0
  46. data/spec/actor/actions_spec.rb +13 -0
  47. data/spec/spec_helper.rb +1 -0
  48. metadata +129 -0
@@ -0,0 +1,39 @@
1
+ class EngineGenerator < RubiGen::Base
2
+ attr_reader :engine_name
3
+
4
+ def initialize(runtime_args, runtime_options = {})
5
+ super
6
+ @destination_root = args.shift
7
+ @engine_name = File.basename(File.expand_path(@destination_root)).underscore
8
+ end
9
+
10
+ def manifest
11
+ record do |m|
12
+
13
+ m.directory "app/controllers"
14
+ m.directory "app/models"
15
+ m.directory "app/views"
16
+ m.directory "app/helpers"
17
+ m.directory "config"
18
+ m.directory "db/migrate"
19
+ m.directory "lib"
20
+ m.directory "public/images"
21
+ m.directory "public/javascripts"
22
+ m.directory "public/stylesheets"
23
+ m.directory "rails"
24
+ m.directory "tasks"
25
+
26
+ m.template('config/routes.rb', "config/routes.rb")
27
+ m.template('Gmfile', "Gmfile")
28
+ m.template('rails/init.rb', "rails/init.rb")
29
+ m.template('init.rb', "init.rb")
30
+ m.template('tasks/engine_tasks.rake', "tasks/#{engine_name}_tasks.rake")
31
+ m.template('README.rdoc', "README.rdoc")
32
+ m.template('MIT-LICENSE.txt', "MIT-LICENSE.txt")
33
+ m.template('lib/engine.rb', "lib/#{engine_name}.rb")
34
+ m.template('gitignore', ".gitignore")
35
+
36
+ end
37
+ end
38
+
39
+ end
@@ -0,0 +1,2 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ end
@@ -0,0 +1 @@
1
+ require File.dirname(__FILE__)+'/rails/init'
@@ -0,0 +1 @@
1
+ # <%= engine_name.camelize %>
@@ -0,0 +1 @@
1
+ # Include hook code here
data/bin/shuttle ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+ begin
3
+ require File.dirname(__FILE__)+'/../lib/shuttle'
4
+ rescue LoadError
5
+ require 'rubygems'
6
+ require 'shuttle'
7
+ end
8
+
9
+ module Shuttle
10
+ BIN_PATH = File.expand_path($PROGRAM_NAME)
11
+ ORIGINAL_ARGV = ARGV.dup
12
+ end
13
+
14
+ Shuttle::AppRunner.use :Server
15
+ Shuttle::AppRunner.use :Satellite
16
+ Shuttle::AppRunner.use :Engines
17
+ Shuttle::AppRunner.use :Jobs
18
+ Shuttle::AppRunner.use :Dev
19
+ Shuttle::AppRunner.namespace = 'shuttle:apps'
20
+ Shuttle::AppRunner.start
@@ -0,0 +1 @@
1
+ require 'shuttle/extentions/rubygems_plugin'
@@ -0,0 +1,76 @@
1
+
2
+ module Shuttle
3
+ class Actor
4
+ module Actions
5
+
6
+ def self.included(base)
7
+ base.extend Shuttle::Actor::Actions::ClassMethods
8
+ end
9
+
10
+ # run the callbacks registerd to <tt>action</tt>. the will run the <tt>before</tt>, <tt>on</tt> and <tt>after</tt> fases.
11
+ def run_callbacks!(action)
12
+ action = action.to_sym
13
+ run_callbacks_in_fase! action, :before
14
+ run_callbacks_in_fase! action, :on
15
+ run_callbacks_in_fase! action, :after
16
+ end
17
+
18
+ # run the callbacks registerd to <tt>action</tt> in the +fase+
19
+ def run_callbacks_in_fase!(action, fase)
20
+ action = action.to_sym
21
+ fase = fase.to_sym
22
+ self.class.methods_for(action, fase).each { |meth| self.send(meth) }
23
+ end
24
+
25
+ module ClassMethods
26
+
27
+ # register a callback to be run <tt>before</tt> the <tt>action</tt>.
28
+ def before(action, meth)
29
+ methods_for(action, :before).push(meth.to_sym)
30
+ end
31
+
32
+ # register a callback to be run <tt>on</tt> the <tt>action</tt>.
33
+ def on(action, meth)
34
+ methods_for(action, :on).push(meth.to_sym)
35
+ end
36
+
37
+ # register a callback to be run <tt>after</tt> the <tt>action</tt>.
38
+ def after(action, meth)
39
+ methods_for(action, :after).push(meth.to_sym)
40
+ end
41
+
42
+ # get the registered callbacks for the +action+ and +face+.
43
+ def methods_for(action, fase)
44
+ action = action.to_sym
45
+ fase = fase.to_sym
46
+
47
+ @actions ||= {}
48
+ @actions[action] ||= {}
49
+ @actions[action][fase] ||= []
50
+ @actions[action][fase]
51
+ end
52
+
53
+ # define one or more actions.
54
+ def action(*names)
55
+ names.each do |name|
56
+ module_eval %{
57
+ def self.before_#{name}(meth)
58
+ before(:#{name}, meth)
59
+ end
60
+ def self.on_#{name}(meth)
61
+ on(:#{name}, meth)
62
+ end
63
+ def self.after_#{name}(meth)
64
+ after(:#{name}, meth)
65
+ end
66
+ def run_#{name}_callbacks!
67
+ run_callbacks!(:#{name})
68
+ end
69
+ }
70
+ end
71
+ end
72
+
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,23 @@
1
+
2
+ module Shuttle
3
+
4
+ # The actor class provides the mechanisme for scheduling the execution of seperate tasks.
5
+ class Actor
6
+
7
+ autoload :Actions, File.dirname(__FILE__)+'/actor/actions'
8
+
9
+ include Shuttle::Actor::Actions
10
+
11
+ attr_reader :system, :satellite
12
+
13
+ action :install_satellite, :uninstall_satellite, :link_satellite
14
+ action :install_engine, :uninstall_engine, :update_engine
15
+
16
+ # create a new actor for the provided system and satellite
17
+ def initialize(system, satellite)
18
+ @system = system
19
+ @satellite = satellite
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,56 @@
1
+
2
+ module Shuttle
3
+ module Actors # :nodoc:
4
+ class ApacheActor < Shuttle::Actor
5
+
6
+ on_install_satellite :write_config_file
7
+ after_install_satellite :restart
8
+
9
+ on_uninstall_satellite :remove_config_file
10
+ after_uninstall_satellite :restart
11
+
12
+ # restart the apache server
13
+ def restart
14
+ system.run "#{system.apachectl_path} -k restart"
15
+ end
16
+
17
+ # write the vhost config file (needs apache restart)
18
+ def write_config_file
19
+ config = %{<VirtualHost *>
20
+ ServerName #{satellite.domain}
21
+
22
+ ErrorLog logs/#{satellite.domain}.error.log
23
+ CustomLog logs/#{satellite.domain}.access.log common
24
+ DocumentRoot #{system.satellite_root}/public
25
+ <Directory "#{system.satellite_root}/public">
26
+ Options All
27
+ AllowOverride All
28
+ Order allow,deny
29
+ Allow from all
30
+ </Directory>
31
+ </VirtualHost>}
32
+ File.open(system.apache_conf_path, 'w+') { |f| f.write config }
33
+ end
34
+
35
+ # remove the vhost config file (needs apache restart)
36
+ def remove_config_file
37
+ File.unlink(system.apache_conf_path) if File.exist? system.apache_conf_path
38
+ end
39
+
40
+ module Config
41
+
42
+ # path to the apachectl tool
43
+ def apachectl_path(&block)
44
+ option(:apachectl_path, block) { |v| v or find_bin('apache2ctl', 'apachectl') }
45
+ end
46
+
47
+ # path to the vhost specific config files
48
+ def apache_conf_path(&block)
49
+ satellite_option(:apache_conf_path, block) { |s,v| v or "/opt/local/apache2/conf/apps/#{s.domain}.conf" }
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,276 @@
1
+
2
+ module Shuttle
3
+ module Actors # :nodoc:
4
+ class BaseActor < Shuttle::Actor
5
+
6
+ on_install_satellite :create_rails_app
7
+ on_link_satellite :link_engines
8
+ on_uninstall_satellite :destroy_rails_app
9
+
10
+ # create a new rails app for the current satellite
11
+ def create_rails_app
12
+ system.as_user(system.web_user, system.web_group) do
13
+ FileUtils.mkdir_p(File.dirname(system.satellite_root), :verbose => true)
14
+ FileUtils.mkdir_p(system.shared_root, :verbose => true)
15
+ end
16
+
17
+ Dir.chdir(File.dirname(system.satellite_root)) do
18
+ system.user_run system.web_user, "rails --force #{system.satellite_root}"
19
+ end
20
+
21
+ system.as_user(system.web_user, system.web_group) do
22
+ Dir.chdir(File.dirname(system.satellite_root)) do
23
+ link(File.join(system.shared_root, 'public'),
24
+ File.join(system.satellite_root, 'public', 'system'))
25
+ link(File.join(system.shared_root, 'private'),
26
+ File.join(system.satellite_root, 'db', 'system'))
27
+ link(File.join(system.shared_root, 'log'),
28
+ File.join(system.satellite_root, 'log'))
29
+ link(File.join(system.shared_root, 'settings'),
30
+ File.join(system.satellite_root, 'config', 'settings'))
31
+ end
32
+
33
+ end
34
+ end
35
+
36
+ # destroy the rails app for the current satellite
37
+ def destroy_rails_app
38
+ FileUtils.rm_rf system.satellite_root, :verbose => true
39
+ end
40
+
41
+ # link the required engines for the current satellite
42
+ def link_engines
43
+ Dir.chdir(system.satellite_root) do
44
+ system.as_user(system.web_user, system.web_group) do
45
+
46
+ write_environment
47
+ clean_links
48
+ @dependecies.reverse_each do |spec|
49
+ link_engine(spec)
50
+ end
51
+
52
+ end
53
+ run_migrations
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def link(src, dst)
60
+ FileUtils.mkdir_p(File.dirname(dst), :verbose => true)
61
+ FileUtils.mkdir_p(src, :verbose => true)
62
+ FileUtils.rm_rf dst, :verbose => true
63
+ FileUtils.symlink(src, dst, :verbose => true)
64
+ end
65
+
66
+ def write_environment
67
+ @dependecies = Shuttle::Satellite::DependencyLoader.load_for(satellite.engines)
68
+ @dependecies.engines
69
+
70
+ rails_header = "Rails::Initializer.run do |config|\n"
71
+ gems_header = " # Gems added by engine_manager:\n \n"
72
+
73
+ gsub_file('config/environment.rb') do |content|
74
+ content.gsub! /^\s*config.gem.+\n/, ''
75
+ content.gsub! %r{#{Regexp.escape(rails_header)}(#{Regexp.escape(gems_header)})?},
76
+ "#{rails_header}#{gems_header}"
77
+
78
+ @dependecies.reverse_each do |spec|
79
+ gem_options = @dependecies.engines[spec.name] || {}
80
+ content.gsub! "engine_manager:\n",
81
+ "engine_manager:\n config.gem #{spec.name.inspect}, #{gem_options.inspect}\n"
82
+ end
83
+ end
84
+ end
85
+
86
+ def link_engine(spec)
87
+ Shuttle.log "linking: #{spec.name}..."
88
+ path = File.join(spec.full_gem_path, 'public')
89
+ if File.directory?(path)
90
+ FileUtils.mkdir_p('public/vendor', :verbose => true)
91
+ FileUtils.ln_s(path, "public/vendor/#{spec.name}", :verbose => true)
92
+ end
93
+
94
+ path = File.join(spec.full_gem_path, 'tasks')
95
+ if File.directory?(path)
96
+ FileUtils.mkdir_p("lib/tasks/vendor/#{spec.name}", :verbose => true)
97
+ Dir.glob("#{path}/*.rake").each do |rake_file|
98
+ FileUtils.ln_s(rake_file,
99
+ "lib/tasks/vendor/#{spec.name}/#{File.basename(rake_file)}", :verbose => true)
100
+ end
101
+ end
102
+
103
+ path = File.join(spec.full_gem_path, 'db', 'migrate')
104
+ if File.directory?(path)
105
+ FileUtils.mkdir_p("db/migrate", :verbose => true)
106
+ unlinked_migrations.concat(Dir.glob("#{path}/*.rb"))
107
+ linked_migrations.each do |migration, target|
108
+ if target.starts_with? spec.full_gem_path
109
+ unlinked_migrations.delete(target)
110
+ unused_migrations.delete(migration)
111
+ end
112
+ end
113
+ end
114
+ end
115
+
116
+ def clean_links
117
+ FileUtils.rm_rf("lib/tasks/vendor", :verbose => true)
118
+ FileUtils.rm_rf("public/vendor", :verbose => true)
119
+ end
120
+
121
+ def run_migrations
122
+ Shuttle.log "running your migrations..." unless unlinked_migrations.empty? and unused_migrations.empty?
123
+
124
+ unlinked_migration_targets = unlinked_migrations.collect{ |migration|
125
+ File.basename(migration) }
126
+
127
+ unused_migrations.each do |migration, target|
128
+ unless unlinked_migration_targets.include? File.basename(migration)
129
+ migration =~ /(\d+)_[^.]+\.rb/
130
+ system.user_run(system.web_user, "cd #{system.satellite_root} ; rake db:migrate:down RAILS_ENV=#{system.rails_environment} VERSION=#{$1}")
131
+ end
132
+ FileUtils.rm_rf(migration, :verbose => true)
133
+ end
134
+ system.as_user(system.web_user, system.web_group) do
135
+ unlinked_migrations.each do |migration|
136
+ FileUtils.ln_s(migration, "db/migrate/#{File.basename(migration)}", :verbose => true)
137
+ end
138
+ end
139
+
140
+ unless unlinked_migrations.empty?
141
+ system.user_run(system.web_user, "cd #{system.satellite_root} ; rake db:migrate RAILS_ENV=#{system.rails_environment}")
142
+ end
143
+ end
144
+
145
+ def gsub_file(path, pattern=nil, replace=nil, &block)
146
+ if File.exist? path
147
+ content = File.read(path)
148
+ if block
149
+ block.call(content)
150
+ else
151
+ return false unless content.gsub!(pattern, replace)
152
+ end
153
+ File.open(path, 'w+') { |f| f.write content }
154
+ end
155
+ end
156
+
157
+ def linked_migrations
158
+ @linked_migrations ||= Dir.glob('db/migrate/*.rb').select { |migration| File.symlink?(migration) }.inject({}) { |m, migration| m[migration] = File.readlink(migration) ; m }
159
+ end
160
+
161
+ def unused_migrations
162
+ @unused_migrations ||= linked_migrations.dup
163
+ end
164
+
165
+ def unlinked_migrations
166
+ @unlinked_migrations ||= []
167
+ end
168
+
169
+ module Helper
170
+
171
+ # install a gem.
172
+ def gem_install(name, options={})
173
+ gem_cmd('install', name, options)
174
+ end
175
+
176
+ # check if a gem is installed
177
+ def gem_installed(name, options)
178
+ version = options[:version] || '0.0.0'
179
+ options = { :version => version, :installed => true }
180
+ (gem_cmd('list', name, options).strip == 'true')
181
+ end
182
+
183
+ # update a gem
184
+ def gem_update(name, options={})
185
+ !(gem_cmd('update', name, options) =~ /Nothing to update/)
186
+ end
187
+
188
+ # ensure the presence of a gem
189
+ def ensure_presence_of_gem(name, options={})
190
+ if !gem_installed(name, options)
191
+ gem_install(name, options)
192
+ end
193
+ end
194
+
195
+ private
196
+
197
+ def gem_cmd(cmd, args, options={})
198
+ user = options.delete(:user)
199
+ user ||= (install_gems_with_web_user ? web_user : system_user)
200
+
201
+ args = [args].flatten.compact
202
+ args.collect! { |a| (a and a.inspect) || '' }
203
+ args += options.map do |k,v|
204
+ if TrueClass === v
205
+ "--#{k}"
206
+ else
207
+ "--#{k}=#{v.inspect}"
208
+ end
209
+ end
210
+ output = user_run(user, "#{gem_bin_path} #{cmd} #{args.join(' ')}")
211
+ Gem.refresh
212
+ output
213
+ end
214
+
215
+ end
216
+
217
+ module Config
218
+
219
+ # set the path to the ruby executable.
220
+ def ruby_path(&block)
221
+ option(:ruby_path, block) { |s, v| v or find_bin('ruby', 'ruby1.8', 'ruby18') }
222
+ end
223
+
224
+ # set the path to the gem executable.
225
+ def gem_bin_path(&block)
226
+ option(:gem_bin_path, block) { |s, v| v or find_bin('gem', 'gem1.8', 'gem18') }
227
+ end
228
+
229
+ # set the path to the rails executable.
230
+ def rails_path(&block)
231
+ option(:rails_path, block) do |v|
232
+ user = (install_gems_with_web_user ? web_user : system_user)
233
+ v or user_find_bin(user, 'rails')
234
+ end
235
+ end
236
+
237
+ # set the owner group of the current satellite.
238
+ def web_group(&block)
239
+ satellite_option(:web_group, block)
240
+ end
241
+
242
+ # set the owner of the current satellite.
243
+ def web_user(&block)
244
+ satellite_option(:web_user, block)
245
+ end
246
+
247
+ # set the system user (the user which runs the shuttle server).
248
+ def system_user(&block)
249
+ option(:system_user, block) { |v| v or 'root' }
250
+ end
251
+
252
+ # set whether gems should be installed with the web user.
253
+ def install_gems_with_web_user(&block)
254
+ option(:install_gems_with_web_user, block)
255
+ end
256
+
257
+ # set the path to the satellite's root path
258
+ def satellite_root(&block)
259
+ satellite_option(:satellite_root, block)
260
+ end
261
+
262
+ # set the path to the satellite's shared path
263
+ def shared_root(&block)
264
+ satellite_option(:shared_root, block)
265
+ end
266
+
267
+ # set the rails environment.
268
+ def rails_environment(&block)
269
+ satellite_option(:rails_environment, block) { |s,v| v or 'development' }
270
+ end
271
+
272
+ end
273
+
274
+ end
275
+ end
276
+ end
@@ -0,0 +1,20 @@
1
+
2
+ module Shuttle
3
+ module Actors # :nodoc:
4
+ class MysqlActor < Shuttle::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 Shuttle
3
+ module Actors # :nodoc:
4
+ class PassengerActor < Shuttle::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