rails_pwnerer 0.5.16 → 0.5.17

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.17. Ability to call custom scripts during an app's lifecycle.
2
+
1
3
  v0.5.16. Letter-based database passwords (ruby's mysql doesn't like numbers).
2
4
 
3
5
  v0.5.15. Home-baked process info (in case Sys::Proctable doesn't work).
data/Manifest CHANGED
@@ -8,6 +8,7 @@ lib/pwnage/app/database.rb
8
8
  lib/pwnage/app/gems.rb
9
9
  lib/pwnage/app/main.rb
10
10
  lib/pwnage/app/nginx_config.rb
11
+ lib/pwnage/app/scripts.rb
11
12
  lib/pwnage/app/svn.rb
12
13
  lib/pwnage/base/atomics.rb
13
14
  lib/pwnage/base/dirs.rb
@@ -36,6 +37,8 @@ lib/pwnage/scaffolds/mysql_config.rb
36
37
  lib/pwnage/scaffolds/packages.rb
37
38
  lib/pwnage/scaffolds/rubygems.rb
38
39
  lib/pwnage/scaffolds/sshd.rb
40
+ lib/pwnage/util/kill_process_set.rb
41
+ lib/pwnage/util/main.rb
39
42
  lib/rails_pwnerer.rb
40
43
  LICENSE
41
44
  Manifest
@@ -59,67 +59,28 @@ class RailsPwnage::App::ClusterConfig
59
59
  def remove_mongrels(app_name, instance_name)
60
60
  # bomb the configuration from the launch directory
61
61
  launch_config = File.join RailsPwnage::Config.path_to(:mongrel_configs), "#{app_name}.#{instance_name}.yml"
62
- File.delete launch_config if File.exists? launch_config
62
+ File.delete launch_config if File.exists? launch_config
63
63
  end
64
64
 
65
- def kill_stray_mongrels(app_name, instance_name)
66
- app_config = RailsPwnage::Config[app_name, instance_name]
67
- # silently die if the app was completely busted
68
- return unless app_config and File.exists? app_config[:app_path]
69
-
70
- # a list of patterns that show up in mongrels' cmdline
71
- patterns = ['mongrel', app_config[:app_path] + ' ', 'tmp/pids/mongrel', 'log/mongrel']
72
-
73
- Dir.chdir app_config[:app_path] do
74
- # Phase 1: look through PID files and issue kill orders
75
- pinfo = process_info()
76
- Dir.glob('tmp/pids/*.pid').each do |fname|
77
- begin
78
- pid = File.open(fname, 'r') { |f| f.read.strip! }
79
- # avoid killing innocent victims
80
- if pinfo[pid].nil? or patterns.all? { |pattern| pinfo[pid][:cmdline].index pattern }
81
- print "Killing #{pid}: #{pinfo[pid][:cmdline]}\n"
82
- Process.kill 'TERM', pid.to_i
83
- end
84
- rescue
85
- # just in case the file gets wiped before we see it
86
- end
87
- begin
88
- print "Deleting #{fname}\n"
89
- File.delete fname if File.exists? fname
90
- rescue
91
- # prevents crashing if the file is wiped after we call exists?
92
- end
93
- end
94
-
95
- # Phase 2: look through the process table and kill anything that looks good
96
- pinfo = process_info()
97
- pinfo.each do |pid, info|
98
- next unless patterns.all? { |pattern| info[:cmdline].index pattern }
99
- print "Killing #{pid}: #{pinfo[pid][:cmdline]}\n"
100
- Process.kill 'TERM', pid.to_i
101
- end
102
- end
103
- end
104
-
105
- def stop_mongrels(app_name, instance_name)
65
+ def stop(app_name, instance_name)
106
66
  app_config = RailsPwnage::Config[app_name, instance_name]
107
67
  # silently die if the app was completely busted
108
68
  return unless app_config and File.exists? app_config[:app_path]
69
+
70
+ cmdline_patterns = ['mongrel', app_config[:app_path] + ' ', 'tmp/pids/mongrel', 'log/mongrel']
109
71
 
110
72
  Dir.chdir app_config[:app_path] do
111
- Kernel.system 'mongrel_rails cluster::stop'
73
+ RailsPwnage::Util.kill_process_set('mongrel_rails cluster::stop',
74
+ 'tmp/pids/*.pid', cmdline_patterns, :verbose => false, :sleep_delay => 0.5)
112
75
  end
113
- sleep 0.5
114
- kill_stray_mongrels app_name, instance_name
115
76
  end
116
77
 
117
- def start_mongrels(app_name, instance_name)
78
+ def start(app_name, instance_name)
118
79
  app_config = RailsPwnage::Config[app_name, instance_name]
119
80
  # silently die if the app was completely busted
120
81
  return unless app_config and File.exists? app_config[:app_path]
121
82
 
122
- kill_stray_mongrels app_name, instance_name
83
+ stop app_name, instance_name
123
84
 
124
85
  # alloc a port if somehow that slipped through the cracks
125
86
  if app_config[:port0] == 0
@@ -140,20 +101,17 @@ class RailsPwnage::App::ClusterConfig
140
101
  # no need to configure nginx here, it'll be done by the executor
141
102
  end
142
103
 
143
- def update(app_name, instance_name, &update_proc)
144
- stop_mongrels app_name, instance_name
104
+ def pre_update(app_name, instance_name, &update_proc)
145
105
  manage_ports app_name, instance_name, :free
146
- yield
147
- ensure
106
+ end
107
+ def post_update(app_name, instance_name)
148
108
  manage_ports app_name, instance_name, :alloc
149
109
  configure_mongrels app_name, instance_name
150
110
  fix_permissions app_name, instance_name
151
- start_mongrels app_name, instance_name
152
- RailsPwnage::App::NginxConfig.new.update app_name, instance_name
153
111
  end
154
112
 
155
113
  def remove(app_name, instance_name)
156
- stop_mongrels app_name, instance_name
114
+ stop app_name, instance_name
157
115
  remove_mongrels app_name, instance_name
158
116
  manage_ports app_name, instance_name, :free
159
117
  end
@@ -172,9 +130,9 @@ class RailsPwnage::App::ClusterConfig
172
130
  RailsPwnage::Config.all_applications.each do |ai|
173
131
  case action
174
132
  when :start
175
- RailsPwnage::App::ClusterConfig.new.start_mongrels ai[0], ai[1]
133
+ RailsPwnage::App::ClusterConfig.new.start ai[0], ai[1]
176
134
  when :stop
177
- RailsPwnage::App::ClusterConfig.new.stop_mongrels ai[0], ai[1]
135
+ RailsPwnage::App::ClusterConfig.new.stop ai[0], ai[1]
178
136
  end
179
137
  end
180
138
  end
@@ -18,7 +18,7 @@ module RailsPwnage::App
18
18
  Config.new.alloc app, instance
19
19
  rails_root = Svn.new.checkout svn_path, app, instance
20
20
  if rails_root
21
- [Config, Svn, Gems, Database, ClusterConfig, NginxConfig].each do |mod|
21
+ [Config, Svn, Gems, Database, ClusterConfig, NginxConfig, Scripts].each do |mod|
22
22
  mod.new.setup app, instance
23
23
  end
24
24
  else
@@ -32,9 +32,9 @@ module RailsPwnage::App
32
32
  # updates an application (restart servers if necessary)
33
33
  def self.update(app_name, instance_name)
34
34
  instance_magic(app_name, instance_name) do |app, instance|
35
- ClusterConfig.new.update app, instance do
36
- [Svn, Config, Gems, Database].each do |mod|
37
- mod.new.update app, instance
35
+ update_app app, instance do
36
+ [Svn, Config, Gems, Database, Scripts].each do |mod|
37
+ mod.new.update app, instance
38
38
  end
39
39
  end
40
40
  NginxConfig.new.update app, instance
@@ -50,6 +50,20 @@ module RailsPwnage::App
50
50
  end
51
51
  end
52
52
 
53
+ def self.update_app(app_name, instance_name, &block)
54
+ Scripts.new.pre_stop app_name, instance_name
55
+ ClusterConfig.new.stop app_name, instance_name
56
+ ClusterConfig.new.pre_update app_name, instance_name
57
+ Scripts.new.post_stop app_name, instance_name
58
+ yield
59
+ ensure
60
+ ClusterConfig.new.post_update app_name, instance_name
61
+ NginxConfig.new.update app_name, instance_name
62
+ Scripts.new.pre_start app_name, instance_name
63
+ ClusterConfig.new.start app_name, instance_name
64
+ Scripts.new.post_start app_name, instance_name
65
+ end
66
+
53
67
  # performs application management (checkpoint / rollback / console)
54
68
  def self.manage(app_name, instance_name, action = :checkpoint)
55
69
  instance_magic(app_name, instance_name) do |app, instance|
@@ -58,11 +72,11 @@ module RailsPwnage::App
58
72
  when :checkpoint
59
73
  ClusterConfig.new.manage app, instance, action
60
74
  Svn.new.manage app, instance, action
61
- ClusterConfig.new.update app, instance do
75
+ self.update_app app, instance do
62
76
  Database.new.manage app, instance, action
63
77
  end
64
78
  when :rollback
65
- ClusterConfig.new.update app, instance do
79
+ self.update_app app, instance do
66
80
  [Svn, Database, ClusterConfig].each do |mod|
67
81
  mod.new.manage app, instance, action
68
82
  end
@@ -80,11 +94,15 @@ module RailsPwnage::App
80
94
  case action
81
95
  when :start
82
96
  Database.new.control_all :start
97
+ Scripts.new.control_all :pre_start
83
98
  ClusterConfig.new.control_all :start
84
99
  NginxConfig.new.control_all :start
100
+ Scripts.new.control_all :post_start
85
101
  when :stop
102
+ Scripts.new.control_all :pre_stop
86
103
  NginxConfig.new.control_all :stop
87
104
  ClusterConfig.new.control_all :stop
105
+ Scripts.new.control_all :post_stop
88
106
  Database.new.control_all :stop
89
107
  end
90
108
  end
@@ -0,0 +1,72 @@
1
+ # runs custom scripts on app events
2
+
3
+ class RailsPwnage::App::Scripts
4
+ include RailsPwnage::Base
5
+
6
+ def run_script(app_name, instance_name, script_name)
7
+ app_config = RailsPwnage::Config[app_name, instance_name]
8
+ pwnerer_user = app_config[:pwnerer_user]
9
+ pwnerer_uid = uid_for_username(pwnerer_user)
10
+ pwnerer_gid = gid_for_username(pwnerer_user)
11
+
12
+ return unless app_path = app_config[:app_path]
13
+
14
+ Dir.chdir app_path do
15
+ script_file = Dir.glob(File.join('script/rails_pwnerer', script_name + '*')).first
16
+ return if script_file.nil?
17
+ # make sure the script is executable
18
+ mode = File.stat(script_file).mode
19
+ File.chmod((mode | 0100) & 0777, script_file)
20
+ File.chown(pwnerer_uid, pwnerer_gid, script_file)
21
+
22
+ # run the script under the app's user
23
+ pid = Process.fork do
24
+ Process.uid = pwnerer_uid
25
+ Process.gid = pwnerer_gid
26
+ Process.egid = pwnerer_gid
27
+ Process.euid = pwnerer_uid
28
+ Dir.chdir app_path do
29
+ script_prefix = (script_file[0] == ?/) ? '' : './'
30
+ Kernel.system %Q|#{script_prefix}#{script_file} "#{app_name}" "#{instance_name}"|
31
+ end
32
+ end
33
+ Process.wait pid
34
+ end
35
+ end
36
+
37
+ def setup(app_name, instance_name)
38
+ run_script app_name, instance_name, 'setup'
39
+ end
40
+
41
+ def update(app_name, instance_name)
42
+ run_script app_name, instance_name, 'update'
43
+ end
44
+
45
+ def remove(app_name, instance_name)
46
+ run_script app_name, instance_name, 'remove'
47
+ end
48
+
49
+ def pre_start(app_name, instance_name)
50
+ run_script app_name, instance_name, 'pre_start'
51
+ end
52
+ def post_start(app_name, instance_name)
53
+ run_script app_name, instance_name, 'post_start'
54
+ end
55
+ def pre_stop(app_name, instance_name)
56
+ run_script app_name, instance_name, 'pre_stop'
57
+ end
58
+ def post_stop(app_name, instance_name)
59
+ run_script app_name, instance_name, 'post_stop'
60
+ end
61
+
62
+ def control_all(action)
63
+ RailsPwnage::Config.all_applications.each do |ai|
64
+ run_script ai[0], ai[1], (case action
65
+ when :pre_start then 'pre_start'
66
+ when :post_start then 'post_start'
67
+ when :pre_stop then 'pre_stop'
68
+ when :post_stop then 'post_stop'
69
+ end)
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,52 @@
1
+ module RailsPwnage::Util
2
+ # Complex procedure for killing a process or a bunch of process replicas
3
+ # kill_command is the script that's supposed to kill the process / processes (tried first)
4
+ # pid_patters are globs identifying PID files (a file can match any of the patterns)
5
+ # process_patterns are strings that should show on a command line (a process must match all)
6
+ # options:
7
+ # :verbose - display what gets killed
8
+ # :script_delay - the amount of seconds to sleep after launching the kill script
9
+ # :force_script - the kill script is executed even if there are no PID files
10
+ def self.kill_process_set(kill_script, pid_patterns, process_patterns, options = {})
11
+ # Phase 1: kill order (only if there's a PID file)
12
+ pid_patterns = [pid_patterns] unless pid_patterns.kind_of? Enumerable
13
+ unless options[:force_script]
14
+ pid_files = pid_patterns.map { |pattern| Dir.glob(pattern) }.flatten
15
+ unless pid_files.empty?
16
+ Kernel.system kill_script unless kill_script.nil?
17
+ sleep options[:script_delay] || 0.5
18
+ end
19
+ end
20
+
21
+ # Phase 2: look through PID files and issue kill orders
22
+ pinfo = process_info()
23
+ pid_files = pid_patterns.map { |pattern| Dir.glob(pattern) }.flatten
24
+ pid_files.each do |fname|
25
+ begin
26
+ pid = File.open(fname, 'r') { |f| f.read.strip! }
27
+ process_cmdline = pinfo[pid][:cmdline]
28
+ # avoid killing innocent victims
29
+ if pinfo[pid].nil? or process_patterns.all? { |pattern| process_cmdline.index pattern }
30
+ print "Killing #{pid}: #{process_cmdline}\n"
31
+ Process.kill 'TERM', pid.to_i
32
+ end
33
+ rescue
34
+ # just in case the file gets wiped before we see it
35
+ end
36
+ begin
37
+ print "Deleting #{fname}\n"
38
+ File.delete fname if File.exists? fname
39
+ rescue
40
+ # prevents crashing if the file is wiped after we call exists?
41
+ end
42
+ end
43
+
44
+ # Phase 3: look through the process table and kill anything that looks good
45
+ pinfo = process_info()
46
+ pinfo.each do |pid, info|
47
+ next unless process_patterns.all? { |pattern| info[:cmdline].index pattern }
48
+ print "Killing #{pid}: #{pinfo[pid][:cmdline]}\n"
49
+ Process.kill 'TERM', pid.to_i
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,5 @@
1
+ module RailsPwnage::Util
2
+ class << self
3
+ include RailsPwnage::Base
4
+ end
5
+ end
data/lib/rails_pwnerer.rb CHANGED
@@ -21,6 +21,9 @@ require 'pwnage/base/process.rb'
21
21
  require 'pwnage/base/rails.rb'
22
22
  require 'pwnage/base/startup.rb'
23
23
 
24
+ require 'pwnage/util/main.rb'
25
+ require 'pwnage/util/kill_process_set.rb'
26
+
24
27
  require 'pwnage/config/app.rb'
25
28
  require 'pwnage/config/main.rb'
26
29
  require 'pwnage/config/paths.rb'
@@ -44,6 +47,7 @@ require 'pwnage/app/cluster_config.rb'
44
47
  require 'pwnage/app/database.rb'
45
48
  require 'pwnage/app/gems.rb'
46
49
  require 'pwnage/app/nginx_config.rb'
50
+ require 'pwnage/app/scripts.rb'
47
51
  require 'pwnage/app/svn.rb'
48
52
 
49
53
  require 'pwnage/ctl_executor.rb'
@@ -1,18 +1,18 @@
1
1
 
2
- # Gem::Specification for Rails_pwnerer-0.5.16
2
+ # Gem::Specification for Rails_pwnerer-0.5.17
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.16
8
+ version: 0.5.17
9
9
  platform: ruby
10
10
  authors:
11
11
  - Victor Costan
12
12
  autorequire:
13
13
  bindir: bin
14
14
 
15
- date: 2008-08-25 00:00:00 -04:00
15
+ date: 2008-08-27 00:00:00 -04:00
16
16
  default_executable:
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
@@ -44,6 +44,7 @@ extra_rdoc_files:
44
44
  - lib/pwnage/app/gems.rb
45
45
  - lib/pwnage/app/main.rb
46
46
  - lib/pwnage/app/nginx_config.rb
47
+ - lib/pwnage/app/scripts.rb
47
48
  - lib/pwnage/app/svn.rb
48
49
  - lib/pwnage/base/atomics.rb
49
50
  - lib/pwnage/base/dirs.rb
@@ -72,6 +73,8 @@ extra_rdoc_files:
72
73
  - lib/pwnage/scaffolds/packages.rb
73
74
  - lib/pwnage/scaffolds/rubygems.rb
74
75
  - lib/pwnage/scaffolds/sshd.rb
76
+ - lib/pwnage/util/kill_process_set.rb
77
+ - lib/pwnage/util/main.rb
75
78
  - lib/rails_pwnerer.rb
76
79
  - LICENSE
77
80
  - README
@@ -86,6 +89,7 @@ files:
86
89
  - lib/pwnage/app/gems.rb
87
90
  - lib/pwnage/app/main.rb
88
91
  - lib/pwnage/app/nginx_config.rb
92
+ - lib/pwnage/app/scripts.rb
89
93
  - lib/pwnage/app/svn.rb
90
94
  - lib/pwnage/base/atomics.rb
91
95
  - lib/pwnage/base/dirs.rb
@@ -114,6 +118,8 @@ files:
114
118
  - lib/pwnage/scaffolds/packages.rb
115
119
  - lib/pwnage/scaffolds/rubygems.rb
116
120
  - lib/pwnage/scaffolds/sshd.rb
121
+ - lib/pwnage/util/kill_process_set.rb
122
+ - lib/pwnage/util/main.rb
117
123
  - lib/rails_pwnerer.rb
118
124
  - LICENSE
119
125
  - Manifest
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.16
4
+ version: 0.5.17
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-25 00:00:00 -04:00
12
+ date: 2008-08-27 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -41,6 +41,7 @@ extra_rdoc_files:
41
41
  - lib/pwnage/app/gems.rb
42
42
  - lib/pwnage/app/main.rb
43
43
  - lib/pwnage/app/nginx_config.rb
44
+ - lib/pwnage/app/scripts.rb
44
45
  - lib/pwnage/app/svn.rb
45
46
  - lib/pwnage/base/atomics.rb
46
47
  - lib/pwnage/base/dirs.rb
@@ -69,6 +70,8 @@ extra_rdoc_files:
69
70
  - lib/pwnage/scaffolds/packages.rb
70
71
  - lib/pwnage/scaffolds/rubygems.rb
71
72
  - lib/pwnage/scaffolds/sshd.rb
73
+ - lib/pwnage/util/kill_process_set.rb
74
+ - lib/pwnage/util/main.rb
72
75
  - lib/rails_pwnerer.rb
73
76
  - LICENSE
74
77
  - README
@@ -83,6 +86,7 @@ files:
83
86
  - lib/pwnage/app/gems.rb
84
87
  - lib/pwnage/app/main.rb
85
88
  - lib/pwnage/app/nginx_config.rb
89
+ - lib/pwnage/app/scripts.rb
86
90
  - lib/pwnage/app/svn.rb
87
91
  - lib/pwnage/base/atomics.rb
88
92
  - lib/pwnage/base/dirs.rb
@@ -111,6 +115,8 @@ files:
111
115
  - lib/pwnage/scaffolds/packages.rb
112
116
  - lib/pwnage/scaffolds/rubygems.rb
113
117
  - lib/pwnage/scaffolds/sshd.rb
118
+ - lib/pwnage/util/kill_process_set.rb
119
+ - lib/pwnage/util/main.rb
114
120
  - lib/rails_pwnerer.rb
115
121
  - LICENSE
116
122
  - Manifest