rails_pwnerer 0.5.0 → 0.5.1

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/CHANGELOG CHANGED
@@ -1,3 +1,5 @@
1
+ v0.5.1. Application instances with per-instance configuration.
2
+
1
3
  v0.5.0. Implemented configuration repository.
2
4
 
3
5
  v0.4.19. Fixed bug in cleaning up application directory on SVN update.
@@ -5,47 +5,64 @@ require 'fileutils'
5
5
  class RailsPwnage::App::ClusterConfig
6
6
  include RailsPwnage::Base
7
7
 
8
- def fix_permissions(app_name)
9
- pwnerer_user = RailsPwnage::Config.pwnerer_user
8
+ def fix_permissions(app_name, instance_name)
9
+ app_config = RailsPwnage::Config[app_name, instance_name]
10
+ pwnerer_user = app_config[:pwnerer_user]
10
11
  pwnerer_uid = uid_for_username(pwnerer_user)
11
12
  pwnerer_group = group_for_username(pwnerer_user)
12
13
 
13
- Dir.chdir(RailsPwnage::Config.path_to(app_name)) do
14
+ Dir.chdir app_config[:app_path] do
14
15
  %w(log tmp public).each do |writable_dir|
15
16
  FileUtils.chown_R(pwnerer_uid, pwnerer_group, writable_dir)
16
17
  end
17
18
  end
18
19
  end
20
+
21
+ def manage_ports(app_name, instance_name, action)
22
+ app_config = RailsPwnage::Config[app_name, instance_name]
23
+ return unless app_config and app_config[:port0] and app_config[:mongrels]
24
+
25
+ case action
26
+ when :alloc
27
+ app_config[:port0] = RailsPwnage::Config.alloc_ports app_config[:mongrels]
28
+ when :free
29
+ RailsPwnage::Config.free_ports app_config[:port0], app_config[:mongrels]
30
+ app_config[:port0] = 0
31
+ end
32
+ RailsPwnage::Config.flush_db RailsPwnage::Config.app_db_name(app_name, instance_name)
33
+ end
19
34
 
20
- def configure_mongrels(app_name)
21
- app_path = RailsPwnage::Config.path_to app_name
22
- pwnerer_user = RailsPwnage::Config.pwnerer_user
35
+
36
+ def configure_mongrels(app_name, instance_name)
37
+ app_config = RailsPwnage::Config[app_name, instance_name]
38
+
39
+ app_path, pwnerer_user = app_config[:app_path], app_config[:pwnerer_user]
23
40
  pwnerer_group = group_for_username(pwnerer_user)
24
41
 
25
- instances = RailsPwnage::Config.app_instances(app_name)
26
- first_port = RailsPwnage::Config.app_port0(app_name)
42
+ mongrels, first_port = app_config[:mongrels], app_config[:port0]
27
43
 
28
44
  Dir.chdir(app_path) do
29
45
  # create the mongrel_cluster configuration
30
- system "mongrel_rails cluster::configure -e production -N #{instances} -p #{first_port} -a 127.0.0.1 -c #{app_path} --user #{pwnerer_user} --group #{pwnerer_group}"
46
+ system "mongrel_rails cluster::configure -e production -N #{mongrels} -p #{first_port} -a 127.0.0.1 -c #{app_path} --user #{pwnerer_user} --group #{pwnerer_group}"
31
47
 
32
48
  # copy the configuration to the launch directory
33
- launch_config = File.join RailsPwnage::Config.path_to(:mongrel_configs), "#{app_name}.yml"
49
+ launch_config = File.join RailsPwnage::Config.path_to(:mongrel_configs), "#{app_name}.#{instance_name}.yml"
34
50
  FileUtils.cp 'config/mongrel_cluster.yml', launch_config
35
51
  end
36
52
  end
37
53
 
38
- def remove_mongrels(app_name)
54
+ def remove_mongrels(app_name, instance_name)
39
55
  # bomb the configuration from the launch directory
40
- launch_config = File.join RailsPwnage::Config.path_to(:mongrel_configs), "#{app_name}.yml"
56
+ launch_config = File.join RailsPwnage::Config.path_to(:mongrel_configs), "#{app_name}.#{instance_name}.yml"
41
57
  File.delete launch_config if File.exists? launch_config
42
58
  end
43
59
 
44
- def stop_mongrels(app_name)
60
+ def stop_mongrels(app_name, instance_name)
61
+ app_config = RailsPwnage::Config[app_name, instance_name]
45
62
  # silently die if the app was completely busted
46
- return unless File.exists? RailsPwnage::Config.path_to(app_name)
63
+ return unless app_config and File.exists? app_config[:app_path]
47
64
 
48
- Dir.chdir(RailsPwnage::Config.path_to(app_name)) do
65
+ Dir.chdir app_config[:app_path] do
49
66
  system 'mongrel_rails cluster::stop'
50
67
 
51
68
  # clean up PID files in case the mongrels died and left them behind
@@ -53,40 +70,45 @@ class RailsPwnage::App::ClusterConfig
53
70
  end
54
71
  end
55
72
 
56
- def start_mongrels(app_name)
73
+ def start_mongrels(app_name, instance_name)
74
+ app_config = RailsPwnage::Config[app_name, instance_name]
57
75
  # silently die if the app was completely busted
58
- return unless File.exists? RailsPwnage::Config.path_to(app_name)
76
+ return unless app_config and File.exists? app_config[:app_path]
59
77
 
60
- Dir.chdir(RailsPwnage::Config.path_to(app_name)) do
78
+ Dir.chdir app_config[:app_path] do
61
79
  system 'mongrel_rails cluster::start'
62
80
  end
63
81
  end
64
82
 
65
- def setup(app_name)
66
- configure_mongrels app_name
67
- fix_permissions app_name
83
+ def setup(app_name, instance_name)
84
+ manage_ports app_name, instance_name, :alloc
85
+ configure_mongrels app_name, instance_name
86
+ fix_permissions app_name, instance_name
68
87
  end
69
88
 
70
- def update(app_name, &update_proc)
71
- stop_mongrels(app_name)
89
+ def update(app_name, instance_name, &update_proc)
90
+ stop_mongrels app_name, instance_name
91
+ manage_ports app_name, instance_name, :free
72
92
  yield
73
93
  ensure
74
- configure_mongrels app_name
75
- fix_permissions app_name
76
- start_mongrels(app_name)
94
+ manage_ports app_name, instance_name, :alloc
95
+ configure_mongrels app_name, instance_name
96
+ fix_permissions app_name, instance_name
97
+ start_mongrels app_name, instance_name
77
98
  end
78
99
 
79
- def remove(app_name)
80
- remove_mongrels app_name
100
+ def remove(app_name, instance_name)
101
+ remove_mongrels app_name, instance_name
102
+ manage_ports app_name, instance_name, :free
81
103
  end
82
104
 
83
- def manage(app_name, action)
105
+ def manage(app_name, instance_name, action)
84
106
  case action
85
107
  when :checkpoint
86
108
  # nothing to do here
87
109
  when :rollback
88
- configure_mongrels app_name
89
- fix_permissions app_name
110
+ configure_mongrels app_name, instance_name
111
+ fix_permissions app_name, instance_name
90
112
  end
91
113
  end
92
114
 
@@ -97,25 +119,5 @@ class RailsPwnage::App::ClusterConfig
97
119
  when :stop
98
120
  control_boot_script('mongrel_cluster', :stop)
99
121
  end
100
- end
101
-
102
- def self.setup(app_name)
103
- self.new.setup(app_name)
104
- end
105
-
106
- def self.remove(app_name)
107
- self.new.remove(app_name)
108
- end
109
-
110
- def self.update(app_name, &update_proc)
111
- self.new.update(app_name, &update_proc)
112
- end
113
-
114
- def self.manage(app_name, action)
115
- self.new.manage(app_name, action)
116
- end
117
-
118
- def self.control_all(action = :start)
119
- self.new.control_all(action)
120
122
  end
121
123
  end
@@ -6,12 +6,14 @@ class RailsPwnage::App::Database
6
6
  include RailsPwnage::Base
7
7
 
8
8
  # creates/drops the mysql database for the application
9
- def admin_database(app_name, action = :create)
10
- db_name = RailsPwnage::Config.app_dbname(app_name)
11
- db_user = RailsPwnage::Config.app_db_user(app_name)
12
- db_pass = RailsPwnage::Config.app_db_password(app_name)
9
+ def admin_database(app_name, instance_name, action = :create)
10
+ app_config = RailsPwnage::Config[app_name, instance_name]
11
+ # exit and don't complain if the app is busted
12
+ return unless app_config and File.exists? app_config[:app_path]
13
+
14
+ db_name, db_user, db_pass = app_config[:db_name], app_config[:db_user], app_config[:db_pass]
13
15
 
14
- Dir.chdir(RailsPwnage::Config.path_to(app_name)) do
16
+ with_temp_dir do
15
17
  # put together the admin script
16
18
  case action
17
19
  when :create
@@ -26,53 +28,55 @@ ENDSQL
26
28
  end
27
29
 
28
30
  # run it
29
- File.open('tmp/admin_db.sql', 'w') { |f| f.write sql_commands }
30
- system "mysql -uroot < tmp/admin_db.sql"
31
+ File.open('admin_db.sql', 'w') { |f| f.write sql_commands }
32
+ dbroot_name = RailsPwnage::Config[:host][:dbroot_name]
33
+ dbroot_pass = RailsPwnage::Config[:host][:dbroot_pass]
34
+ dbpass_arg = dbroot_pass.empty? ? '' : "-p#{dbroot_pass}"
35
+ system "mysql -u#{dbroot_name} #{dbpass_arg} < admin_db.sql"
31
36
 
32
37
  # cleanup
33
- File.delete('tmp/admin_db.sql')
38
+ File.delete('admin_db.sql')
34
39
  end
35
40
  end
36
41
 
37
42
  # configures rails to use the database in the production environment
38
- def configure_rails(app_name)
39
- db_name = RailsPwnage::Config.app_dbname(app_name)
40
- db_user = RailsPwnage::Config.app_db_user(app_name)
41
- db_pass = RailsPwnage::Config.app_db_password(app_name)
43
+ def configure_rails(app_name, instance_name)
44
+ app_config = RailsPwnage::Config[app_name, instance_name]
45
+ db_name, db_user, db_pass = app_config[:db_name], app_config[:db_user], app_config[:db_pass]
42
46
 
43
- config_file = RailsPwnage::Config.path_to(app_name) + File::SEPARATOR + 'config' + File::SEPARATOR + 'database.yml'
47
+ config_file = File.join app_config[:app_path], 'config', 'database.yml'
44
48
  configuration = File.open(config_file, 'r') { |f| YAML.load f }
45
49
  configuration['production'].merge! 'adapter' => 'mysql', 'database' => db_name, 'username' => db_user, 'password' => db_pass
46
50
  File.open(config_file, 'w') { |f| YAML.dump(configuration, f) }
47
51
 
48
52
  # bonus: lock down the database so only the right user can access it
49
- pwnerer_user = RailsPwnage::Config.pwnerer_user
53
+ pwnerer_user = app_config[:pwnerer_user]
50
54
  File.chmod(0600, config_file)
51
55
  File.chown(uid_for_username(pwnerer_user), gid_for_username(pwnerer_user), config_file)
52
56
  end
53
57
 
54
58
  # migrates the database to the latest schema version
55
- def migrate_database(app_name)
56
- Dir.chdir(RailsPwnage::Config.path_to(app_name)) do
59
+ def migrate_database(app_name, instance_name)
60
+ Dir.chdir RailsPwnage::Config[app_name, instance_name][:app_path] do
57
61
  # now migrate the database
58
62
  system "rake db:migrate RAILS_ENV=production"
59
63
  end
60
64
  end
61
65
 
62
66
  # creates a database dump in the backup area
63
- def dump_database(app_name)
64
- db_name = RailsPwnage::Config.app_dbname(app_name)
65
- db_user = RailsPwnage::Config.app_db_user(app_name)
66
- db_pass = RailsPwnage::Config.app_db_password(app_name)
67
+ def dump_database(app_name, instance_name)
68
+ app_config = RailsPwnage::Config[app_name, instance_name]
69
+ db_name, db_user, db_pass = app_config[:db_name], app_config[:db_user], app_config[:db_pass]
67
70
 
68
- pwnerer_user = RailsPwnage::Config.pwnerer_user
71
+ pwnerer_user = app_config[:pwnerer_user]
69
72
  pwnerer_uid = uid_for_username(pwnerer_user)
70
73
  pwnerer_gid = gid_for_username(pwnerer_user)
71
74
 
72
75
  timestamp = Time.now.strftime '%Y%m%d%H%M%S'
73
- dump_file = "db/#{app_name}_#{timestamp}.sql"
74
- Dir.chdir(RailsPwnage::Config.path_to(:backup, app_name)) do
75
- system "mysqldump --add-drop-database --add-drop-table --extended-insert --single-transaction -u#{db_user} -p#{db_pass} #{db_name} > #{dump_file}"
76
+ dump_file = "db/#{app_name}.#{instance_name}_#{timestamp}.sql"
77
+ Dir.chdir app_config[:backup_path] do
78
+ system("mysqldump --add-drop-database --add-drop-table --extended-insert" +
79
+ " --single-transaction -u#{db_user} -p#{db_pass} #{db_name} > #{dump_file}")
76
80
  # lockdown the file
77
81
  File.chmod(0400, dump_file)
78
82
  File.chown(pwnerer_uid, pwnerer_gid, dump_file)
@@ -80,48 +84,46 @@ ENDSQL
80
84
  end
81
85
 
82
86
  # loads the latest database dump from the backup area
83
- def load_database(app_name)
84
- db_name = RailsPwnage::Config.app_dbname(app_name)
85
- db_user = RailsPwnage::Config.app_db_user(app_name)
86
- db_pass = RailsPwnage::Config.app_db_password(app_name)
87
+ def load_database(app_name, instance_name)
88
+ app_config = RailsPwnage::Config[app_name, instance_name]
89
+ db_name, db_user, db_pass = app_config[:db_name], app_config[:db_user], app_config[:db_pass]
87
90
 
88
- Dir.chdir(RailsPwnage::Config.path_to(:backup, app_name)) do
91
+ Dir.chdir app_config[:backup_path] do
89
92
  # find the latest dump and load it in
90
- dump_file = Dir.glob("db/#{app_name}_*").max
93
+ dump_file = Dir.glob("db/#{app_name}.#{instance_name}_*").max
91
94
  system "mysql -u#{db_user} -p#{db_pass} #{db_name} < #{dump_file}"
92
95
  end
93
96
  end
94
97
 
95
- def setup(app_name)
98
+ def setup(app_name, instance_name)
96
99
  control_boot_script('mysql', :start)
97
- admin_database app_name, :create
98
- configure_rails app_name
99
- migrate_database app_name
100
+ admin_database app_name, instance_name, :create
101
+ configure_rails app_name, instance_name
102
+ migrate_database app_name, instance_name
100
103
  end
101
104
 
102
- def update(app_name)
105
+ def update(app_name, instance_name)
103
106
  control_boot_script('mysql', :start)
104
- configure_rails app_name
105
- migrate_database app_name
107
+ configure_rails app_name, instance_name
108
+ migrate_database app_name, instance_name
106
109
  end
107
110
 
108
- def remove(app_name)
111
+ def remove(app_name, instance_name)
109
112
  control_boot_script('mysql', :start)
110
- admin_database app_name, :drop
113
+ admin_database app_name, instance_name, :drop
111
114
  end
112
115
 
113
116
  # backs up or restores the database
114
- def manage(app_name, action)
115
-
117
+ def manage(app_name, instance_name, action)
116
118
  case action
117
119
  when :checkpoint
118
- dump_database app_name
120
+ dump_database app_name, instance_name
119
121
  when :rollback
120
- admin_database app_name, :drop
121
- admin_database app_name, :create
122
- load_database app_name
123
- configure_rails app_name
124
- migrate_database app_name
122
+ admin_database app_name, instance_name, :drop
123
+ admin_database app_name, instance_name, :create
124
+ load_database app_name, instance_name
125
+ configure_rails app_name, instance_name
126
+ migrate_database app_name, instance_name
125
127
  end
126
128
  end
127
129
 
@@ -133,24 +135,4 @@ ENDSQL
133
135
  control_boot_script('mysql', :stop)
134
136
  end
135
137
  end
136
-
137
- def self.setup(app_name)
138
- self.new.setup(app_name)
139
- end
140
-
141
- def self.update(app_name)
142
- self.new.update(app_name)
143
- end
144
-
145
- def self.remove(app_name)
146
- self.new.remove(app_name)
147
- end
148
-
149
- def self.manage(app_name, action)
150
- self.new.manage(app_name, action)
151
- end
152
-
153
- def self.control_all(action = :start)
154
- self.new.control_all(action)
155
- end
156
138
  end
@@ -2,26 +2,16 @@
2
2
 
3
3
  class RailsPwnage::App::Gems
4
4
  include RailsPwnage::Base
5
-
6
- def setup(app_name)
7
- Dir.chdir(RailsPwnage::Config.path_to(app_name)) do
8
- # install the gems needed by the app
9
- system "rake gems:install RAILS_ENV=production"
10
- end
11
- end
12
5
 
13
- def update(app_name)
14
- Dir.chdir(RailsPwnage::Config.path_to(app_name)) do
6
+ def update(app_name, instance_name)
7
+ app_path = RailsPwnage::Config[app_name, instance_name][:app_path]
8
+ Dir.chdir app_path do
15
9
  # install the gems needed by the app
16
10
  system "rake gems:install RAILS_ENV=production"
17
11
  end
18
12
  end
19
13
 
20
- def self.setup(app_name)
21
- self.new.setup(app_name)
22
- end
23
-
24
- def self.update(app_name)
25
- self.new.update(app_name)
14
+ def setup(app_name, instance_name)
15
+ update(app_name, instance_name)
26
16
  end
27
17
  end
@@ -1,51 +1,72 @@
1
1
  module RailsPwnage::App
2
- # installs an application given its SVN path
3
- def self.install(svn_path)
4
- app_name = Svn.setup(svn_path)
5
- Gems.setup(app_name)
6
- Database.setup(app_name)
7
- ClusterConfig.setup(app_name)
8
- NginxConfig.setup(app_name)
2
+ # internal method implementing magic instance names
3
+ def self.instance_magic(app_name, instance_name)
4
+ case instance_name
5
+ when '*'
6
+ RailsPwnage::Config.all_instances app_name { |i| yield app_name, i }
7
+ when '.'
8
+ yield app_name, RailsPwnage::Config[:host][:instance]
9
+ else
10
+ yield app_name, instance_name
11
+ end
9
12
  end
10
13
 
14
+ # installs an application given its SVN path
15
+ def self.install(svn_path, instance_name)
16
+ app_name = File.basename svn_path
17
+ instance_magic(app_name, instance_name) do |app, instance|
18
+ Config.new.alloc app, instance
19
+ Svn.new.checkout svn_path, app, instance
20
+ [Config, Svn, Gems, Database, ClusterConfig, NginxConfig].each do |mod|
21
+ mod.new.setup app, instance
22
+ end
23
+ end
24
+ end
25
+
11
26
  # updates an application (restart servers if necessary)
12
- def self.update(app_name)
13
- ClusterConfig.update app_name do
14
- Svn.update app_name
15
- Gems.update app_name
16
- Database.update app_name
17
- end
18
- NginxConfig.update app_name
27
+ def self.update(app_name, instance_name)
28
+ instance_magic(app_name, instance_name) do |app, instance|
29
+ ClusterConfig.new.update app, instance do
30
+ [Svn, Config, Gems, Database].each do |mod|
31
+ mod.new.update app, instance
32
+ end
33
+ end
34
+ NginxConfig.new.update app, instance
35
+ end
19
36
  end
20
37
 
21
38
  # removes an application (and stops its servers)
22
- def self.remove(app_name)
23
- ClusterConfig.remove app_name
24
- NginxConfig.remove app_name
25
- Database.remove app_name
26
- Svn.remove app_name
39
+ def self.remove(app_name, instance_name)
40
+ instance_magic(app_name, instance_name) do |app, instance|
41
+ [ClusterConfig, NginxConfig, Database, Svn, Config].each do |mod|
42
+ mod.new.remove app, instance
43
+ end
44
+ end
27
45
  end
28
46
 
29
47
  # performs application management (checkpoint / rollback / console)
30
- def self.manage(app_name, action = :checkpoint)
31
- case action
32
- when :checkpoint
33
- ClusterConfig.manage app_name, action
34
- Svn.manage app_name, action
35
- ClusterConfig.update app_name do
36
- Database.manage app_name, action
37
- end
38
- when :rollback
39
- ClusterConfig.update app_name do
40
- Svn.manage app_name, action
41
- Database.manage app_name, action
42
- ClusterConfig.manage app_name, action
43
- end
44
- when :console
45
- Svn.manage app_name, action
46
- when :db_console
47
- Svn.manage app_name, action
48
- end
48
+ def self.manage(app_name, instance_name, action = :checkpoint)
49
+ instance_magic(app_name, instance_name) do |app, instance|
50
+ # TODO: add backup / restore for the configuration db (easy)
51
+ case action
52
+ when :checkpoint
53
+ ClusterConfig.new.manage app, instance, action
54
+ Svn.new.manage app, instance, action
55
+ ClusterConfig.new.update app, instance do
56
+ Database.new.manage app, instance, action
57
+ end
58
+ when :rollback
59
+ ClusterConfig.new.update app, instance do
60
+ [Svn, Database, ClusterConfig].each do |mod|
61
+ mod.new.manage app, instance, action
62
+ end
63
+ end
64
+ when :console
65
+ Svn.new.manage app, instance, action
66
+ when :db_console
67
+ Svn.new.manage app, instance, action
68
+ end
69
+ end
49
70
  end
50
71
 
51
72
  # start or stop all apps
@@ -53,13 +74,13 @@ module RailsPwnage::App
53
74
  case action
54
75
  when :start
55
76
  control_all :stop
56
- Database.control_all :start
57
- ClusterConfig.control_all :start
58
- NginxConfig.control_all :start
77
+ Database.new.control_all :start
78
+ ClusterConfig.new.control_all :start
79
+ NginxConfig.new.control_all :start
59
80
  when :stop
60
- NginxConfig.control_all :stop
61
- ClusterConfig.control_all :stop
62
- Database.control_all :stop
81
+ NginxConfig.new.control_all :stop
82
+ ClusterConfig.new.control_all :stop
83
+ Database.new.control_all :stop
63
84
  end
64
85
  end
65
86
  end
@@ -4,15 +4,16 @@ class RailsPwnage::App::NginxConfig
4
4
  include RailsPwnage::Base
5
5
 
6
6
  # writes the nginx configuration for this server
7
- def config_nginx(app_name)
8
- first_port = RailsPwnage::Config.app_port0(app_name)
9
- hostname_filter = RailsPwnage::Config.app_servername(app_name)
7
+ def config_nginx(app_name, instance_name)
8
+ app_config = RailsPwnage::Config[app_name, instance_name]
9
+ first_port = app_config[:port0]
10
+ hostname_filter = app_config[:dns_name]
10
11
 
11
- nginx_config = File.join(RailsPwnage::Config.path_to(:nginx_configs), app_name)
12
+ nginx_config = File.join(RailsPwnage::Config.path_to(:nginx_configs), app_name + '.' + instance_name)
12
13
  File.open(nginx_config, 'w') do |f|
13
14
  # link to the mongrels
14
- f << " upstream #{app_name} {\n"
15
- RailsPwnage::Config.app_instances(app_name).times do |instance|
15
+ f << " upstream #{app_name}_#{instance_name} {\n"
16
+ app_config[:mongrels].times do |instance|
16
17
  f << " server 127.0.0.1:#{first_port + instance};\n"
17
18
  end
18
19
  f << " }\n\n"
@@ -21,9 +22,9 @@ class RailsPwnage::App::NginxConfig
21
22
  f << <<NGINX_CONFIG
22
23
  server {
23
24
  listen 80;
24
- #{(hostname_filter.nil? ? '' : "server_name " + hostname_filter + ";")}
25
- root #{RailsPwnage::Config.path_to(app_name)};
26
- client_max_body_size #{RailsPwnage::Config.app_max_request_mb(app_name)}M;
25
+ #{(hostname_filter.empty? ? '' : "server_name " + hostname_filter + ";")}
26
+ root #{app_config[:app_path]};
27
+ client_max_body_size #{app_config[:max_request_mb]}M;
27
28
  location / {
28
29
  proxy_set_header X-Real-IP $remote_addr;
29
30
  proxy_set_header Host $host;
@@ -38,7 +39,7 @@ class RailsPwnage::App::NginxConfig
38
39
  rewrite (.*) $1.html break;
39
40
  }
40
41
  if (!-f $request_filename) {
41
- proxy_pass http://#{app_name};
42
+ proxy_pass http://#{app_name}_#{instance_name};
42
43
  break;
43
44
  }
44
45
  }
@@ -47,8 +48,8 @@ NGINX_CONFIG
47
48
  end
48
49
  end
49
50
 
50
- def remove_nginx_config(app_name)
51
- nginx_config = File.join(RailsPwnage::Config.path_to(:nginx_configs), app_name)
51
+ def remove_nginx_config(app_name, instance_name)
52
+ nginx_config = File.join(RailsPwnage::Config.path_to(:nginx_configs), app_name + '.' + instance_name)
52
53
  File.delete nginx_config if File.exists? nginx_config
53
54
  end
54
55
 
@@ -58,13 +59,13 @@ NGINX_CONFIG
58
59
  File.delete stub_file if File.exists?(stub_file)
59
60
  end
60
61
 
61
- def setup(app_name)
62
- config_nginx app_name
62
+ def setup(app_name, instance_name)
63
+ config_nginx app_name, instance_name
63
64
  remove_nginx_stub
64
65
  end
65
66
 
66
- def remove(app_name)
67
- remove_nginx_config app_name
67
+ def remove(app_name, instance_name)
68
+ remove_nginx_config app_name, instance_name
68
69
  end
69
70
 
70
71
  def control_all(action)
@@ -78,19 +79,7 @@ NGINX_CONFIG
78
79
  end
79
80
  end
80
81
 
81
- def self.setup(app_name)
82
- self.new.setup(app_name)
83
- end
84
-
85
- def self.update(app_name)
82
+ def update(app_name, instance_name)
86
83
  # nothing to do here, unless we enable config rewriting
87
84
  end
88
-
89
- def self.remove(app_name)
90
- self.new.remove(app_name)
91
- end
92
-
93
- def self.control_all(action = :start)
94
- self.new.control_all(action)
95
- end
96
85
  end
@@ -1,39 +1,22 @@
1
1
  # checks out the application
2
2
 
3
3
  require 'fileutils'
4
+ require 'pathname'
4
5
  require 'rexml/document'
5
6
 
6
7
  class RailsPwnage::App::Svn
