golden_brindle 0.1.1 → 0.2

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