golden_brindle 0.1.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.0
1
+ 0.2
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{golden_brindle}
8
- s.version = "0.1.1"
8
+ s.version = "0.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Alexander Simonov"]
12
- s.date = %q{2011-09-02}
12
+ s.date = %q{2011-09-03}
13
13
  s.default_executable = %q{golden_brindle}
14
14
  s.description = %q{Unicorn HTTP server multiple application runner tool}
15
15
  s.email = %q{alex@simonov.me}
@@ -34,6 +34,8 @@ Gem::Specification.new do |s|
34
34
  "lib/golden_brindle/command.rb",
35
35
  "lib/golden_brindle/configure.rb",
36
36
  "lib/golden_brindle/const.rb",
37
+ "lib/golden_brindle/hooks.rb",
38
+ "lib/golden_brindle/rails_support.rb",
37
39
  "lib/golden_brindle/restart.rb",
38
40
  "lib/golden_brindle/start.rb",
39
41
  "lib/golden_brindle/stop.rb",
@@ -13,8 +13,8 @@ module Cluster
13
13
 
14
14
  def validate
15
15
  @cwd = File.expand_path(@cwd)
16
- valid_dir? @cwd, "Invalid path to golden_brindle configuration files: #@cwd"
17
- return @valid
16
+ valid_dir? @cwd, "Invalid path to golden_brindle configuration files: #{@cwd}"
17
+ @valid
18
18
  end
19
19
 
20
20
  def run
@@ -22,9 +22,7 @@ module Cluster
22
22
  counter = 0
23
23
  errors = 0
24
24
  Dir.chdir @cwd do
25
- confs = Dir.glob("*.yml")
26
- confs += Dir.glob("*.conf")
27
- confs.each do |conf|
25
+ Dir.glob("**/*.{yml,conf}").each do |conf|
28
26
  cmd = "golden_brindle #{command} -C #{conf}"
29
27
  cmd += " -d" if command == "start" #daemonize only when start
30
28
  puts cmd if @verbose
@@ -32,8 +30,7 @@ module Cluster
32
30
  puts output if @verbose
33
31
  status = $?.success?
34
32
  puts "golden_brindle #{command} returned an error." unless status
35
- counter += 1 if status
36
- errors += 1 unless status
33
+ status ? counter += 1 : errors += 1
37
34
  end
38
35
  end
39
36
  puts "Success:#{counter}; Errors: #{errors}"
@@ -43,7 +40,6 @@ module Cluster
43
40
 
44
41
  class Start < GemPlugin::Plugin "/commands"
45
42
  include Cluster::Base
46
-
47
43
  end
48
44
 
49
45
  class Stop < GemPlugin::Plugin "/commands"
@@ -7,7 +7,7 @@ module GoldenBrindle
7
7
  begin
8
8
  Process.kill(signal, pid)
9
9
  rescue Errno::ESRCH
10
- puts "Process does not exist. Not running."
10
+ puts "Process does not exist. Not running."
11
11
  end
12
12
  puts "Done."
13
13
  end
@@ -30,8 +30,7 @@ module GoldenBrindle
30
30
  end
31
31
  end
32
32
  end
33
-
34
-
33
+
35
34
  # Called by the subclass to setup the command and parse the argv arguments.
36
35
  # The call is destructive on argv since it uses the OptionParser#parse! function.
37
36
  def initialize(options={})
@@ -42,9 +41,7 @@ module GoldenBrindle
42
41
  # this is retarded, but it has to be done this way because -h and -v exit
43
42
  @done_validating = false
44
43
  @original_args = argv.dup
45
-
46
44
  configure
47
-
48
45
  # I need to add my own -h definition to prevent the -h by default from exiting.
49
46
  @opt.on_tail("-h", "--help", "Show this message") do
50
47
  @done_validating = true
@@ -58,7 +55,6 @@ module GoldenBrindle
58
55
  puts "Version #{GoldenBrindle::Const::VERSION}"
59
56
  end
60
57
  end
61
-
62
58
  @opt.parse! argv
63
59
  end
