Commit 9a33365f authored by Tim Burke's avatar Tim Burke

py3: Allow percentages in configs

Previously, configs like

    fallocate_reserve = 1%

would cause a py3 backend server to fail to start, complaining like

    configparser.InterpolationSyntaxError: Error in file
    /etc/swift/object-server/1.conf.d: '%' must be followed
    by '%' or '(', found: '%'

This could also come up in proxy-server configs, with things like
percent signs in tempauth password.

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". On py2, we didn't really have to think about
it, since values like "1%" would pass through just fine. (It would blow
up a SafeConfigParser, but a normal ConfigParser only does replacements
when there's something like a "%(opt)s" in the value.)

On py3, SafeConfigParser became ConfigParser, and the old interpolation
mode (AFAICT) doesn't exist.

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.

Change-Id: I0f9cecd11f00b522a8486972551cb30af151ce32
Closes-Bug: #1844368
parent 2d87ad63
......@@ -32,6 +32,7 @@ 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
......@@ -55,6 +56,23 @@ 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
......
......@@ -70,6 +70,7 @@ class TestWSGI(unittest.TestCase):
config = """
[DEFAULT]
swift_dir = TEMPDIR
fallocate_reserve = 1%
[pipeline:main]
pipeline = proxy-server
......@@ -122,6 +123,7 @@ class TestWSGI(unittest.TestCase):
'__file__': conf_file,
'here': os.path.dirname(conf_file),
'conn_timeout': '0.2',
'fallocate_reserve': '1%',
'swift_dir': t,
'__name__': 'proxy-server'
}
......@@ -2064,6 +2066,7 @@ class TestPipelineModification(unittest.TestCase):
[filter:tempauth]
use = egg:swift#tempauth
user_test_tester = t%%sting .admin
[filter:copy]
use = egg:swift#copy
......@@ -2090,7 +2093,10 @@ class TestPipelineModification(unittest.TestCase):
for version, pipeline, expected in to_test:
conf_file = os.path.join(t, 'proxy-server.conf')
with open(conf_file, 'w') as f:
f.write(contents % (t, pipeline))
to_write = contents % (t, pipeline)
# Sanity check that the password only has one % in it
self.assertIn('t%sting', to_write)
f.write(to_write)
app = wsgi.loadapp(conf_file, global_conf={})
actual = ' '.join(m.rsplit('.', 1)[1]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment