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 +2 -0
- data/lib/pwnage/app/cluster_config.rb +53 -51
- data/lib/pwnage/app/database.rb +49 -67
- data/lib/pwnage/app/gems.rb +5 -15
- data/lib/pwnage/app/main.rb +65 -44
- data/lib/pwnage/app/nginx_config.rb +18 -29
- data/lib/pwnage/app/svn.rb +64 -83
- data/lib/pwnage/config/main.rb +1 -42
- data/lib/pwnage/executor.rb +21 -10
- data/lib/rails_pwnage.rb +12 -3
- data/rails_pwnerer.gemspec +3 -3
- metadata +2 -2
data/CHANGELOG
CHANGED
@@ -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
|
-
|
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
|
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
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
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 #{
|
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?
|
63
|
+
return unless app_config and File.exists? app_config[:app_path]
|
47
64
|
|
48
|
-
Dir.chdir
|
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?
|
76
|
+
return unless app_config and File.exists? app_config[:app_path]
|
59
77
|
|
60
|
-
Dir.chdir
|
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
|
-
|
67
|
-
|
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
|
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
|
-
|
75
|
-
|
76
|
-
|
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
|
data/lib/pwnage/app/database.rb
CHANGED
@@ -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
|
-
|
11
|
-
|
12
|
-
|
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
|
-
|
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('
|
30
|
-
|
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('
|
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
|
-
|
40
|
-
db_user =
|
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 =
|
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 =
|
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
|
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
|
-
|
65
|
-
db_user =
|
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 =
|
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
|
75
|
-
system
|
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
|
-
|
85
|
-
db_user =
|
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
|
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
|
data/lib/pwnage/app/gems.rb
CHANGED
@@ -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
|
-
|
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
|
21
|
-
|
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
|
data/lib/pwnage/app/main.rb
CHANGED
@@ -1,51 +1,72 @@
|
|
1
1
|
module RailsPwnage::App
|
2
|
-
#
|
3
|
-
def self.
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
9
|
-
|
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
|
-
|
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.
|
25
|
-
root #{
|
26
|
-
client_max_body_size #{
|
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
|
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
|
data/lib/pwnage/app/svn.rb
CHANGED
@@ -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
|
-
|
19
|
-
|
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
|
-
|
33
|
-
FileUtils.mkpath
|
34
|
-
File.chown(pwnerer_uid, pwnerer_gid,
|
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(
|
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
|
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
|
-
|
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 =
|
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
|
42
|
+
FileUtils.cp_r app_path, 'tmp'
|
58
43
|
|
59
44
|
# remove the garbage in the cold copy
|
60
|
-
cleanup_app_caches
|
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} #{
|
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
|
-
|
77
|
-
|
78
|
-
|
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
|
-
|
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
|
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
|
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
|
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
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
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
|
159
|
-
|
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
|
163
|
-
|
135
|
+
|
136
|
+
def setup(app_name, instance_name)
|
137
|
+
scaffold_backup(app_name, instance_name)
|
164
138
|
end
|
165
139
|
|
166
|
-
def
|
167
|
-
|
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
|
-
|
149
|
+
def remove(app_name, instance_name)
|
150
|
+
drop_files(app_name, instance_name)
|
151
|
+
end
|
171
152
|
end
|
data/lib/pwnage/config/main.rb
CHANGED
@@ -1,44 +1,3 @@
|
|
1
1
|
module RailsPwnage::Config
|
2
|
-
|
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
|
data/lib/pwnage/executor.rb
CHANGED
@@ -40,15 +40,18 @@ class RailsPwnage::Executor
|
|
40
40
|
|
41
41
|
when 'install', 'micro'
|
42
42
|
svn_path = args[1]
|
43
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
71
|
+
app_name = args[1]
|
72
|
+
instance_name = args[2] || '.'
|
73
|
+
RailsPwnage::App.manage app_name, instance_name, :rollback
|
67
74
|
when 'console'
|
68
|
-
|
69
|
-
|
70
|
-
RailsPwnage::App.manage
|
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/
|
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'
|
data/rails_pwnerer.gemspec
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
|
2
|
-
# Gem::Specification for Rails_pwnerer-0.5.
|
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.
|
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
|
+
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.
|
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-
|
12
|
+
date: 2008-08-16 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|