Skip to content

Commit

Permalink
Remove yaml (psych) requirement in StateFile (#2784)
Browse files Browse the repository at this point in the history
Don't require yaml in state_file.rb
cli.rb & launcher.rb - deprecate state file constants
  • Loading branch information
MSP-Greg committed Jan 1, 2022
1 parent 06e88c1 commit 2b6968f
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 13 deletions.
1 change: 1 addition & 0 deletions lib/puma/cli.rb
Expand Up @@ -21,6 +21,7 @@ class << self
# Handles invoke a Puma::Server in a command line style.
#
class CLI
# @deprecated 6.0.0
KEYS_NOT_TO_PERSIST_IN_STATE = Launcher::KEYS_NOT_TO_PERSIST_IN_STATE

# Create a new CLI object using +argv+ as the command line
Expand Down
1 change: 1 addition & 0 deletions lib/puma/launcher.rb
Expand Up @@ -15,6 +15,7 @@ module Puma
# It is responsible for either launching a cluster of Puma workers or a single
# puma server.
class Launcher
# @deprecated 6.0.0
KEYS_NOT_TO_PERSIST_IN_STATE = [
:logger, :lowlevel_error_handler,
:before_worker_shutdown, :before_worker_boot, :before_worker_fork,
Expand Down
48 changes: 41 additions & 7 deletions lib/puma/state_file.rb
@@ -1,15 +1,40 @@
# frozen_string_literal: true

require 'yaml'

module Puma

# Puma::Launcher uses StateFile to write a yaml file for use with Puma::ControlCLI.
#
# In previous versions of Puma, YAML was used to read/write the state file.
# Since Puma is similar to Bundler/RubyGems in that it may load before one's app
# does, minimizing the dependencies that may be shared with the app is desired.
#
# At present, it only works with numeric and string values. It is still a valid
# yaml file, and the CI tests parse it with Psych.
#
class StateFile

ALLOWED_FIELDS = %w!control_url control_auth_token pid running_from!

# @deprecated 6.0.0
FIELDS = ALLOWED_FIELDS

def initialize
@options = {}
end

def save(path, permission = nil)
contents =YAML.dump @options
contents = "---\n".dup
@options.each do |k,v|
next unless ALLOWED_FIELDS.include? k
case v
when Numeric
contents << "#{k}: #{v}\n"
when String
next if v.strip.empty?
contents << (k == 'running_from' || v.to_s.include?(' ') ?
"#{k}: \"#{v}\"\n" : "#{k}: #{v}\n")
end
end
if permission
File.write path, contents, mode: 'wb:UTF-8'
else
Expand All @@ -18,12 +43,21 @@ def save(path, permission = nil)
end

def load(path)
@options = YAML.load File.read(path)
File.read(path).lines.each do |line|
next if line.start_with? '#'
k,v = line.split ':', 2
next unless v && ALLOWED_FIELDS.include?(k)
v = v.strip
@options[k] =
case v
when /\A\d+\z/ then v.to_i
when /\A\d+\.\d+\z/ then v.to_f
else v.gsub(/\A"|"\z/, '')
end
end
end

FIELDS = %w!control_url control_auth_token pid running_from!

FIELDS.each do |f|
ALLOWED_FIELDS.each do |f|
define_method f do
@options[f]
end
Expand Down
24 changes: 18 additions & 6 deletions test/test_cli.rb
Expand Up @@ -4,6 +4,7 @@

require "puma/cli"
require "json"
require "psych"

class TestCLI < Minitest::Test
include SSLHelper if ::Puma::HAS_SSL
Expand Down Expand Up @@ -347,9 +348,21 @@ def test_tmp_control
cli = Puma::CLI.new ["--state", @tmp_path, "--control-url", "auto"]
cli.launcher.write_state

data = YAML.load File.read(@tmp_path)
opts = cli.launcher.instance_variable_get(:@options)

assert_equal Process.pid, data["pid"]
data = Psych.load_file @tmp_path

Puma::StateFile::ALLOWED_FIELDS.each do |key|
val =
case key
when 'pid' then Process.pid
when 'running_from' then File.expand_path('.') # same as Launcher
else opts[key.to_sym]
end
assert_equal val, data[key]
end

assert_equal (Puma::StateFile::ALLOWED_FIELDS & data.keys).sort, data.keys.sort

url = data["control_url"]

Expand All @@ -364,10 +377,9 @@ def test_state_file_callback_filtering
"--state", @tmp_path ]
cli.launcher.write_state

data = YAML.load_file(@tmp_path)
data = Psych.load_file @tmp_path

keys_not_stripped = data.keys & Puma::CLI::KEYS_NOT_TO_PERSIST_IN_STATE
assert_empty keys_not_stripped
assert_equal (Puma::StateFile::ALLOWED_FIELDS & data.keys).sort, data.keys.sort
end

def test_log_formatter_default_single
Expand Down Expand Up @@ -401,7 +413,7 @@ def test_state
cli = Puma::CLI.new ["--state", @tmp_path, "--control-url", url]
cli.launcher.write_state

data = YAML.load File.read(@tmp_path)
data = Psych.load_file @tmp_path

assert_equal Process.pid, data["pid"]
assert_equal url, data["control_url"]
Expand Down

0 comments on commit 2b6968f

Please sign in to comment.