bug fix in the config readers: mixing with the init section should affect only own init options (from init section only bypass default section);

the situation details:
  value of "_daemon" from default section "default" (with init section) falsely overwrites it from definition section "test" -
  the resulting value of "_daemon" should be "test" in all 3 resulting failregex's (as specified in test.local),
  fixed and covered now;
additionally more complex cases covered also (all filter parameters in jail via "%(known/...)s", dynamical interpolation across all, etc);
pull/1726/head
sebres 8 years ago
parent 4f1473724b
commit 57e9c25449

@ -32,7 +32,7 @@ from ..helpers import getLogger
if sys.version_info >= (3,2):
# SafeConfigParser deprecated from Python 3.2 (renamed to ConfigParser)
from configparser import ConfigParser as SafeConfigParser, \
from configparser import ConfigParser as SafeConfigParser, NoSectionError, \
BasicInterpolation
# And interpolation of __name__ was simply removed, thus we need to
@ -60,7 +60,7 @@ if sys.version_info >= (3,2):
parser, option, accum, rest, section, map, depth)
else: # pragma: no cover
from ConfigParser import SafeConfigParser
from ConfigParser import SafeConfigParser, NoSectionError
# Gets the instance of the logger.
logSys = getLogger(__name__)
@ -200,6 +200,18 @@ after = 1.conf
def get_sections(self):
return self._sections
def options(self, section, onlyOwn=False):
"""Return a list of option names for the given section name."""
try:
opts = self._sections[section]
except KeyError:
raise NoSectionError(section)
if not onlyOwn:
# mix it with defaults:
return set(opts.keys()) | set(self._defaults)
# only own option names:
return opts.keys()
def read(self, filenames, get_includes=True):
if not isinstance(filenames, list):
filenames = [ filenames ]

@ -122,9 +122,9 @@ class ConfigReader():
if self._cfg is not None:
return self._cfg.merge_section(*args, **kwargs)
def options(self, *args):
def options(self, section, onlyOwn=False):
if self._cfg is not None:
return self._cfg.options(*args)
return self._cfg.options(section, onlyOwn)
return {}
def get(self, sec, opt, raw=False, vars={}):
@ -297,23 +297,35 @@ class DefinitionInitConfigReader(ConfigReader):
self._create_unshared(self._file)
return SafeConfigParserWithIncludes.read(self._cfg, self._file)
def getOptions(self, pOpts):
def getOptions(self, pOpts, all=False):
# overwrite static definition options with init values, supplied as
# direct parameters from jail-config via action[xtra1="...", xtra2=...]:
if not pOpts:
pOpts = dict()
if self._initOpts:
if not pOpts:
pOpts = dict()
pOpts = _merge_dicts(pOpts, self._initOpts)
self._opts = ConfigReader.getOptions(
self, "Definition", self._configOpts, pOpts)
self._pOpts = pOpts
if self.has_section("Init"):
for opt in self.options("Init"):
v = self.get("Init", opt)
if not opt.startswith('known/') and opt != '__name__':
# get only own options (without options from default):
getopt = lambda opt: self.get("Init", opt)
for opt in self.options("Init", onlyOwn=True):
if opt == '__name__': continue
v = None
if not opt.startswith('known/'):
if v is None: v = getopt(opt)
self._initOpts['known/'+opt] = v
if not opt in self._initOpts:
if opt not in self._initOpts:
if v is None: v = getopt(opt)
self._initOpts[opt] = v
if all and self.has_section("Definition"):
# merge with all definition options (and options from default),
# bypass already converted option (so merge only new options):
for opt in self.options("Definition"):
if opt == '__name__' or opt in self._opts: continue
self._opts[opt] = self.get("Definition", opt)
def _convert_to_boolean(self, value):
return value.lower() in ("1", "yes", "true", "on")
@ -336,12 +348,12 @@ class DefinitionInitConfigReader(ConfigReader):
def getCombined(self, ignore=()):
combinedopts = self._opts
ignore = set(ignore).copy()
if self._initOpts:
combinedopts = _merge_dicts(self._opts, self._initOpts)
combinedopts = _merge_dicts(combinedopts, self._initOpts)
if not len(combinedopts):
return {}
# ignore conditional options:
ignore = set(ignore).copy()
for n in combinedopts:
cond = SafeConfigParserWithIncludes.CONDITIONAL_RE.match(n)
if cond:

@ -139,11 +139,11 @@ class JailReader(ConfigReader):
filterName, self.__name, filterOpt,
share_config=self.share_config, basedir=self.getBaseDir())
ret = self.__filter.read()
# merge options from filter as 'known/...':
self.__filter.getOptions(self.__opts)
ConfigReader.merge_section(self, self.__name, self.__filter.getCombined(), 'known/')
if not ret:
raise JailDefError("Unable to read the filter %r" % filterName)
# merge options from filter as 'known/...' (all options unfiltered):
self.__filter.getOptions(self.__opts, all=True)
ConfigReader.merge_section(self, self.__name, self.__filter.getCombined(), 'known/')
else:
self.__filter = None
logSys.warning("No filter set for jail %s" % self.__name)

@ -1,6 +1,13 @@
#[INCLUDES]
#before = common.conf
[DEFAULT]
_daemon = default
[Definition]
failregex = failure test 1 (filter.d/test.conf) <HOST>
where = conf
failregex = failure <_daemon> <one> (filter.d/test.%(where)s) <HOST>
[Init]
# test parameter, should be overriden in jail by "filter=test[one=1,...]"
one = *1*

@ -2,6 +2,15 @@
#before = common.conf
[Definition]
# overwrite default daemon, additionally it should be accessible in jail with "%(known/_daemon)s":
_daemon = test
# interpolate previous regex (from test.conf) + new 2nd + dynamical substitution) of "two" an "where":
failregex = %(known/failregex)s
failure test 2 (filter.d/test.local) <HOST>
failure %(_daemon)s <two> (filter.d/test.<where>) <HOST>
# parameter "two" should be specified in jail by "filter=test[..., two=2]"
[Init]
# this parameter can be used in jail with "%(known/three)s":
three = 3
# this parameter "where" does not overwrite "where" in definition of test.conf (dynamical values only):
where = local

@ -15,9 +15,9 @@ ignoreip =
[test-known-interp]
enabled = true
filter = test
filter = test[one=1,two=2]
failregex = %(known/failregex)s
failure test 3 (jail.local) <HOST>
failure %(known/_daemon)s %(known/three)s (jail.local) <HOST>
[missinglogfiles]
enabled = true

Loading…
Cancel
Save