7
8
  include RailsPwnage::Base
8
-
9
- def svn_checkout(svn_path)
10
- app_name = File.basename(svn_path)
11
-
12
- prod_apps = RailsPwnage::Config.path_to :apps
13
- Dir.chdir(prod_apps) do
14
- # checkout application
15
- system "svn co #{svn_path} #{app_name}"
16
- end
17
9
 
18
- return app_name
19
- end
20
-
21
- def svn_update(app_name)
22
- Dir.chdir(RailsPwnage::Config.path_to(app_name)) do
23
- system "svn update"
24
- end
25
- end
26
-
27
- def scaffold_backup(app_name)
28
- pwnerer_user = RailsPwnage::Config.pwnerer_user
10
+ def scaffold_backup(app_name, instance_name)
11
+ pwnerer_user = RailsPwnage::Config[app_name, instance_name][:pwnerer_user]
29
12
  pwnerer_uid = uid_for_username(pwnerer_user)
30
13
  pwnerer_gid = gid_for_username(pwnerer_user)
31
14
 
32
- backup_dir = RailsPwnage::Config.path_to :backup, app_name
33
- FileUtils.mkpath backup_dir unless File.exists? backup_dir
34
- File.chown(pwnerer_uid, pwnerer_gid, backup_dir)
15
+ backup_path = RailsPwnage::Config[app_name, instance_name][:backup_path]
16
+ FileUtils.mkpath backup_path unless File.exists? backup_path
17
+ File.chown(pwnerer_uid, pwnerer_gid, backup_path)
35
18
 
36
- Dir.chdir(RailsPwnage::Config.path_to(:backup, app_name)) do
19
+ Dir.chdir(backup_path) do
37
20
  ['db', 'files', 'tmp'].each do |subdir|
38
21
  Dir.mkdir subdir unless File.exists? subdir
39
22
  File.chown pwnerer_uid, pwnerer_gid, subdir
@@ -42,26 +25,28 @@ class RailsPwnage::App::Svn
42
25
  end
43
26
 
44
27
  # dump the application files to the backup area
45
- def dump_files(app_name)
46
- pwnerer_user = RailsPwnage::Config.pwnerer_user
28
+ def dump_files(app_name, instance_name)
29
+ pwnerer_user = RailsPwnage::Config[app_name, instance_name][:pwnerer_user]
47
30
  pwnerer_uid = uid_for_username(pwnerer_user)
48
31
  pwnerer_gid = gid_for_username(pwnerer_user)
49
32
 
50
33
  timestamp = Time.now.strftime '%Y%m%d%H%M%S'
51
- dump_file = "files/#{app_name}_#{timestamp}.tar.gz"
34
+ dump_file = "files/#{app_name}.#{instance_name}_#{timestamp}.tar.gz"
52
35
 
53
- Dir.chdir(RailsPwnage::Config.path_to(:backup, app_name)) do
36
+ backup_path = RailsPwnage::Config[app_name, instance_name][:backup_path]
37
+ app_path = RailsPwnage::Config[app_name, instance_name][:app_path]
38
+ Dir.chdir backup_path do
54
39
  # create a cold copy of the application files
55
- cold_copy = "tmp#{File::SEPARATOR}#{app_name}"
40
+ cold_copy = File.join('tmp', File.basename(app_path))
56
41
  FileUtils.rm_r cold_copy if File.exists? cold_copy
57
- FileUtils.cp_r RailsPwnage::Config.path_to(app_name), 'tmp'
42
+ FileUtils.cp_r app_path, 'tmp'
58
43
 
59
44
  # remove the garbage in the cold copy
60
- cleanup_app_caches File.join('tmp', app_name), true
45
+ cleanup_app_caches cold_copy, instance_name, true
61
46
 
62
47
  # pack and protect the cold copy
63
48
  Dir.chdir 'tmp' do
64
- system "tar -czf ../#{dump_file} #{app_name}"
49
+ system "tar -czf ../#{dump_file} #{File.basename(app_path)}"
65
50
  end
66
51
  File.chmod(400, dump_file)
67
52
  File.chown(pwnerer_uid, pwnerer_gid, dump_file)
@@ -72,22 +57,31 @@ class RailsPwnage::App::Svn
72
57
  end
73
58
 
74
59
  # loads the latest file dump from the backup area
75
- def load_files(app_name)
76
- dump_file = Dir.glob(RailsPwnage::Config.path_to(:backup, app_name) + File::SEPARATOR + "files/#{app_name}_*").max
77
- Dir.chdir(RailsPwnage::Config.path_to(:apps)) do
78
- # find the latest dump and load it in
60
+ def load_files(app_name, instance_name)
61
+ backup_path = RailsPwnage::Config[app_name, instance_name][:backup_path]
62
+ app_path = RailsPwnage::Config[app_name, instance_name][:app_path]
63
+
64
+ dump_file = Dir.glob(File.join(backup_path, "files/#{app_name}.#{instance_name}_*")).max
65
+ restore_path = Pathname.new(File.join(app_path, '..')).cleanpath.to_s
66
+ Dir.chdir restore_path do
67
+ # find the latest dump and load it in
79
68
  system "tar -xzf #{dump_file}"
80
- end
69
+ end
81
70
  end
82
-
71
+
83
72
  # remove the application files
84
- def drop_files(app_name)
85
- FileUtils.rm_r RailsPwnage::Config.path_to(app_name) if File.exists? RailsPwnage::Config.path_to(app_name)
73
+ def drop_files(app_name, instance_name)
74
+ app_config = RailsPwnage::Config[app_name, instance_name]
75
+ # exit and don't complain if the app is busted
76
+ return unless app_config and File.exists? app_config[:app_path]
77
+
78
+ app_path = app_config[:app_path]
79
+ FileUtils.rm_r app_path if File.exists? app_path
86
80
  end
87
81
 
88
82
  # remove any files not in SVN in the application dir
89
- def cleanup_app_dir(app_name, target_dir, app_name_is_dir = false)
90
- Dir.chdir(app_name_is_dir ? app_name : RailsPwnage::Config.path_to(app_name)) do
83
+ def cleanup_app_dir(app_name, instance_name, target_dir, app_name_is_dir = false)
84
+ Dir.chdir(app_name_is_dir ? app_name : RailsPwnage::Config[app_name, instance_name][:app_path]) do
91
85
  # get a listing of what happened in that directory
92
86
  xml_status = `svn status --xml #{target_dir}`
93
87
  xsdoc = REXML::Document.new xml_status
@@ -102,70 +96,57 @@ class RailsPwnage::App::Svn
102
96
  end
103
97
 
104
98
  # clean up the application directory by removing caches
105
- def cleanup_app_caches(app_name, app_name_is_dir = false)
99
+ def cleanup_app_caches(app_name, instance_name, app_name_is_dir = false)
106
100
  # TODO: learn how Rails caches work and kill those too
107
101
  ['app', 'lib', 'public/images',
108
102
  'public/javascripts', 'public/stylesheets', 'script',
109
103
  'test', 'tmp', 'vendor'
110
- ].each { |dir| cleanup_app_dir app_name, dir, app_name_is_dir }
104
+ ].each { |dir| cleanup_app_dir app_name, instance_name, dir, app_name_is_dir }
111
105
  end
112
106
 
113
- def manage(app_name, action)
107
+ def manage(app_name, instance_name, action)
114
108
  case action
115
109
  when :checkpoint
116
- dump_files app_name
110
+ dump_files app_name, instance_name
117
111
  when :rollback
118
- drop_files app_name
119
- load_files app_name
112
+ drop_files app_name, instance_name
113
+ load_files app_name, instance_name
120
114
  when :console
121
- Dir.chdir(RailsPwnage::Config.path_to(app_name)) do
115
+ Dir.chdir(RailsPwnage::Config[app_name, instance_name][:app_path]) do
122
116
  Kernel.system 'ruby script/console production'
123
117
  end
124
118
  when :db_console
125
- Dir.chdir(RailsPwnage::Config.path_to(app_name)) do
119
+ Dir.chdir(RailsPwnage::Config[app_name, instance_name][:app_path]) do
126
120
  Kernel.system 'ruby script/dbconsole --include-password production'
127
121
  end
128
122
  end
129
123
  end
130
-
131
- def setup(svn_path)
132
- app_name = svn_checkout(svn_path)
133
-
134
- # TODO: fetch configuration, feed to system
135
-
136
- scaffold_backup(app_name)
137
-
138
- return app_name
139
- end
140
-
141
- def update(app_name)
142
- scaffold_backup(app_name)
143
124
 
144
- # TODO: maybe backup old version before issuing the svn update?
145
-
146
- cleanup_app_caches(app_name)
147
- svn_update(app_name)
148
- end
149
-
150
- def remove(app_name)
151
- drop_files(app_name)
152
- end
153
-
154
- def self.setup(svn_path)
155
- self.new.setup(svn_path)
125
+ def svn_update(app_name, instance_name)
126
+ Dir.chdir RailsPwnage::Config[app_name, instance_name][:app_path] do
127
+ system "svn update"
128
+ end
156
129
  end
157
130
 
158
- def self.update(app_name)
159
- self.new.update(app_name)
131
+ def checkout(svn_path, app_name, instance_name)
132
+ app_path = RailsPwnage::Config[app_name, instance_name][:app_path]
133
+ system "svn co #{svn_path} #{app_path}"
160
134
  end
161
-
162
- def self.remove(app_name)
163
- self.new.remove(app_name)
135
+
136
+ def setup(app_name, instance_name)
137
+ scaffold_backup(app_name, instance_name)
164
138
  end
165
139
 
166
- def self.manage(app_name, action)
167
- self.new.manage(app_name, action)
140
+ def update(app_name, instance_name)
141
+ scaffold_backup(app_name, instance_name)
142
+
143
+ # TODO: maybe backup old version before issuing the svn update?
144
+
145
+ cleanup_app_caches(app_name, instance_name)
146
+ svn_update(app_name, instance_name)
168
147
  end
169
148
 
170
- # TODO: uninstallation
149
+ def remove(app_name, instance_name)
150
+ drop_files(app_name, instance_name)
151
+ end
171
152
  end
@@ -1,44 +1,3 @@
1
1
  module RailsPwnage::Config
2
- # the user which will receive the keys to the production system
3
- def self.pwnerer_user
4
- 'victor'
5
- end
6
-
7
- # the number of instances for the given application
8
- def self.app_instances(app_name)
9
- 4
10
- end
11
-
12
- # the first internal port for the given application
13
- def self.app_port0(app_name)
14
- 8000
15
- end
16
-
17
- # the name of the database for the given application
18
- def self.app_dbname(app_name)
19
- # NOTE: convention, this doesn't have to change
20
- app_name + '_prod'
21
- end
22
-
23
- # the datbase user for the given application
24
- def self.app_db_user(app_name)
25
- # NOTE: convention, this doesn't have to change
26
- app_name
27
- end
28
-
29
- # the password of the database user for the given application
30
- def self.app_db_password(app_name)
31
- 'superpass'
32
- end
33
-
34
- # a DNS name for server-based filtering (multiple apps on the same box)
35
- def self.app_servername(app_name)
36
- # "#{app_name}.zergling.net"
37
- nil
38
- end
39
-
40
- # the maximum request size (megabytes) to be accepted by an application
41
- def self.app_max_request_mb(app_name)
42
- 48
43
- end
2
+
44
3
  end