64
60
 
@@ -94,7 +90,7 @@ module GoldenBrindle
94
90
 
95
91
  # Returns true/false depending on whether the command is configured properly.
96
92
  def validate
97
- return @valid
93
+ @valid
98
94
  end
99
95
 
100
96
  # Returns a help message. Defaults to OptionParser#help which should be good.
@@ -108,10 +104,9 @@ module GoldenBrindle
108
104
  raise NotImplementedError
109
105
  end
110
106
 
111
-
112
107
  # Validates the given expression is true and prints the message if not, exiting.
113
108
  def valid?(exp, message)
114
- if not @done_validating and (not exp)
109
+ if !@done_validating && !exp
115
110
  failure message
116
111
  @valid = false
117
112
  @done_validating = true
@@ -120,22 +115,21 @@ module GoldenBrindle
120
115
 
121
116
  # Validates that a file exists and if not displays the message
122
117
  def valid_exists?(file, message)
123
- valid?(file != nil && File.exist?(file), message)
118
+ valid?(File.exist?(file), message)
124
119
  end
125
120
 
126
-
127
121
  # Validates that the file is a file and not a directory or something else.
128
122
  def valid_file?(file, message)
129
- valid?(file != nil && File.file?(file), message)
123
+ valid?(File.file?(file), message)
130
124
  end
131
125
 
132
126
  # Validates that the given directory exists
133
127
  def valid_dir?(file, message)
134
- valid?(file != nil && File.directory?(file), message)
128
+ valid?(File.directory?(file), message)
135
129
  end
136
130
 
137
131
  def can_change_user?
138
- valid?(Process.euid.to_i == 0,"if you want to change workers UID/GID you must run script from root")
132
+ valid?(Process.euid.to_i == 0, "if you want to change workers UID/GID you must run script from root")
139
133
  end
140
134
 
141
135
  def valid_user?(user)
@@ -175,7 +169,7 @@ module GoldenBrindle
175
169
  def commands
176
170
  pmgr = GemPlugin::Manager.instance
177
171
  list = pmgr.plugins["/commands"].keys
178
- return list.sort
172
+ list.sort
179
173
  end
180
174
 
181
175
  # Prints a list of available commands.
@@ -227,16 +221,16 @@ module GoldenBrindle
227
221
  # Normally the command is NOT valid right after being created
228
222
  # but sometimes (like with -h or -v) there's no further processing
229
223
  # needed so the command is already valid so we can skip it.
230
- if not command.done_validating
231
- if not command.validate
232
- STDERR.puts "#{cmd_name} reported an error. Use goldent_brindle #{cmd_name} -h to get help."
224
+ if !command.done_validating
225
+ if !command.validate
226
+ STDERR.puts "#{cmd_name} reported an error. Use golden_brindle #{cmd_name} -h to get help."
233
227
  return false
234
228
  else
235
229
  command.run
236
230
  end
237
231
  end
238
232
 
239
- return true
233
+ true
240
234
  end
241
235
  end
242
236
 
@@ -32,7 +32,7 @@ module Brindle
32
32
  valid_dir? File.dirname(@config_file), "Path to config file not valid: #{@config_file}"
33
33
 
34
34
  if @config_script
35
- valid_exists?(@config_script, "Unicorn-specific config file not there: #@config_script")
35
+ valid_exists?(@config_script, "Unicorn-specific config file not there: #{@config_script}")
36
36
  return false unless @valid
37
37
  end
38
38
 
@@ -41,7 +41,7 @@ module Brindle
41
41
  valid_dir? File.dirname(@pid_file), "Path to pid file not valid: #@pid_file"
42
42
  valid_user? @user if @user
43
43
  valid_group? @group if @group
44
- return @valid
44
+ @valid
45
45
  end
46
46
 
47
47
  def run
@@ -3,7 +3,7 @@ module GoldenBrindle
3
3
  module Const
4
4
 
5
5
  # current version
6
- VERSION="0.1.1"
6
+ VERSION="0.2"
7
7
  # main banner
8
8
  BANNER = "Usage: golden_brindle <command> [options]"
