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 +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
|