@@ -40,15 +40,18 @@ class RailsPwnage::Executor
40
40
 
41
41
  when 'install', 'micro'
42
42
  svn_path = args[1]
43
- RailsPwnage::App.install svn_path
43
+ instance_name = args[2] || '.'
44
+ RailsPwnage::App.install svn_path, instance_name
44
45
 
45
46
  when 'update', 'ubermicro'
46
47
  app_name = args[1]
47
- RailsPwnage::App.update app_name
48
+ instance_name = args[2] || '.'
49
+ RailsPwnage::App.update app_name, instance_name
48
50
 
49
51
  when 'uninstall', 'remove'
50
52
  app_name = args[1]
51
- RailsPwnage::App.remove app_name
53
+ instance_name = args[2] || '.'
54
+ RailsPwnage::App.remove app_name, instance_name
52
55
 
53
56
  when 'go'
54
57
  case args[1]
@@ -61,19 +64,27 @@ class RailsPwnage::Executor
61
64
  end
62
65
 
63
66
  when 'backup', 'checkpoint', 'save'
64
- RailsPwnage::App.manage args[1], :checkpoint
67
+ app_name = args[1]
68
+ instance_name = args[2] || '.'
69
+ RailsPwnage::App.manage app_name, instance_name, :checkpoint
65
70
  when 'restore', 'reload', 'recover', 'rollback'
66
- RailsPwnage::App.manage args[1], :rollback
71
+ app_name = args[1]
72
+ instance_name = args[2] || '.'
73
+ RailsPwnage::App.manage app_name, instance_name, :rollback
67
74
  when 'console'
68
- RailsPwnage::App.manage args[1], :console
69
- when 'db_console'
70
- RailsPwnage::App.manage args[1], :db_console
75
+ app_name = args[1]
76
+ instance_name = args[2] || '.'
77
+ RailsPwnage::App.manage app_name, instance_name, :console
78
+ when 'dbconsole', 'db_console'
79
+ app_name = args[1]
80
+ instance_name = args[2] || '.'
81
+ RailsPwnage::App.manage app_name, instance_name, :db_console
71
82
 
72
- when 'config_show'
83
+ when 'showconfig', 'configshow', 'show_config', 'config_show'
73
84
  if args.length < 2
74
85
  # dump all databases
75
86
  RailsPwnage::Config.databases.each do |db|
76
- print "Database: #{db}"
87
+ print "Database: #{db}\n"
77
88
  pp RailsPwnage::Config[db]
78
89
  end
79
90
  else
data/lib/rails_pwnage.rb CHANGED
@@ -1,9 +1,16 @@
1
1
  module RailsPwnage
2
2
  end
3
3
 
4
+ module RailsPwnage::App
5
+ end
6
+
7
+ module RailsPwnage::Config
8
+ end
9
+
4
10
  module RailsPwnage::Scaffolds
5
11
  end
6
12
 
13
+
7
14
  require 'pwnage/base.rb'
8
15
  require 'pwnage/base/atomics.rb'
9
16
  require 'pwnage/base/dirs.rb'
@@ -12,6 +19,7 @@ require 'pwnage/base/hostname.rb'
12
19
  require 'pwnage/base/packages.rb'
13
20
  require 'pwnage/base/startup.rb'
14
21
 
22
+ require 'pwnage/config/app.rb'
15
23
  require 'pwnage/config/main.rb'
16
24
  require 'pwnage/config/paths.rb'
17
25
  require 'pwnage/config/ports.rb'
@@ -29,8 +37,9 @@ require 'pwnage/scaffolds/packages.rb'
29
37
  require 'pwnage/scaffolds/rubygems.rb'
30
38
 
31
39
  require 'pwnage/app/main.rb'
32
- require 'pwnage/app/svn.rb'
33
- require 'pwnage/app/gems.rb'
34
- require 'pwnage/app/database.rb'
40
+ require 'pwnage/app/config.rb'
35
41
  require 'pwnage/app/cluster_config.rb'
42
+ require 'pwnage/app/database.rb'
43
+ require 'pwnage/app/gems.rb'
36
44
  require 'pwnage/app/nginx_config.rb'
45
+ require 'pwnage/app/svn.rb'
@@ -1,18 +1,18 @@
1
1
 
2
- # Gem::Specification for Rails_pwnerer-0.5.0
2
+ # Gem::Specification for Rails_pwnerer-0.5.1
3
3
  # Originally generated by Echoe
4
4
 
5
5
  --- !ruby/object:Gem::Specification
6
6
  name: rails_pwnerer
7
7
  version: !ruby/object:Gem::Version
8
- version: 0.5.0
8
+ version: 0.5.1
9
9
  platform: ruby
10
10
  authors:
11
11
  - Victor Costan
12
12
  autorequire:
13
13
  bindir: bin
14
14
 
15
- date: 2008-08-15 00:00:00 -04:00
15
+ date: 2008-08-16 00:00:00 -04:00
16
16
  default_executable:
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_pwnerer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Costan
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-08-15 00:00:00 -04:00
12
+ date: 2008-08-16 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency