py3: (Better) fix percentages in configs

We previously fixed a bunch of places, but not quite *all* the places;
at the very least, some account-layer services (like the replicator and
auditor IIRC) could still bomb out -- and it's important that
replicators still respect fallocate_reserve!

Now, do the NicerInterpolation thing every time we call readconf.
Additionally, clean up the original fix to avoid globally
monkey-patching configparser.

Related-Bug: #1844368
Closes-Bug: #1872553
Change-Id: I4512e686cde37930f0482909f537220a57fef76b
(cherry picked from commit 2854eddb44)
This commit is contained in:
Tim Burke 2020-06-09 16:45:21 -07:00
parent 2e50b58170
commit bb1263b8d4
2 changed files with 28 additions and 20 deletions

View File

@ -72,6 +72,7 @@ if not six.PY2:
utf16_decoder = codecs.getdecoder('utf-16')
utf16_encoder = codecs.getencoder('utf-16')
from six.moves import cPickle as pickle
from six.moves import configparser
from six.moves.configparser import (ConfigParser, NoSectionError,
NoOptionError, RawConfigParser)
from six.moves import range, http_client
@ -2965,6 +2966,17 @@ def read_conf_dir(parser, conf_dir):
return parser.read(sorted(conf_files))
if six.PY2:
NicerInterpolation = None # just don't cause ImportErrors over in wsgi.py
else:
class NicerInterpolation(configparser.BasicInterpolation):
def before_get(self, parser, section, option, value, defaults):
if '%(' not in value:
return value
return super(NicerInterpolation, self).before_get(
parser, section, option, value, defaults)
def readconf(conf_path, section_name=None, log_name=None, defaults=None,
raw=False):
"""
@ -2986,7 +2998,19 @@ def readconf(conf_path, section_name=None, log_name=None, defaults=None,
if raw:
c = RawConfigParser(defaults)
else:
c = ConfigParser(defaults)
if six.PY2:
c = ConfigParser(defaults)
else:
# In general, we haven't really thought much about interpolation
# in configs. Python's default ConfigParser has always supported
# it, though, so *we* got it "for free". Unfortunatley, since we
# "supported" interpolation, we have to assume there are
# deployments in the wild that use it, and try not to break them.
# So, do what we can to mimic the py2 behavior of passing through
# values like "1%" (which we want to support for
# fallocate_reserve).
c = ConfigParser(defaults, interpolation=NicerInterpolation())
if hasattr(conf_path, 'readline'):
if hasattr(conf_path, 'seek'):
conf_path.seek(0)

View File

@ -32,7 +32,6 @@ from eventlet.green import socket, ssl, os as green_os
import six
from six import BytesIO
from six import StringIO
from six.moves import configparser
from swift.common import utils, constraints
from swift.common.storage_policy import BindPortsCache
@ -41,7 +40,7 @@ from swift.common.swob import Request, wsgi_quote, wsgi_unquote, \
from swift.common.utils import capture_stdio, disable_fallocate, \
drop_privileges, get_logger, NullLogger, config_true_value, \
validate_configuration, get_hub, config_auto_int_value, \
reiterate
reiterate, NicerInterpolation
SIGNUM_TO_NAME = {getattr(signal, n): n for n in dir(signal)
if n.startswith('SIG') and '_' not in n}
@ -56,23 +55,6 @@ except (ImportError, NotImplementedError):
CPU_COUNT = 1
if not six.PY2:
# In general, we haven't really thought much about interpolation in
# configs. Python's default ConfigParser has always supported it, though,
# so *we* got it "for free". Unfortunatley, since we "supported"
# interpolation, we have to assume there are deployments in the wild that
# use it, and try not to break them. So, do what we can to mimic the py2
# behavior of passing through values like "1%" (which we want to support
# for fallocate_reserve).
class NicerInterpolation(configparser.BasicInterpolation):
def before_get(self, parser, section, option, value, defaults):
if '%(' not in value:
return value
return super(NicerInterpolation, self).before_get(
parser, section, option, value, defaults)
configparser.ConfigParser._DEFAULT_INTERPOLATION = NicerInterpolation()
class NamedConfigLoader(loadwsgi.ConfigLoader):
"""
Patch paste.deploy's ConfigLoader so each context object will know what
@ -80,6 +62,8 @@ class NamedConfigLoader(loadwsgi.ConfigLoader):
"""
def get_context(self, object_type, name=None, global_conf=None):
if not six.PY2:
self.parser._interpolation = NicerInterpolation()
context = super(NamedConfigLoader, self).get_context(
object_type, name=name, global_conf=global_conf)
context.name = name