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:
parent
5fc904b099
commit
6103e7f45b
7 changed files with 163 additions and 61 deletions
5
examples/config.rb
Normal file
5
examples/config.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
state_path "puma.state"
|
||||
activate_control_app
|
||||
|
||||
rackup "test/lobster.ru"
|
||||
threads 3, 10
|
|
@ -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
98
lib/puma/config.rb
Normal 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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 = []
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue