rails_pwnerer 0.4 → 0.4.5
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/README +17 -3
- data/lib/pwnage/app/cluster_config.rb +22 -1
- data/lib/pwnage/app/database.rb +54 -24
- data/lib/pwnage/app/main.rb +3 -1
- data/lib/pwnage/app/svn.rb +49 -19
- data/rails_pwnerer.gemspec +2 -2
- metadata +1 -1
data/CHANGELOG
CHANGED
data/README
CHANGED
@@ -9,13 +9,18 @@ welcome to test/update for other systems, and I'll be happy to merge patches,
|
|
9
9
|
or add you to the RubyForge project.
|
10
10
|
|
11
11
|
|
12
|
-
|
12
|
+
Life without +rails_pwnerer+:
|
13
13
|
|
14
14
|
Read a 20-page guide, and spend the better half of a day getting a box
|
15
15
|
ready for production. You'll be frustrated in the process, but feel
|
16
16
|
accomplished at the end. Assuming you don't do something wrong.
|
17
17
|
|
18
|
-
|
18
|
+
Read a couple more 20-page guides, and learn to push newer versions
|
19
|
+
of your application. You'll become lazy, and take shortcuts, like having
|
20
|
+
production passwords in the repository, insecure file permissions.
|
21
|
+
I won't even mention backups.
|
22
|
+
|
23
|
+
Life with +rails_pwnerer+:
|
19
24
|
|
20
25
|
1) Install rubygems:
|
21
26
|
sudo apt-get install rubygems
|
@@ -32,5 +37,14 @@ sudo rpwn install svn+ssh://your.repository.host/path/to/your_application
|
|
32
37
|
5) Reboot, or start the services right away:
|
33
38
|
sudo rpwn go live
|
34
39
|
|
35
|
-
|
40
|
+
* Keep your application updated:
|
36
41
|
sudo rpwn update your_application
|
42
|
+
|
43
|
+
* Create a backup:
|
44
|
+
sudo rpwn backup your_application
|
45
|
+
|
46
|
+
* Restore from the latest backup:
|
47
|
+
sudo rpwn restore your_application
|
48
|
+
|
49
|
+
* Bring down all the applications (panic mode):
|
50
|
+
sudo rpwn go down
|
@@ -35,6 +35,9 @@ class RailsPwnage::App::ClusterConfig
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def stop_mongrels(app_name)
|
38
|
+
# silently die if the app was completely busted
|
39
|
+
return unless File.exists? RailsPwnage::Config.path_to(app_name)
|
40
|
+
|
38
41
|
with_dir(RailsPwnage::Config.path_to(app_name)) do
|
39
42
|
system 'mongrel_rails cluster::stop'
|
40
43
|
|
@@ -44,6 +47,9 @@ class RailsPwnage::App::ClusterConfig
|
|
44
47
|
end
|
45
48
|
|
46
49
|
def start_mongrels(app_name)
|
50
|
+
# silently die if the app was completely busted
|
51
|
+
return unless File.exists? RailsPwnage::Config.path_to(app_name)
|
52
|
+
|
47
53
|
with_dir(RailsPwnage::Config.path_to(app_name)) do
|
48
54
|
system 'mongrel_rails cluster::start'
|
49
55
|
end
|
@@ -58,10 +64,21 @@ class RailsPwnage::App::ClusterConfig
|
|
58
64
|
stop_mongrels(app_name)
|
59
65
|
yield
|
60
66
|
ensure
|
61
|
-
|
67
|
+
configure_mongrels app_name
|
68
|
+
fix_permissions app_name
|
62
69
|
start_mongrels(app_name)
|
63
70
|
end
|
64
71
|
|
72
|
+
def backup(app_name, action)
|
73
|
+
case action
|
74
|
+
when :checkpoint
|
75
|
+
# nothing to do here
|
76
|
+
when :rollback
|
77
|
+
configure_mongrels app_name
|
78
|
+
fix_permissions app_name
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
65
82
|
def control_all(action)
|
66
83
|
case action
|
67
84
|
when :start
|
@@ -79,6 +96,10 @@ class RailsPwnage::App::ClusterConfig
|
|
79
96
|
self.new.update(app_name, &update_proc)
|
80
97
|
end
|
81
98
|
|
99
|
+
def self.backup(app_name, action)
|
100
|
+
self.new.backup(app_name, action)
|
101
|
+
end
|
102
|
+
|
82
103
|
def self.control_all(action = :start)
|
83
104
|
self.new.control_all(action)
|
84
105
|
end
|
data/lib/pwnage/app/database.rb
CHANGED
@@ -5,25 +5,32 @@ require 'yaml'
|
|
5
5
|
class RailsPwnage::App::Database
|
6
6
|
include RailsPwnage::Base
|
7
7
|
|
8
|
-
# creates the mysql database for the application
|
9
|
-
def
|
8
|
+
# creates/drops the mysql database for the application
|
9
|
+
def admin_database(app_name, action = :create)
|
10
10
|
db_name = RailsPwnage::Config.app_dbname(app_name)
|
11
11
|
db_user = RailsPwnage::Config.app_db_user(app_name)
|
12
12
|
db_pass = RailsPwnage::Config.app_db_password(app_name)
|
13
13
|
|
14
14
|
with_dir(RailsPwnage::Config.path_to(app_name)) do
|
15
|
-
# put together the
|
15
|
+
# put together the admin script
|
16
|
+
case action
|
17
|
+
when :create
|
16
18
|
sql_commands = <<ENDSQL
|
17
19
|
CREATE DATABASE #{db_name};
|
18
20
|
GRANT ALL ON #{db_name}.* TO '#{db_user}'@'localhost' IDENTIFIED BY '#{db_pass}' WITH GRANT OPTION;
|
19
21
|
ENDSQL
|
22
|
+
when :drop
|
23
|
+
sql_commands = <<ENDSQL
|
24
|
+
DROP DATABASE #{db_name};
|
25
|
+
ENDSQL
|
26
|
+
end
|
20
27
|
|
21
28
|
# run it
|
22
|
-
File.open('tmp/
|
23
|
-
system "mysql -uroot < tmp/
|
29
|
+
File.open('tmp/admin_db.sql', 'w') { |f| f.write sql_commands }
|
30
|
+
system "mysql -uroot < tmp/admin_db.sql"
|
24
31
|
|
25
32
|
# cleanup
|
26
|
-
File.delete('tmp/
|
33
|
+
File.delete('tmp/admin_db.sql')
|
27
34
|
end
|
28
35
|
end
|
29
36
|
|
@@ -44,16 +51,49 @@ ENDSQL
|
|
44
51
|
File.chown(uid_for_username(pwnerer_user), gid_for_username(pwnerer_user), config_file)
|
45
52
|
end
|
46
53
|
|
47
|
-
# migrates the database
|
54
|
+
# migrates the database to the latest schema version
|
48
55
|
def migrate_database(app_name)
|
49
56
|
with_dir(RailsPwnage::Config.path_to(app_name)) do
|
50
57
|
# now migrate the database
|
51
58
|
system "rake db:migrate RAILS_ENV=production"
|
52
59
|
end
|
53
60
|
end
|
61
|
+
|
62
|
+
# 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
|
+
|
68
|
+
pwnerer_user = RailsPwnage::Config.pwnerer_user
|
69
|
+
pwnerer_uid = uid_for_username(pwnerer_user)
|
70
|
+
pwnerer_gid = gid_for_username(pwnerer_user)
|
71
|
+
|
72
|
+
timestamp = Time.now.strftime '%Y%m%d%H%M%S'
|
73
|
+
dump_file = "db/#{app_name}_#{timestamp}.sql"
|
74
|
+
with_dir(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
|
+
# lockdown the file
|
77
|
+
File.chmod(0400, dump_file)
|
78
|
+
File.chown(pwnerer_uid, pwnerer_gid, dump_file)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# 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
|
+
|
88
|
+
with_dir(RailsPwnage::Config.path_to(:backup, app_name)) do
|
89
|
+
# find the latest dump and load it in
|
90
|
+
dump_file = Dir.glob("db/#{app_name}_*").max
|
91
|
+
system "mysql -u#{db_user} -p#{db_pass} #{db_name} < #{dump_file}"
|
92
|
+
end
|
93
|
+
end
|
54
94
|
|
55
95
|
def setup(app_name)
|
56
|
-
|
96
|
+
admin_database app_name, :create
|
57
97
|
configure_rails app_name
|
58
98
|
migrate_database app_name
|
59
99
|
end
|
@@ -65,26 +105,16 @@ ENDSQL
|
|
65
105
|
|
66
106
|
# backs up or restores the database
|
67
107
|
def backup(app_name, action)
|
68
|
-
db_name = RailsPwnage::Config.app_dbname(app_name)
|
69
|
-
db_user = RailsPwnage::Config.app_db_user(app_name)
|
70
|
-
db_pass = RailsPwnage::Config.app_db_password(app_name)
|
71
|
-
|
72
|
-
pwnerer_user = RailsPwnage::Config.pwnerer_user
|
73
|
-
pwnerer_uid = uid_for_username(pwnerer_user)
|
74
|
-
pwnerer_gid = gid_for_username(pwnerer_user)
|
75
108
|
|
76
109
|
case action
|
77
110
|
when :checkpoint
|
78
|
-
|
79
|
-
dump_file = "db/#{app_name}_#{timestamp}.sql"
|
80
|
-
with_dir(RailsPwnage::Config.path_to(:backup, app_name)) do
|
81
|
-
system "mysqldump --add-drop-database --add-drop-table --extended-insert --single-transaction -u#{db_user} -p#{db_pass} #{db_name} > #{dump_file}"
|
82
|
-
# lockdown the file
|
83
|
-
File.chmod(0400, dump_file)
|
84
|
-
File.chown(pwnerer_uid, pwnerer_gid, dump_file)
|
85
|
-
end
|
111
|
+
dump_database app_name
|
86
112
|
when :rollback
|
87
|
-
|
113
|
+
admin_database app_name, :drop
|
114
|
+
admin_database app_name, :create
|
115
|
+
load_database app_name
|
116
|
+
configure_rails app_name
|
117
|
+
migrate_database app_name
|
88
118
|
end
|
89
119
|
end
|
90
120
|
|
data/lib/pwnage/app/main.rb
CHANGED
@@ -20,14 +20,16 @@ module RailsPwnage::App
|
|
20
20
|
def self.backup(app_name, action = :checkpoint)
|
21
21
|
case action
|
22
22
|
when :checkpoint
|
23
|
+
ClusterConfig.backup app_name, action
|
23
24
|
Svn.backup app_name, action
|
24
|
-
ClusterConfig.update(app_name) do
|
25
|
+
ClusterConfig.update(app_name) do
|
25
26
|
Database.backup app_name, action
|
26
27
|
end
|
27
28
|
when :rollback
|
28
29
|
ClusterConfig.update(app_name) do
|
29
30
|
Svn.backup app_name, action
|
30
31
|
Database.backup app_name, action
|
32
|
+
ClusterConfig.backup app_name, action
|
31
33
|
end
|
32
34
|
end
|
33
35
|
end
|
data/lib/pwnage/app/svn.rb
CHANGED
@@ -40,33 +40,63 @@ class RailsPwnage::App::Svn
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
-
|
43
|
+
# dump the application files to the backup area
|
44
|
+
def dump_files(app_name)
|
44
45
|
pwnerer_user = RailsPwnage::Config.pwnerer_user
|
45
46
|
pwnerer_uid = uid_for_username(pwnerer_user)
|
46
47
|
pwnerer_gid = gid_for_username(pwnerer_user)
|
47
48
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
49
|
+
timestamp = Time.now.strftime '%Y%m%d%H%M%S'
|
50
|
+
dump_file = "files/#{app_name}_#{timestamp}.tar.gz"
|
51
|
+
|
52
|
+
with_dir(RailsPwnage::Config.path_to(:backup, app_name)) do
|
53
|
+
# create a cold copy of the application files
|
54
|
+
cold_copy = "tmp#{File::SEPARATOR}#{app_name}"
|
55
|
+
FileUtils.rm_r cold_copy if File.exists? cold_copy
|
56
|
+
FileUtils.cp_r RailsPwnage::Config.path_to(app_name), 'tmp'
|
52
57
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
# pack and protect the cold copy
|
60
|
-
with_dir 'tmp' do
|
61
|
-
system "tar -czf ../#{dump_file} #{app_name}"
|
58
|
+
# remove the temp garbage in the cold copy
|
59
|
+
fs = File::SEPARATOR
|
60
|
+
["cache#{fs}*", "pids#{fs}*.pid", "sessions#{fs}*"].each do |pattern|
|
61
|
+
Dir.glob("tmp#{fs}#{app_name}#{pattern}") do |entry|
|
62
|
+
next if entry =~ /\.svn$/
|
63
|
+
FileUtils.rm_r entry
|
62
64
|
end
|
63
|
-
File.chmod(400, dump_file)
|
64
|
-
File.chown(pwnerer_uid, pwnerer_gid, dump_file)
|
65
|
-
|
66
|
-
# clean up
|
67
|
-
FileUtils.rm_r cold_copy
|
68
65
|
end
|
66
|
+
|
67
|
+
# pack and protect the cold copy
|
68
|
+
with_dir 'tmp' do
|
69
|
+
system "tar -czf ../#{dump_file} #{app_name}"
|
70
|
+
end
|
71
|
+
File.chmod(400, dump_file)
|
72
|
+
File.chown(pwnerer_uid, pwnerer_gid, dump_file)
|
73
|
+
|
74
|
+
# clean up
|
75
|
+
FileUtils.rm_r cold_copy
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# loads the latest file dump from the backup area
|
80
|
+
def load_files(app_name)
|
81
|
+
dump_file = Dir.glob(RailsPwnage::Config.path_to(:backup, app_name) + File::SEPARATOR + "files/#{app_name}_*").max
|
82
|
+
with_dir(RailsPwnage::Config.path_to(:prod_apps)) do
|
83
|
+
# find the latest dump and load it in
|
84
|
+
system "tar -xzf #{dump_file}"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# remove the application files
|
89
|
+
def drop_files(app_name)
|
90
|
+
FileUtils.rm_r RailsPwnage::Config.path_to(app_name) if File.exists? RailsPwnage::Config.path_to(app_name)
|
91
|
+
end
|
92
|
+
|
93
|
+
def backup(app_name, action)
|
94
|
+
case action
|
95
|
+
when :checkpoint
|
96
|
+
dump_files app_name
|
69
97
|
when :rollback
|
98
|
+
drop_files app_name
|
99
|
+
load_files app_name
|
70
100
|
end
|
71
101
|
end
|
72
102
|
|
data/rails_pwnerer.gemspec
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
|
2
|
-
# Gem::Specification for Rails_pwnerer-0.4
|
2
|
+
# Gem::Specification for Rails_pwnerer-0.4.5
|
3
3
|
# Originally generated by Echoe
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = %q{rails_pwnerer}
|
7
|
-
s.version = "0.4"
|
7
|
+
s.version = "0.4.5"
|
8
8
|
|
9
9
|
s.specification_version = 2 if s.respond_to? :specification_version=
|
10
10
|
|