aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJake Hunsaker <jhunsake@redhat.com>2019-08-17 18:11:23 -0400
committerPavel Moravec <pmoravec@redhat.com>2019-08-25 12:52:15 +0200
commit51fbec1cc057908e549f4b83ba482959c09e08ab (patch)
treee3144f6ec4ed6c39ee5bd17243bafc19c53c2bd8
parent0c83c8245ffab2ff3f568078651553f59ef475bb (diff)
downloadsos-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__.py45
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):