From 061d839a26b584af2a864449e09a56c5bb3efe5a Mon Sep 17 00:00:00 2001 From: Anton Arefiev Date: Thu, 11 Feb 2016 10:13:45 +0200 Subject: [PATCH] Add new condition: is-empty Now, if operators want to check some attribute isn't specified, they should use 'eq' condition with None, '', etc values: {'op': 'eq', 'field': 'inventory.bmc_addres', 'value': ''} It would be useful to have condition plugin witch verify this case, 'is-empty' checks that field is empty string, list, dict or None value: {'op': 'is-empty', 'field': 'inventory.bmc_addres'} Change-Id: I6596a067e769530092c3db34405e0f0917d2f052 --- doc/source/usage.rst | 5 ++++- ironic_inspector/plugins/rules.py | 7 +++++++ ironic_inspector/test/functional.py | 4 +++- ironic_inspector/test/test_plugins_rules.py | 20 +++++++++++++++++++ .../empty-condition-abc707b771be6be3.yaml | 4 ++++ setup.cfg | 1 + 6 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 releasenotes/notes/empty-condition-abc707b771be6be3.yaml diff --git a/doc/source/usage.rst b/doc/source/usage.rst index 607e27b79..c94b5f382 100644 --- a/doc/source/usage.rst +++ b/doc/source/usage.rst @@ -69,7 +69,10 @@ A condition is represented by an object with fields: * ``matches`` - requires a full match against a given regular expression; -* ``contains`` - requires a value to contain a given regular expression. +* ``contains`` - requires a value to contain a given regular expression; + +* ``is-empty`` - checks that field is an empty string, list, dict or + None value. ``field`` a `JSON path `_ to the field in the introspection data to use in comparison. diff --git a/ironic_inspector/plugins/rules.py b/ironic_inspector/plugins/rules.py index abc6521a7..84672ea5a 100644 --- a/ironic_inspector/plugins/rules.py +++ b/ironic_inspector/plugins/rules.py @@ -67,6 +67,13 @@ class NeCondition(SimpleCondition): op = operator.ne +class EmptyCondition(base.RuleConditionPlugin): + REQUIRED_PARAMS = set() + + def check(self, node_info, field, params, **kwargs): + return field in ('', None, [], {}) + + class NetCondition(base.RuleConditionPlugin): def validate(self, params, **kwargs): super(NetCondition, self).validate(params, **kwargs) diff --git a/ironic_inspector/test/functional.py b/ironic_inspector/test/functional.py index 17a7a1f2d..559599d37 100644 --- a/ironic_inspector/test/functional.py +++ b/ironic_inspector/test/functional.py @@ -94,7 +94,8 @@ class Base(base.NodeTest): 'bmc_address': self.bmc_address }, 'root_disk': {'name': '/dev/sda', 'model': 'Big Data Disk', - 'size': 1000 * units.Gi}, + 'size': 1000 * units.Gi, + 'wwn': None}, } self.data_old_ramdisk = { 'cpus': 4, @@ -308,6 +309,7 @@ class Test(Base): {'field': 'local_gb', 'op': 'lt', 'value': 1000}, {'field': 'local_gb', 'op': 'matches', 'value': '[0-9]+'}, {'field': 'cpu_arch', 'op': 'contains', 'value': '[0-9]+'}, + {'field': 'root_disk.wwn', 'op': 'is-empty'} ], 'actions': [ {'action': 'set-attribute', 'path': '/extra/foo', diff --git a/ironic_inspector/test/test_plugins_rules.py b/ironic_inspector/test/test_plugins_rules.py index 4a20e96b6..d26172737 100644 --- a/ironic_inspector/test/test_plugins_rules.py +++ b/ironic_inspector/test/test_plugins_rules.py @@ -115,6 +115,26 @@ class TestNetCondition(test_base.BaseTest): {'value': '192.0.2.1/24'})) +class TestEmptyCondition(test_base.BaseTest): + cond = rules_plugins.EmptyCondition() + + def test_check_none(self): + self.assertTrue(self.cond.check(None, None, {})) + self.assertFalse(self.cond.check(None, 0, {})) + + def test_check_empty_string(self): + self.assertTrue(self.cond.check(None, '', {})) + self.assertFalse(self.cond.check(None, '16', {})) + + def test_check_empty_list(self): + self.assertTrue(self.cond.check(None, [], {})) + self.assertFalse(self.cond.check(None, ['16'], {})) + + def test_check_empty_dict(self): + self.assertTrue(self.cond.check(None, {}, {})) + self.assertFalse(self.cond.check(None, {'test': '16'}, {})) + + class TestFailAction(test_base.BaseTest): act = rules_plugins.FailAction() diff --git a/releasenotes/notes/empty-condition-abc707b771be6be3.yaml b/releasenotes/notes/empty-condition-abc707b771be6be3.yaml new file mode 100644 index 000000000..5cf7a5318 --- /dev/null +++ b/releasenotes/notes/empty-condition-abc707b771be6be3.yaml @@ -0,0 +1,4 @@ +--- +features: + - Added new condition plugin "is-empty", which allows to match + empty string, list, dictionary or None. diff --git a/setup.cfg b/setup.cfg index 8a20f0455..733f17ff0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -45,6 +45,7 @@ ironic_inspector.rules.conditions = in-net = ironic_inspector.plugins.rules:NetCondition matches = ironic_inspector.plugins.rules:MatchesCondition contains = ironic_inspector.plugins.rules:ContainsCondition + is-empty = ironic_inspector.plugins.rules:EmptyCondition ironic_inspector.rules.actions = example = ironic_inspector.plugins.example:ExampleRuleAction fail = ironic_inspector.plugins.rules:FailAction