From a0ad62c4f290cc3b762058c1647c91dd34c14891 Mon Sep 17 00:00:00 2001 From: Adam Goldsmith Date: Sat, 11 Mar 2023 00:55:38 -0500 Subject: [PATCH] Allow negating an attribute filter --- check_home_assistant_state.py | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/check_home_assistant_state.py b/check_home_assistant_state.py index 164d706..c468151 100755 --- a/check_home_assistant_state.py +++ b/check_home_assistant_state.py @@ -46,13 +46,31 @@ class ScalarOrUnknownContext(nagiosplugin.ScalarContext): ) +@dataclasses.dataclass +class AttributeFilter: + attribute: str + value: str + negated: bool + + @classmethod + def from_str(cls, arg: str): + k, _, v = arg.partition("=") + if k.endswith("!"): + return cls(k.removesuffix("!"), v, True) + else: + return cls(k, v, False) + + def check(self, attributes: dict[str, str]) -> bool: + return self.negated ^ (attributes.get(self.attribute) == self.value) + + @dataclasses.dataclass class Entities(nagiosplugin.Resource): url: str token: str device_class: str numeric: bool - filters: list[str] + filters: list[AttributeFilter] attribute: Optional[str] friendly_name: bool ignore_missing: bool @@ -122,7 +140,7 @@ class Entities(nagiosplugin.Resource): for state in response: if ( state["attributes"].get("device_class") == self.device_class - and all(state["attributes"].get(k) == v for k, v in self.filters) + and all(filter.check(state["attributes"]) for filter in self.filters) and (len(self.include) == 0 or state["entity_id"] in self.include) and state["entity_id"] not in self.exclude ): @@ -169,11 +187,6 @@ class RegexContext(nagiosplugin.Context): ) -def key_value(arg: str): - k, _, v = arg.partition("=") - return k, v - - class Icinga2ConfAction(argparse.Action): def __init__( self, @@ -302,10 +315,10 @@ def main(): common_args.add_argument( "-f", "--filter", - type=key_value, + type=AttributeFilter.from_str, default=[], nargs="*", - help="filter by 'attribute=value' (may be specified multiple times)", + help="filter by 'attribute=value' (may be specified multiple times). Use != to negate the match", ) common_args.add_argument( "-i",