mirror of https://github.com/fail2ban/fail2ban
SafeConfigParserWithIncludes: fixed read of included config-files (expands with localized version, so `inc.local` overwrites options of `inc.conf` for config-files included with before/after);
added new test to cover this case.pull/2306/head
parent
555b29e8e6
commit
0245777c84
|
@ -73,6 +73,17 @@ else: # pragma: no cover
|
|||
return self._cp_interpolate_some(option, accum, rest, section, map, *args, **kwargs)
|
||||
SafeConfigParser._interpolate_some = _interpolate_some
|
||||
|
||||
def _expandConfFilesWithLocal(filenames):
|
||||
"""Expands config files with local extension.
|
||||
"""
|
||||
newFilenames = []
|
||||
for filename in filenames:
|
||||
newFilenames.append(filename)
|
||||
localname = os.path.splitext(filename)[0] + '.local'
|
||||
if localname not in filenames and os.path.isfile(localname):
|
||||
newFilenames.append(localname)
|
||||
return newFilenames
|
||||
|
||||
# Gets the instance of the logger.
|
||||
logSys = getLogger(__name__)
|
||||
logLevel = 7
|
||||
|
@ -245,6 +256,7 @@ after = 1.conf
|
|||
def _getIncludes(self, filenames, seen=[]):
|
||||
if not isinstance(filenames, list):
|
||||
filenames = [ filenames ]
|
||||
filenames = _expandConfFilesWithLocal(filenames)
|
||||
# retrieve or cache include paths:
|
||||
if self._cfg_share:
|
||||
# cache/share include list:
|
||||
|
|
|
@ -28,7 +28,8 @@ import re
|
|||
import shutil
|
||||
import tempfile
|
||||
import unittest
|
||||
from ..client.configreader import ConfigReader, ConfigReaderUnshared, NoSectionError
|
||||
from ..client.configreader import ConfigReader, ConfigReaderUnshared, \
|
||||
DefinitionInitConfigReader, NoSectionError
|
||||
from ..client import configparserinc
|
||||
from ..client.jailreader import JailReader, extractOptions
|
||||
from ..client.filterreader import FilterReader
|
||||
|
@ -125,6 +126,54 @@ option = %s
|
|||
self._remove("c.d/90.conf")
|
||||
self.assertEqual(self._getoption(), 2)
|
||||
|
||||
def testLocalInIncludes(self):
|
||||
self._write("c.conf", value=None, content="""
|
||||
[INCLUDES]
|
||||
before = ib.conf
|
||||
after = ia.conf
|
||||
[Definition]
|
||||
test = %(default/test)s
|
||||
""")
|
||||
self._write("ib.conf", value=None, content="""
|
||||
[DEFAULT]
|
||||
test = A
|
||||
[Definition]
|
||||
option = 1
|
||||
""")
|
||||
self._write("ib.local", value=None, content="""
|
||||
[DEFAULT]
|
||||
test = B
|
||||
[Definition]
|
||||
option = 2
|
||||
""")
|
||||
self._write("ia.conf", value=None, content="""
|
||||
[DEFAULT]
|
||||
test = C
|
||||
[Definition]
|
||||
oafter = 3
|
||||
""")
|
||||
self._write("ia.local", value=None, content="""
|
||||
[DEFAULT]
|
||||
test = D
|
||||
[Definition]
|
||||
oafter = 4
|
||||
""")
|
||||
class TestDefConfReader(DefinitionInitConfigReader):
|
||||
_configOpts = {
|
||||
"option": ["int", None],
|
||||
"oafter": ["int", None],
|
||||
"test": ["string", None],
|
||||
}
|
||||
self.c = TestDefConfReader('c', 'option', {})
|
||||
self.c.setBaseDir(self.d)
|
||||
self.assertTrue(self.c.read())
|
||||
self.c.getOptions({}, all=True)
|
||||
o = self.c.getCombined()
|
||||
# test local wins (overwrite all options):
|
||||
self.assertEqual(o.get('option'), 2)
|
||||
self.assertEqual(o.get('oafter'), 4)
|
||||
self.assertEqual(o.get('test'), 'D')
|
||||
|
||||
def testInterpolations(self):
|
||||
self.assertFalse(self.c.read('i')) # nothing is there yet
|
||||
self._write("i.conf", value=None, content="""
|
||||
|
|
Loading…
Reference in New Issue