1
0
Fork 0
mirror of https://github.com/puma/puma.git synced 2022-11-09 13:48:40 -05:00

Add ability to use a config file (-C, --config)

This commit is contained in:
Evan Phoenix 2011-12-06 14:56:38 -08:00
parent 5fc904b099
commit 6103e7f45b
7 changed files with 163 additions and 61 deletions

5
examples/config.rb Normal file
View file

@ -0,0 +1,5 @@
state_path "puma.state"
activate_control_app
rackup "test/lobster.ru"
threads 3, 10

View file

@ -3,6 +3,7 @@ require 'uri'
require 'puma/server'
require 'puma/const'
require 'puma/config'
require 'rack/commonlogger'
@ -10,9 +11,7 @@ module Puma
# Handles invoke a Puma::Server in a command line style.
#
class CLI
DefaultTCPHost = "0.0.0.0"
DefaultTCPPort = 9292
DefaultRackup = "config.ru"
IS_JRUBY = defined?(JRUBY_VERSION)
# Create a new CLI object using +argv+ as the command line
@ -109,14 +108,17 @@ module Puma
@options = {
:min_threads => 0,
:max_threads => 16,
:quiet => false
:quiet => false,
:binds => []
}
@binds = []
@parser = OptionParser.new do |o|
o.on "-b", "--bind URI", "URI to bind to (tcp:// and unix:// only)" do |arg|
@binds << arg
@options[:binds] << arg
end
o.on "-C", "--config PATH", "Load PATH as a config file" do |arg|
@options[:config_file] = arg
end
o.on "--pidfile PATH", "Use PATH as a pidfile" do |arg|
@ -127,6 +129,19 @@ module Puma
@options[:quiet] = true
end
o.on "-S", "--state PATH", "Where to store the state details" do |arg|
@options[:state] = arg
end
o.on "--control URL", "The bind url to use for the control server",
"Use 'auto' to use temp unix server" do |arg|
if arg
@options[:control_url] = arg
elsif IS_JRUBY
raise NotImplementedError, "No default url available on JRuby"
end
end
o.on '-t', '--threads INT', "min:max threads to use (default 0:16)" do |arg|
min, max = arg.split(":")
if max
@ -138,27 +153,6 @@ module Puma
end
end
o.on "-S", "--state PATH", "Where to store the state details" do |arg|
@options[:state] = arg
end
o.on "--status [URL]", "The bind url to use for the status server" do |arg|
if arg and arg != "@"
@options[:status_address] = arg
elsif IS_JRUBY
raise NotImplementedError, "No default url available on JRuby"
else
require 'tmpdir'
t = (Time.now.to_f * 1000).to_i
path = "#{Dir.tmpdir}/puma-status-#{t}-#{$$}"
@temp_status_path = path
@options[:status_address] = "unix://#{path}"
end
end
end
@parser.banner = "puma <options> <rackup file>"
@ -173,7 +167,7 @@ module Puma
# the rackup file, and set @app.
#
def load_rackup
@app, options = Rack::Builder.parse_file @rackup
@app, options = Rack::Builder.parse_file @options[:rackup]
@options.merge! options
options.each do |key,val|
@ -200,9 +194,7 @@ module Puma
if path = @options[:state]
state = { "pid" => Process.pid }
if url = @options[:status_address]
state["status_address"] = url
end
state["config"] = @config
File.open(path, "w") do |f|
f.write state.to_yaml
@ -213,6 +205,18 @@ module Puma
# :nodoc:
def parse_options
@parser.parse! @argv
@config = Puma::Configuration.new @options
@config.load
unless @options[:rackup]
@options[:rackup] = @argv.shift || DefaultRackup
end
if @options[:control_url] == "auto"
path = @temp_status_path = Configuration.temp_path
@options[:control_url] = "unix://#{path}"
end
end
# Parse the options, load the rackup, start the server and wait
@ -221,10 +225,10 @@ module Puma
def run
parse_options
@rackup = @argv.shift || "config.ru"
rackup = @options[:rackup]
unless File.exists?(@rackup)
raise "Missing rackup file '#{@rackup}'"
unless File.exists?(rackup)
raise "Missing rackup file '#{rackup}'"
end
load_rackup
@ -235,11 +239,6 @@ module Puma
@app = Rack::CommonLogger.new(@app, STDOUT)
end
if @binds.empty?
@options[:Host] ||= DefaultTCPHost
@options[:Port] ||= DefaultTCPPort
end
min_t = @options[:min_threads]
max_t = @options[:max_threads]
@ -250,12 +249,7 @@ module Puma
log "Puma #{Puma::Const::PUMA_VERSION} starting..."
log "* Min threads: #{min_t}, max threads: #{max_t}"
if @options[:Host]
log "* Listening on tcp://#{@options[:Host]}:#{@options[:Port]}"
server.add_tcp_listener @options[:Host], @options[:Port]
end
@binds.each do |str|
@options[:binds].each do |str|
uri = URI.parse str
case uri.scheme
when "tcp"
@ -273,7 +267,7 @@ module Puma
@server = server
if str = @options[:status_address]
if str = @options[:control_url]
require 'puma/app/status'
uri = URI.parse str

98
lib/puma/config.rb Normal file
View file

@ -0,0 +1,98 @@
module Puma
class Configuration
DefaultTCPHost = "0.0.0.0"
DefaultTCPPort = 9292
def initialize(options)
@options = options
@options[:binds] ||= []
end
attr_reader :options
def load
if path = @options[:config_file]
instance_eval File.read(path), path, 1
end
# Rakeup default option support
if host = @options[:Host]
port = @options[:Port] || DefaultTCPPort
@options[:binds] << "tcp://#{host}:#{port}"
end
if @options[:binds].empty?
@options[:binds] << "tcp://#{DefaultTCPHost}:#{DefaultTCPPort}"
end
end
def self.temp_path
require 'tmpdir'
t = (Time.now.to_f * 1000).to_i
"#{Dir.tmpdir}/puma-status-#{t}-#{$$}"
end
# Use +obj+ or +block+ as the Rack app. This allows a config file to
# be the app itself.
#
def app(obj=nil, &block)
obj ||= block
raise "Provide either a #call'able or a block" unless obj
@options[:app] = obj
end
# Start the Puma control rack app on +url+. This app can be communicated
# with to control the main server.
#
def activate_control_app(url="auto")
@options[:control_url] = url
end
# Bind the server to +url+. tcp:// and unix:// are the only accepted
# protocols.
#
def bind(url)
@options[:binds] << url
end
# Store the pid of the server in the file at +path+.
def pidfile(path)
@options[:pidfile] = path
end
# Disable request logging.
#
def quiet
@options[:quiet] = true
end
# Load +path+ as a rackup file.
#
def rackup(path)
@options[:rackup] = path.to_s
end
# Configure +min+ to be the minimum number of threads to use to answer
# requests and +max+ the maximum.
#
def threads(min, max)
if min > max
raise "The minimum number of threads must be less than the max"
end
@options[:min_threads] = min
@options[:max_threads] = max
end
# Use +path+ as the file to store the server info state. This is
# used by pumactl to query and control the server.
#
def state_path(path)
@options[:state] = path.to_s
end
end
end

View file

@ -71,7 +71,7 @@ module Puma
PATH_INFO = 'PATH_INFO'.freeze
PUMA_VERSION = VERSION = "0.9.0".freeze
PUMA_VERSION = VERSION = "0.9.1".freeze
PUMA_TMP_BASE = "puma".freeze

View file

@ -1,6 +1,8 @@
require 'optparse'
require 'puma/const'
require 'puma/config'
require 'yaml'
require 'uri'
@ -22,7 +24,7 @@ module Puma
end
def connect
if str = @state['status_address']
if str = @config.options[:control_url]
uri = URI.parse str
case uri.scheme
when "tcp"
@ -44,6 +46,7 @@ module Puma
@parser.parse! @argv
@state = YAML.load_file(@path)
@config = @state['config']
cmd = @argv.shift
@ -101,8 +104,8 @@ module Puma
def command_stats
sock = connect
s << "GET /stats HTTP/1.0\r\n\r\n"
rep = s.read
sock << "GET /stats HTTP/1.0\r\n\r\n"
rep = sock.read
body = rep.split("\r\n").last

View file

@ -137,7 +137,9 @@ module Puma
@todo << Stop
end
@workers.each { |w| w.join }
# Use this instead of #each so that we don't stop in the middle
# of each and see a mutated object mid #each
@workers.first.join until @workers.empty?
@spawned = 0
@workers = []

View file

@ -28,13 +28,13 @@ class TestCLI < Test::Unit::TestCase
end
unless defined? JRUBY_VERSION
def test_status
def test_control
url = "unix://#{@tmp_path}"
sin = StringIO.new
sout = StringIO.new
cli = Puma::CLI.new ["-b", "unix://#{@tmp_path2}", "--status", url, "test/lobster.ru"], sin, sout
cli = Puma::CLI.new ["-b", "unix://#{@tmp_path2}", "--control", url, "test/lobster.ru"], sin, sout
cli.parse_options
t = Thread.new { cli.run }
@ -51,13 +51,13 @@ class TestCLI < Test::Unit::TestCase
t.join
end
def test_status_stop
def test_control_stop
url = "unix://#{@tmp_path}"
sin = StringIO.new
sout = StringIO.new
cli = Puma::CLI.new ["-b", "unix://#{@tmp_path2}", "--status", url, "test/lobster.ru"], sin, sout
cli = Puma::CLI.new ["-b", "unix://#{@tmp_path2}", "--control", url, "test/lobster.ru"], sin, sout
cli.parse_options
t = Thread.new { cli.run }
@ -73,9 +73,9 @@ class TestCLI < Test::Unit::TestCase
t.join
end
def test_tmp_status
def test_tmp_control
url = "tcp://127.0.0.1:8232"
cli = Puma::CLI.new ["--state", @tmp_path, "--status"]
cli = Puma::CLI.new ["--state", @tmp_path, "--control", "auto"]
cli.parse_options
cli.write_state
@ -83,7 +83,7 @@ class TestCLI < Test::Unit::TestCase
assert_equal Process.pid, data["pid"]
url = data["status_address"]
url = data["config"].options[:control_url]
m = %r!unix://(.*)!.match(url)
@ -93,13 +93,13 @@ class TestCLI < Test::Unit::TestCase
def test_state
url = "tcp://127.0.0.1:8232"
cli = Puma::CLI.new ["--state", @tmp_path, "--status", url]
cli = Puma::CLI.new ["--state", @tmp_path, "--control", url]
cli.parse_options
cli.write_state
data = YAML.load_file(@tmp_path)
assert_equal Process.pid, data["pid"]
assert_equal url, data["status_address"]
assert_equal url, data["config"].options[:control_url]
end
end