rails_pwnerer 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
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