diff options
author | Jake Hunsaker <jhunsake@redhat.com> | 2019-08-17 18:11:23 -0400 |
---|---|---|
committer | Pavel Moravec <pmoravec@redhat.com> | 2019-08-25 12:52:15 +0200 |
commit | 51fbec1cc057908e549f4b83ba482959c09e08ab (patch) | |
tree | e3144f6ec4ed6c39ee5bd17243bafc19c53c2bd8 | |
parent | 0c83c8245ffab2ff3f568078651553f59ef475bb (diff) | |
download | sos-51fbec1cc057908e549f4b83ba482959c09e08ab.tar.gz |
[Plugin] Allow predicates to match any or all given items
Expands predicate evaluation to be able to evaluate True or False
depending on if any of the passed items are present (previous behavior)
or if _all_ the passed items need to be present. This is handled by
optionally passing a dict via the 'required' argument to SoSPredicate.
The keys in this dict are items supported by SoSPredicate (currently
'kmods' and 'services'), with values being either 'any' or 'all'.
Both kmods and services can be passed to the same predicate to allow
fine-grained control over if a command should be collected.
The default behavior remains the same, meaning that both 'kmods' and
'services' are set to 'any' for the required dict. For example,
creating a predicate like the following:
SoSPredicate(self, kmods=['foo', 'bar'], services=['oof', 'rab'])
implies "required={'kmods': 'any', 'services': 'any'}" and thus as long
as either kmods _and_ either of the services exist, the predicate
evaluates True. If, for example, neither of the kmods are present, the
predicate will evaluate False.
Providing a predicate like the following however, will require _both_
kmods to be present and either of the services to evaluate True. If
either kmods are not present, and --allow-system-changes is not set by
the end user, this predicate will evaluate False:
SoSPredicate(self, kmods=['foo', 'bar'], services=['oof', 'rab'],
required={'kmods': 'all'})
Further, --allow-system-changes is handled directly in predicate
evaluation for kmods, meaning individual plugins (like networking) do
not need to separately check for if this flag is set or not. However,
they will still need to specify 'changes=True' to the add_cmd_ouput()
call if the intent is for the warning message that gets logged to
include a mention about using --allow-system-changes.
Fixes: #1755
Signed-off-by: Jake Hunsaker <jhunsake@redhat.com>
Signed-off-by: Pavel Moravec <pmoravec@redhat.com>
-rw-r--r-- | sos/plugins/__init__.py | 45 |
1 files changed, 32 insertions, 13 deletions
diff --git a/sos/plugins/__init__.py b/sos/plugins/__init__.py index 428b7a0c..d08a20e0 100644 --- a/sos/plugins/__init__.py +++ b/sos/plugins/__init__.py @@ -147,34 +147,53 @@ class SoSPredicate(object): """ return self.__str(quote=True, prefix="SoSPredicate(", suffix=")") - def __nonzero__(self): - """Predicate evaluation hook. - """ - pvalue = False - - # Allow loading kernel modules? - pvalue |= self._owner.get_option("allow_system_changes") + def _eval_kmods(self): + if not self.kmods or self._owner.get_option('allow_system_changes'): + return True # Are kernel modules loaded? - for k in self.kmods: - pvalue |= self._owner.is_module_loaded(k) + _kmods = [self._owner.is_module_loaded(k) for k in self.kmods] + + if self.required['kmods'] == 'any': + return any(_kmods) + else: + return all(_kmods) + + def _eval_services(self): + if not self.services: + return True + + _svcs = [self._owner.service_is_running(s) for s in self.services] + + if self.required['services'] == 'any': + return any(_svcs) + else: + return all(_svcs) - for s in self.services: - pvalue |= self._owner.service_is_running(s) + def __nonzero__(self): + """Predicate evaluation hook. + """ # Null predicate? if not any([self.kmods, self.services, self.dry_run]): return True - return pvalue and not self.dry_run + return ((self._eval_kmods() and self._eval_services()) and not + self.dry_run) - def __init__(self, owner, dry_run=False, kmods=[], services=[]): + def __init__(self, owner, dry_run=False, kmods=[], services=[], + required={}): """Initialise a new SoSPredicate object. """ self._owner = owner self.kmods = list(kmods) self.services = list(services) self.dry_run = dry_run | self._owner.commons['cmdlineopts'].dry_run + self.required = {'kmods': 'any', 'services': 'any'} + self.required.update({ + k: v for k, v in required.items() if + required[k] != self.required[k] + }) class SoSCommand(object): |