9
9
 
@@ -0,0 +1,70 @@
1
+ module Brindle
2
+ module Hooks
3
+ def collect_hooks
4
+ [:after_fork, :after_reload, :before_fork, :before_exec].inject({}) do |memo, sym|
5
+ memo[sym] = send(sym)
6
+ memo
7
+ end
8
+ end
9
+
10
+ def after_fork
11
+ lambda do |server, worker|
12
+ defined?(ActiveRecord::Base) and
13
+ ActiveRecord::Base.establish_connection
14
+ # trying to change user and group
15
+ begin
16
+ # check if something not set in config or cli
17
+ unless @user.nil? || @group.nil?
18
+ uid, gid = Process.euid, Process.egid
19
+ user, group = @user, @group
20
+ target_uid = Etc.getpwnam(user).uid
21
+ target_gid = Etc.getgrnam(group).gid
22
+ worker.tmp.chown(target_uid, target_gid)
23
+ if uid != target_uid || gid != target_gid
24
+ Process.initgroups(user, target_gid)
25
+ Process::GID.change_privilege(target_gid)
26
+ Process::UID.change_privilege(target_uid)
27
+ end
28
+ end
29
+ rescue => e
30
+ if ENV['RAILS_ENV'] == 'development'
31
+ STDERR.puts "couldn't change user, oh well"
32
+ else
33
+ raise e
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ def before_fork
40
+ lambda do |server, worker|
41
+ defined?(ActiveRecord::Base) and
42
+ ActiveRecord::Base.connection.disconnect!
43
+ # http://rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
44
+ if GC.respond_to?(:copy_on_write_friendly=)
45
+ GC.copy_on_write_friendly = true
46
+ end
47
+ old_pid = "#{server.config[:pid]}.oldbin"
48
+ if File.exists?(old_pid) && server.pid != old_pid
49
+ begin
50
+ Process.kill("QUIT", File.read(old_pid).to_i)
51
+ rescue Errno::ENOENT, Errno::ESRCH
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ def after_reload
58
+ lambda do
59
+ ::FileUtils.mkdir_p(%w(cache pids sessions sockets).map! { |d| "tmp/#{d}" })
60
+ end
61
+ end
62
+
63
+ def before_exec
64
+ lambda do |server|
65
+ ENV["BUNDLE_GEMFILE"] = "#{@cwd}/Gemfile" if @bundler
66
+ end
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,80 @@
1
+ module Brindle
2
+ class RailsSupport
3
+ class << self
4
+
5
+ def rails3?
6
+ ::Rails::VERSION::MAJOR == 3
7
+ end
8
+
9
+ def rails2?
10
+ ::Rails::VERSION::MAJOR == 2
11
+ end
12
+
13
+ def support_rack?
14
+ return true if rails3?
15
+ return true if rails2? && ::Rails::VERSION::MINOR >= 3
16
+ false
17
+ end
18
+
19
+ def rails3_application
20
+ return unless rails3? || ::File.exist?('config/application.rb')
21
+ return Object.const_get($1)::Application if \
22
+ ::File.read('config/application.rb') =~ /^module\s+([\w:]+)\s*$/
23
+ rescue NameError
24
+ nil
25
+ end
26
+
27
+ def rails_dispatcher
28
+ result = rails3_application
29
+ if result.nil? && defined?(ActionController::Dispatcher)
30
+ result = ActionController::Dispatcher.new
31
+ end
32
+ result || abort("Unable to locate the application dispatcher class")
33
+ end
34
+
35
+ def rails_builder(daemonize)
36
+ # this lambda won't run until after forking if preload_app is false
37
+ lambda do
38
+ # Load Rails
39
+ begin
40
+ require ::File.expand_path('config/boot')
41
+ require ::File.expand_path('config/environment')
42
+ rescue LoadError => e
43
+ abort "#{$0} must be run inside RAILS_ROOT: #{e.inspect}"
44
+ end
45
+
46
+ defined?(::Rails::VERSION::STRING) or
47
+ abort "Rails::VERSION::STRING not defined by config/{boot,environment}"
48
+
49
+ old_rails = !support_rack?
50
+
51
+ ::Rack::Builder.new do
52
+ map_path = ENV['RAILS_RELATIVE_URL_ROOT'] || '/'
53
+ if old_rails
54
+ if map_path != '/'
55
+ warn "relative URL roots may not work for older Rails"
56
+ end
57
+ warn "LogTailer not available for Rails < 2.3" unless daemonize
58
+ warn "Debugger not available" if $DEBUG
59
+ require 'unicorn/app/old_rails'
60
+ map(map_path) do
61
+ use Unicorn::App::OldRails::Static
62
+ run Unicorn::App::OldRails.new
63
+ end
64
+ else
65
+ use Rails::Rack::LogTailer unless daemonize
66
+ use Rails::Rack::Debugger if $DEBUG
67
+ map(map_path) do
68
+ unless defined?(ActionDispatch::Static)
69
+ use Rails::Rack::Static
70
+ end
71
+ run Brindle::RailsSupport.rails_dispatcher
72
+ end
73
+ end
74
+ end.to_app
75
+ end
76
+ end
77
+
78
+ end
79
+ end
80
+ end
@@ -24,7 +24,7 @@ module Brindle
24
24
  @cwd = File.expand_path(@cwd)
25
25
  valid_dir? @cwd, "Invalid path to application dir: #@cwd"
26
26
  valid_exists? File.join(@cwd,@pid_file), "PID file #@pid_file does not exist. Not running?"
27
- return @valid
27
+ @valid
28
28
  end
29
29
 
30
30
  def run
@@ -1,8 +1,8 @@
1
-
2
1
  module Brindle
3
2
 
4
3
  class Start < GemPlugin::Plugin "/commands"
5
4
  include GoldenBrindle::Command::Base
5
+ include Hooks
6
6
 
7
7
  def configure
8
8
  options [
@@ -28,80 +28,7 @@ module Brindle
28
28
  ]
29
29
  end
30
30
 
31
-
32
- #
33
- # Rails 3 dispatcher support
34
- # Code from unicorn_rails script
35
- #
36
- def self.rails_dispatcher
37
- if ::Rails::VERSION::MAJOR >= 3 && ::File.exist?('config/application.rb')
38
- if ::File.read('config/application.rb') =~ /^module\s+([\w:]+)\s*$/
39
- app_module = Object.const_get($1)
40
- begin
41
- result = app_module::Application
42
- rescue NameError
43
- end
44
- end
45
- end
46
-
47
- if result.nil? && defined?(ActionController::Dispatcher)
48
- result = ActionController::Dispatcher.new
49
- end
50
-
51
- result || abort("Unable to locate the application dispatcher class")
52
- end
53
-
54
- def rails_builder(daemonize)
55
- # this lambda won't run until after forking if preload_app is false
56
- lambda do ||
57
- # Load Rails
58
- begin
59
- require ::File.expand_path('config/boot')
60
- require ::File.expand_path('config/environment')
61
- rescue LoadError => err
62
- abort "#$0 must be run inside RAILS_ROOT: #{err.inspect}"
63
- end
64
-
65
- defined?(::Rails::VERSION::STRING) or
66
- abort "Rails::VERSION::STRING not defined by config/{boot,environment}"
67
- # it seems Rails >=2.2 support Rack, but only >=2.3 requires it
68
- old_rails = case ::Rails::VERSION::MAJOR
69
- when 0, 1 then true
70
- when 2 then Rails::VERSION::MINOR < 3 ? true : false
71
- else
72
- false
73
- end
74
-
75
- Rack::Builder.new do
76
- map_path = ENV['RAILS_RELATIVE_URL_ROOT'] || '/'
77
- if old_rails
78
- if map_path != '/'
79
- # patches + tests welcome, but I really cbf to deal with this
80
- # since all apps I've ever dealt with just use "/" ...
81
- warn "relative URL roots may not work for older Rails"
82
- end
83
- warn "LogTailer not available for Rails < 2.3" unless daemonize
84
- warn "Debugger not available" if $DEBUG
85
- require 'unicorn/app/old_rails'
86
- map(map_path) do
87
- use Unicorn::App::OldRails::Static
88
- run Unicorn::App::OldRails.new
89
- end
90
- else
91
- use Rails::Rack::LogTailer unless daemonize
92
- use Rails::Rack::Debugger if $DEBUG
93
- map(map_path) do
94
- unless defined?(ActionDispatch::Static)
95
- use Rails::Rack::Static
96
- end
97
- run Brindle::Start.rails_dispatcher
98
- end
99
- end
100
- end.to_app
101
- end
102
- end
103
-
104
- def validate
31
+ def validate
105
32
  if @config_file
106
33
  valid_exists?(@config_file, "Config file not there: #@config_file")
107
34
  return false unless @valid
@@ -127,7 +54,44 @@ module Brindle
127
54
  valid_dir? File.dirname(File.join(@cwd,@pid_file)), "Path to pid file not valid: #{@pid_file}"
128
55
  valid_user? @user if @user
129
56
  valid_group? @group if @group
130
- return @valid
57
+ @valid
58
+ end
59
+
60
+ def default_options
61
+ {
62
+ :listeners => [],
63
+ :pid => @pid_file,
64
+ :config_file => @config_script,
65
+ :worker_processes => @workers.to_i,
66
+ :working_directory => @cwd,
67
+ :timeout => @timeout.to_i
68
+ }
69
+ end
70
+
71
+ def bundler_cmd
72
+ cmd = "bundle exec #{@opt.program_name}"
73
+ @original_args.each_slice(2) do |arg_key,value|
74
+ cmd << " #{arg_key} #{value}" if arg_key != "-b"
75
+ end
76
+ cmd
77
+ end
78
+
79
+ def collect_listeners
80
+ return if @port.nil?
81
+ start_port = end_port = nil
82
+ start_port ||= @port.to_i
83
+ end_port ||= start_port + @servers.to_i - 1
84
+ (start_port..end_port).map do |port|
85
+ "#{@address}:#{port}"
86
+ end
87
+ end
88
+
89
+ def parse_listen_option
90
+ return if @listen.nil? || @listen.empty?
91
+ @listen.split(',').map do |listen|
92
+ listen = File.join(@cwd,listen) if listen[0..0] != "/" && !listen.match(/\w+\:\w+/)
93
+ "#{listen}"
94
+ end
131
95
  end
132
96
 
133
97
  def run
@@ -136,93 +100,24 @@ module Brindle
136
100
  if @bundler
137
101
  puts "Using Bundler"
138
102
  puts "reexec via bundle exec"
139
- require 'pp'
140
- cmd_for_exec = "bundle exec #{@opt.program_name}"
141
- @original_args.each_slice(2) do |arg_key,value|
142
- cmd_for_exec << " #{arg_key} #{value}" if arg_key != "-b"
143
- end
144
- exec(cmd_for_exec)
103
+ exec(bundler_cmd)
145
104
  end
146
- options = {
147
- :listeners => [],
148
- :pid => @pid_file,
149
- :config_file => @config_script,
150
- :worker_processes => @workers.to_i,
151
- :working_directory => @cwd,
152
- :timeout => @timeout.to_i
153
- }
105
+ options = default_options
154
106
  # set user via Unicorn options. If we don't set group - then use only user
155
107
  options[:user] = @user unless @user.nil?
156
108
  options[:stderr_path] = options[:stdout_path] = @log_file if @daemon
157
- # ensure Rails standard tmp paths exist
158
- options[:after_reload] = lambda do
159
- FileUtils.mkdir_p(%w(cache pids sessions sockets).map! { |d| "tmp/#{d}" })
160
- end
161
-
162
109
  options[:preload_app] = @preload
163
- # do base steps for Rails
164
- options[:after_fork] = lambda do |server, worker|
165
- defined?(ActiveRecord::Base) and
166
- ActiveRecord::Base.establish_connection
167
- # trying to change user and group
168
- begin
169
- # check if something not set in config or cli
170
- unless @user.nil? || @group.nil?
171
- uid, gid = Process.euid, Process.egid
172
- user, group = @user, @group
173
- target_uid = Etc.getpwnam(user).uid
174
- target_gid = Etc.getgrnam(group).gid
175
- worker.tmp.chown(target_uid, target_gid)
176
- if uid != target_uid || gid != target_gid
177
- Process.initgroups(user, target_gid)
178
- Process::GID.change_privilege(target_gid)
179
- Process::UID.change_privilege(target_uid)
180
- end
181
- end
182
- rescue => e
183
- if ENV['RAILS_ENV'] == 'development'
184
- STDERR.puts "couldn't change user, oh well"
185
- else
186
- raise e
187
- end
188
- end
189
- end
190
- options[:before_fork] = lambda do |server, worker|
191
- defined?(ActiveRecord::Base) and
192
- ActiveRecord::Base.connection.disconnect!
193
- # http://rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
194
- if GC.respond_to?(:copy_on_write_friendly=)
195
- GC.copy_on_write_friendly = true
196
- end
197
- old_pid = "#{server.config[:pid]}.oldbin"
198
- if File.exists?(old_pid) && server.pid != old_pid
199
- begin
200
- Process.kill("QUIT", File.read(old_pid).to_i)
201
- rescue Errno::ENOENT, Errno::ESRCH
202
- end
203
- end
204
- end
110
+ options.merge!(collect_hooks)
205
111
  ENV['RAILS_ENV'] = @environment
206
112
  ENV['RAILS_RELATIVE_URL_ROOT'] = @prefix
207
- unless @port.nil?
208
- start_port = end_port = nil
209
- start_port ||= @port.to_i
210
- end_port ||= start_port + @servers.to_i - 1
211
- (start_port..end_port).each do |port|
212
- options[:listeners] << "#{@address}:#{port}"
213
- end
214
- end
215
- unless @listen.nil? || @listen.empty?
216
- @listen.split(',').each do |listen|
217
- listen = File.join(@cwd,listen) if listen[0..0] != "/" && !listen.match(/\w+\:\w+/)
218
- options[:listeners] << "#{listen}"
219
- end
113
+ [collect_listeners, parse_listen_option].each do |listeners|
114
+ options[:listeners] += listeners if listeners
220
115
  end
221
- app = rails_builder(@daemon)
116
+ app = RailsSupport.rails_builder(@daemon)
222
117
  if @daemon
223
118
  Unicorn::Launcher.daemonize!(options)
224
119
  end
225
- puts "start Unicorn..."
120
+ puts "start Unicorn v#{Unicorn::Const::UNICORN_VERSION}..."
226
121
  if Unicorn.respond_to?(:run)
227
122
  Unicorn.run(app, options)
228
123
  else
@@ -6,6 +6,8 @@ require 'unicorn/launcher'
6
6
  require 'golden_brindle/const'
7
7
  require 'golden_brindle/command'
8
8
  require 'golden_brindle/configure'
9
+ require 'golden_brindle/rails_support'
10
+ require 'golden_brindle/hooks'
9
11
  require 'golden_brindle/start'
10
12
  require 'golden_brindle/stop'
11
13
  require 'golden_brindle/restart'
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: golden_brindle
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.1
5
+ version: "0.2"
6
6
  platform: ruby
7
7
  authors:
8
8
  - Alexander Simonov
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-09-02 00:00:00 +03:00
13
+ date: 2011-09-03 00:00:00 +03:00
14
14
  default_executable: golden_brindle
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -60,6 +60,8 @@ files:
60
60
  - lib/golden_brindle/command.rb
61
61
  - lib/golden_brindle/configure.rb
62
62
  - lib/golden_brindle/const.rb
63
+ - lib/golden_brindle/hooks.rb
64
+ - lib/golden_brindle/rails_support.rb
63
65
  - lib/golden_brindle/restart.rb
64
66
  - lib/golden_brindle/start.rb
65
67
  - lib/golden_brindle/stop.rb