From 3d762f7800962d1b175bebf00880bab54c563502 Mon Sep 17 00:00:00 2001 From: "Bradley A. Thornton" Date: Fri, 30 Oct 2020 14:36:30 -0700 Subject: [PATCH] CI cleanup (#23) CI cleanup Reviewed-by: https://github.com/apps/ansible-zuul --- .../fragments/23 linting and formatting.yaml | 3 + changelogs/fragments/add_fact_diff.yaml | 4 +- changelogs/fragments/test_ci.yaml | 3 - changelogs/fragments/validate.yaml | 3 + plugins/action/validate.py | 4 +- plugins/module_utils/validate/base.py | 6 +- plugins/test/validate.py | 2 +- plugins/validate/jsonschema.py | 22 ++- tests/unit/plugins/action/test_fact_diff.py | 6 +- tests/unit/plugins/action/test_update_fact.py | 7 +- tests/unit/plugins/action/test_validate.py | 171 +++++++++--------- tests/unit/plugins/filter/test_validate.py | 143 +++++++-------- tests/unit/plugins/lookup/test_validate.py | 150 +++++++-------- tests/unit/plugins/test/test_validate.py | 158 ++++++++-------- tests/unit/requirements.txt | 1 + 15 files changed, 339 insertions(+), 344 deletions(-) create mode 100644 changelogs/fragments/23 linting and formatting.yaml delete mode 100644 changelogs/fragments/test_ci.yaml diff --git a/changelogs/fragments/23 linting and formatting.yaml b/changelogs/fragments/23 linting and formatting.yaml new file mode 100644 index 0000000..7b9d8c2 --- /dev/null +++ b/changelogs/fragments/23 linting and formatting.yaml @@ -0,0 +1,3 @@ +--- +bugfixes: + - linting and formatting for CI diff --git a/changelogs/fragments/add_fact_diff.yaml b/changelogs/fragments/add_fact_diff.yaml index d91d589..94af7bb 100644 --- a/changelogs/fragments/add_fact_diff.yaml +++ b/changelogs/fragments/add_fact_diff.yaml @@ -1,3 +1,3 @@ --- -major_changes: - - Added validate module/lookup/filter/test plugin to validate data based on given criteria +minor_changes: + - Added fact_diff plugin and sub plugin diff --git a/changelogs/fragments/test_ci.yaml b/changelogs/fragments/test_ci.yaml deleted file mode 100644 index 47e2100..0000000 --- a/changelogs/fragments/test_ci.yaml +++ /dev/null @@ -1,3 +0,0 @@ ---- -major_changes: - - test ci. diff --git a/changelogs/fragments/validate.yaml b/changelogs/fragments/validate.yaml index e69de29..5a7307b 100644 --- a/changelogs/fragments/validate.yaml +++ b/changelogs/fragments/validate.yaml @@ -0,0 +1,3 @@ +--- +minor_changes: + - Added validate module/lookup/filter/test plugin to validate data based on given criteria diff --git a/plugins/action/validate.py b/plugins/action/validate.py index 91ccc83..6569c67 100644 --- a/plugins/action/validate.py +++ b/plugins/action/validate.py @@ -68,7 +68,9 @@ class ActionModule(ActionBase): return argspec_result self._task_vars = task_vars - self._playhost = task_vars.get("inventory_hostname") if task_vars else None + self._playhost = ( + task_vars.get("inventory_hostname") if task_vars else None + ) self._validator_engine, validator_result = load_validator( engine=updated_params["engine"], diff --git a/plugins/module_utils/validate/base.py b/plugins/module_utils/validate/base.py index b80b53b..b3fa85e 100644 --- a/plugins/module_utils/validate/base.py +++ b/plugins/module_utils/validate/base.py @@ -40,10 +40,8 @@ def load_validator( return None, result cref = dict(zip(["corg", "cname", "plugin"], engine.split("."))) - validatorlib = ( - "ansible_collections.{corg}.{cname}.plugins.validate.{plugin}".format( - **cref - ) + validatorlib = "ansible_collections.{corg}.{cname}.plugins.validate.{plugin}".format( + **cref ) try: diff --git a/plugins/test/validate.py b/plugins/test/validate.py index 6a5f06c..8ff73af 100644 --- a/plugins/test/validate.py +++ b/plugins/test/validate.py @@ -147,7 +147,7 @@ def validate(*args, **kwargs): class TestModule(object): """data validation test""" - # For testing + test_map = {"validate": validate} def tests(self): diff --git a/plugins/validate/jsonschema.py b/plugins/validate/jsonschema.py index 458037b..cd36485 100644 --- a/plugins/validate/jsonschema.py +++ b/plugins/validate/jsonschema.py @@ -46,12 +46,20 @@ from ansible.module_utils.basic import missing_required_lib from ansible.errors import AnsibleError from ansible.module_utils.six import string_types -from ansible_collections.ansible.utils.plugins.validate._base import ValidateBase +from ansible_collections.ansible.utils.plugins.validate._base import ( + ValidateBase, +) from ansible_collections.ansible.utils.plugins.module_utils.common.utils import ( to_list, ) +# PY2 compatiblilty for JSONDecodeError +try: + from json.decoder import JSONDecodeError +except ImportError: + JSONDecodeError = ValueError + try: import jsonschema @@ -100,7 +108,7 @@ class Validate(ValidateBase): ) raise AnsibleError(msg) - except (TypeError, json.decoder.JSONDecodeError) as exe: + except (TypeError, JSONDecodeError) as exe: msg = ( "'data' option value is invalid, value should of type dict or str format of dict." " Failed to read with error '{err}'".format( @@ -123,7 +131,7 @@ class Validate(ValidateBase): raise AnsibleError(msg) self._criteria = criteria - except (TypeError, json.decoder.JSONDecodeError) as exe: + except (TypeError, JSONDecodeError) as exe: msg = ( "'criteria' option value is invalid, value should of type dict or str format of dict." " Failed to read with error '{err}'".format( @@ -200,11 +208,9 @@ class Validate(ValidateBase): "found": validation_error.instance, } self._result["errors"].append(error) - error_message = ( - "At '{schema_path}' {message}. ".format( - schema_path=error["schema_path"], - message=error["message"], - ) + error_message = "At '{schema_path}' {message}. ".format( + schema_path=error["schema_path"], + message=error["message"], ) error_messages.append(error_message) if error_messages: diff --git a/tests/unit/plugins/action/test_fact_diff.py b/tests/unit/plugins/action/test_fact_diff.py index f9807d3..14080da 100644 --- a/tests/unit/plugins/action/test_fact_diff.py +++ b/tests/unit/plugins/action/test_fact_diff.py @@ -9,7 +9,6 @@ __metaclass__ = type import re import unittest -from mock import MagicMock from ansible.playbook.task import Task from ansible.template import Templar @@ -17,6 +16,11 @@ from ansible_collections.ansible.utils.plugins.action.fact_diff import ( ActionModule, ) +try: + from unittest.mock import MagicMock # pylint:disable=syntax-error +except ImportError: + from mock import MagicMock + class TestUpdate_Fact(unittest.TestCase): def setUp(self): diff --git a/tests/unit/plugins/action/test_update_fact.py b/tests/unit/plugins/action/test_update_fact.py index 1abdc42..9d17c9f 100644 --- a/tests/unit/plugins/action/test_update_fact.py +++ b/tests/unit/plugins/action/test_update_fact.py @@ -10,7 +10,6 @@ __metaclass__ = type import copy import unittest from jinja2 import Template, TemplateSyntaxError -from mock import MagicMock from ansible.playbook.task import Task from ansible.template import Templar @@ -18,6 +17,12 @@ from ansible_collections.ansible.utils.plugins.action.update_fact import ( ActionModule, ) +try: + from unittest.mock import MagicMock # pylint:disable=syntax-error +except ImportError: + from mock import MagicMock + + VALID_DATA = { "a": { "b": {"4.4": [{"1": {5: {"foo": 123}}}], 5.5: "float5.5"}, diff --git a/tests/unit/plugins/action/test_validate.py b/tests/unit/plugins/action/test_validate.py index 1e25d30..98fc25e 100644 --- a/tests/unit/plugins/action/test_validate.py +++ b/tests/unit/plugins/action/test_validate.py @@ -7,10 +7,7 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type -import copy import unittest -from jinja2 import Template, TemplateSyntaxError -from mock import MagicMock from ansible.playbook.task import Task from ansible.template import Templar from ansible.errors import AnsibleActionFail @@ -19,91 +16,76 @@ from ansible_collections.ansible.utils.plugins.action.validate import ( ActionModule, ) +try: + from unittest.mock import MagicMock # pylint:disable=syntax-error +except ImportError: + from mock import MagicMock + + DATA = { - "GigabitEthernet0/0/0/0": { - "auto_negotiate": False, - "counters": { - "in_crc_errors": 0, - "in_errors": 0, - "rate": { - "in_rate": 0, - "out_rate": 0 - } + "GigabitEthernet0/0/0/0": { + "auto_negotiate": False, + "counters": { + "in_crc_errors": 0, + "in_errors": 0, + "rate": {"in_rate": 0, "out_rate": 0}, + }, + "description": "configured using Ansible", + "duplex_mode": "full", + "enabled": True, + "line_protocol": "up", + "mtu": 1514, + "oper_status": "down", + "type": "GigabitEthernet", }, - "description": "configured using Ansible", - "duplex_mode": "full", - "enabled": True, - "line_protocol": "up", - "mtu": 1514, - "oper_status": "down", - "type": "GigabitEthernet" - }, - "GigabitEthernet0/0/0/1": { - "auto_negotiate": False, - "counters": { - "in_crc_errors": 10, - "in_errors": 0, - "rate": { - "in_rate": 0, - "out_rate": 0 - } + "GigabitEthernet0/0/0/1": { + "auto_negotiate": False, + "counters": { + "in_crc_errors": 10, + "in_errors": 0, + "rate": {"in_rate": 0, "out_rate": 0}, + }, + "description": "# interface is configures with Ansible", + "duplex_mode": "full", + "enabled": False, + "line_protocol": "up", + "mtu": 1514, + "oper_status": "up", + "type": "GigabitEthernet", }, - "description": "# interface is configures with Ansible", - "duplex_mode": "full", - "enabled": False, - "line_protocol": "up", - "mtu": 1514, - "oper_status": "up", - "type": "GigabitEthernet" - } } CRITERIA_CRC_ERROR_CHECK = { - "type" : "object", + "type": "object", "patternProperties": { "^.*": { "type": "object", "properties": { "counters": { "properties": { - "in_crc_errors": { - "type": "number", - "maximum": 0 - } + "in_crc_errors": {"type": "number", "maximum": 0} } } - } + }, } - } + }, } CRITERIA_ENABLED_CHECK = { - "type" : "object", + "type": "object", "patternProperties": { - "^.*": { - "type": "object", - "properties": { - "enabled": { - "enum": [True] - } - } - } - } + "^.*": {"type": "object", "properties": {"enabled": {"enum": [True]}}} + }, } CRITERIA_OPER_STATUS_UP_CHECK = { - "type" : "object", + "type": "object", "patternProperties": { "^.*": { "type": "object", - "properties": { - "oper_status": { - "type": "string", - "pattern": "up" - } - } + "properties": {"oper_status": {"type": "string", "pattern": "up"}}, } - } + }, } CRITERIA_IN_RATE_CHECK = { @@ -115,18 +97,15 @@ CRITERIA_IN_RATE_CHECK = { "counters": { "properties": { "rate": { - "properties": { - "in_rate": { - "type": "number", - "maximum": 0 + "properties": { + "in_rate": {"type": "number", "maximum": 0} } - } } } } - } + }, } - } + }, } @@ -154,41 +133,48 @@ class TestValidate(unittest.TestCase): # missing required arguments self._plugin._task.args = {"engine": "ansible.utils.jsonschema"} result = self._plugin.run(task_vars=None) - self.assertIn("missing required arguments: criteria", result["errors"]) + msg = "missing required arguments criteria data" + for word in msg.split(): + self.assertIn(word, result["errors"]) # invalid engine option value self._plugin._task.args = { "engine": "ansible.utils.sample", "data": DATA, - "criteria": CRITERIA_OPER_STATUS_UP_CHECK + "criteria": CRITERIA_OPER_STATUS_UP_CHECK, } result = self._plugin.run(task_vars=None) - self.assertIn("For engine 'ansible.utils.sample' error loading the corresponding validate plugin", result["msg"]) + self.assertIn( + "For engine 'ansible.utils.sample' error loading the corresponding validate plugin", + result["msg"], + ) # invalid data option value self._plugin._task.args = { "engine": "ansible.utils.jsonschema", "data": "invalid data", - "criteria": CRITERIA_OPER_STATUS_UP_CHECK + "criteria": CRITERIA_OPER_STATUS_UP_CHECK, } with self.assertRaises(AnsibleActionFail) as error: self._plugin.run(task_vars=None) self.assertIn( - "'data' option value is invalid, value should of type dict or str format of dict", str(error.exception) + "'data' option value is invalid, value should of type dict or str format of dict", + str(error.exception), ) # invalid criteria option value self._plugin._task.args = { "engine": "ansible.utils.jsonschema", "data": DATA, - "criteria": "invalid criteria" + "criteria": "invalid criteria", } with self.assertRaises(AnsibleActionFail) as error: self._plugin.run(task_vars=None) self.assertIn( - "'criteria' option value is invalid, value should of type dict or str format of dict", str(error.exception) + "'criteria' option value is invalid, value should of type dict or str format of dict", + str(error.exception), ) def test_invalid_validate_plugin_config_options(self): @@ -197,11 +183,16 @@ class TestValidate(unittest.TestCase): self._plugin._task.args = { "engine": "ansible.utils.jsonschema", "data": DATA, - "criteria": CRITERIA_IN_RATE_CHECK + "criteria": CRITERIA_IN_RATE_CHECK, } - result = self._plugin.run(task_vars={'ansible_validate_jsonschema_draft': 'draft0'}) - self.assertIn("value of draft must be one of: draft3, draft4, draft6, draft7, got: draft0", result["msg"]) + result = self._plugin.run( + task_vars={"ansible_validate_jsonschema_draft": "draft0"} + ) + self.assertIn( + "value of draft must be one of: draft3, draft4, draft6, draft7, got: draft0", + result["msg"], + ) def test_invalid_data(self): """Check passing invalid data as per criteria""" @@ -209,13 +200,25 @@ class TestValidate(unittest.TestCase): self._plugin._task.args = { "engine": "ansible.utils.jsonschema", "data": DATA, - "criteria": [CRITERIA_CRC_ERROR_CHECK, CRITERIA_ENABLED_CHECK, CRITERIA_OPER_STATUS_UP_CHECK] + "criteria": [ + CRITERIA_CRC_ERROR_CHECK, + CRITERIA_ENABLED_CHECK, + CRITERIA_OPER_STATUS_UP_CHECK, + ], } result = self._plugin.run(task_vars=None) - self.assertIn("patternProperties.^.*.properties.counters.properties.in_crc_errors.maximum", result["msg"]) - self.assertIn("patternProperties.^.*.properties.enabled.enum", result["msg"]) - self.assertIn("'patternProperties.^.*.properties.oper_status.pattern", result["msg"]) + self.assertIn( + "patternProperties.^.*.properties.counters.properties.in_crc_errors.maximum", + result["msg"], + ) + self.assertIn( + "patternProperties.^.*.properties.enabled.enum", result["msg"] + ) + self.assertIn( + "'patternProperties.^.*.properties.oper_status.pattern", + result["msg"], + ) def test_valid_data(self): """Check passing valid data as per criteria""" @@ -223,7 +226,7 @@ class TestValidate(unittest.TestCase): self._plugin._task.args = { "engine": "ansible.utils.jsonschema", "data": DATA, - "criteria": CRITERIA_IN_RATE_CHECK + "criteria": CRITERIA_IN_RATE_CHECK, } result = self._plugin.run(task_vars=None) diff --git a/tests/unit/plugins/filter/test_validate.py b/tests/unit/plugins/filter/test_validate.py index 4adc65b..f9251f7 100644 --- a/tests/unit/plugins/filter/test_validate.py +++ b/tests/unit/plugins/filter/test_validate.py @@ -13,90 +13,69 @@ from ansible.errors import AnsibleFilterError from ansible_collections.ansible.utils.plugins.filter.validate import validate DATA = { - "GigabitEthernet0/0/0/0": { - "auto_negotiate": False, - "counters": { - "in_crc_errors": 0, - "in_errors": 0, - "rate": { - "in_rate": 0, - "out_rate": 0 - } + "GigabitEthernet0/0/0/0": { + "auto_negotiate": False, + "counters": { + "in_crc_errors": 0, + "in_errors": 0, + "rate": {"in_rate": 0, "out_rate": 0}, + }, + "description": "configured using Ansible", + "duplex_mode": "full", + "enabled": True, + "line_protocol": "up", + "mtu": 1514, + "oper_status": "down", + "type": "GigabitEthernet", }, - "description": "configured using Ansible", - "duplex_mode": "full", - "enabled": True, - "line_protocol": "up", - "mtu": 1514, - "oper_status": "down", - "type": "GigabitEthernet" - }, - "GigabitEthernet0/0/0/1": { - "auto_negotiate": False, - "counters": { - "in_crc_errors": 10, - "in_errors": 0, - "rate": { - "in_rate": 0, - "out_rate": 0 - } + "GigabitEthernet0/0/0/1": { + "auto_negotiate": False, + "counters": { + "in_crc_errors": 10, + "in_errors": 0, + "rate": {"in_rate": 0, "out_rate": 0}, + }, + "description": "# interface is configures with Ansible", + "duplex_mode": "full", + "enabled": False, + "line_protocol": "up", + "mtu": 1514, + "oper_status": "up", + "type": "GigabitEthernet", }, - "description": "# interface is configures with Ansible", - "duplex_mode": "full", - "enabled": False, - "line_protocol": "up", - "mtu": 1514, - "oper_status": "up", - "type": "GigabitEthernet" - } } CRITERIA_CRC_ERROR_CHECK = { - "type" : "object", + "type": "object", "patternProperties": { "^.*": { "type": "object", "properties": { "counters": { "properties": { - "in_crc_errors": { - "type": "number", - "maximum": 0 - } + "in_crc_errors": {"type": "number", "maximum": 0} } } - } + }, } - } + }, } CRITERIA_ENABLED_CHECK = { - "type" : "object", + "type": "object", "patternProperties": { - "^.*": { - "type": "object", - "properties": { - "enabled": { - "enum": [True] - } - } - } - } + "^.*": {"type": "object", "properties": {"enabled": {"enum": [True]}}} + }, } CRITERIA_OPER_STATUS_UP_CHECK = { - "type" : "object", + "type": "object", "patternProperties": { "^.*": { "type": "object", - "properties": { - "oper_status": { - "type": "string", - "pattern": "up" - } - } + "properties": {"oper_status": {"type": "string", "pattern": "up"}}, } - } + }, } CRITERIA_IN_RATE_CHECK = { @@ -108,18 +87,15 @@ CRITERIA_IN_RATE_CHECK = { "counters": { "properties": { "rate": { - "properties": { - "in_rate": { - "type": "number", - "maximum": 0 + "properties": { + "in_rate": {"type": "number", "maximum": 0} } - } } } } - } + }, } - } + }, } @@ -136,34 +112,35 @@ class TestValidate(unittest.TestCase): with self.assertRaises(AnsibleFilterError) as error: validate(*args, **kwargs) self.assertIn( - "Missing either 'data' or 'criteria' value in filter input, refer 'ansible.utils.validate' filter", str(error.exception) + "Missing either 'data' or 'criteria' value in filter input, refer 'ansible.utils.validate' filter", + str(error.exception), ) # missing required arguments with self.assertRaises(AnsibleFilterError) as error: validate([DATA], {}) self.assertIn( - "Expected value of 'data' option is either dict or str, received type", str(error.exception) + "Expected value of 'data' option is either dict or str, received type", + str(error.exception), ) args = [DATA, [CRITERIA_IN_RATE_CHECK]] - kwargs = {'engine': 'ansible.utils.sample'} + kwargs = {"engine": "ansible.utils.sample"} with self.assertRaises(AnsibleFilterError) as error: validate(*args, **kwargs) self.assertIn( - "For engine 'ansible.utils.sample' error loading", str(error.exception) + "For engine 'ansible.utils.sample' error loading", + str(error.exception), ) args = ["invalid data", [CRITERIA_IN_RATE_CHECK]] - kwargs = {'engine': 'ansible.utils.jsonschema'} + kwargs = {"engine": "ansible.utils.jsonschema"} with self.assertRaises(AnsibleFilterError) as error: validate(*args, **kwargs) - self.assertIn( - "'data' option value is invalid", str(error.exception) - ) + self.assertIn("'data' option value is invalid", str(error.exception)) args = [DATA, "invalid criteria"] - kwargs = {'engine': 'ansible.utils.jsonschema'} + kwargs = {"engine": "ansible.utils.jsonschema"} with self.assertRaises(AnsibleFilterError) as error: validate(*args, **kwargs) self.assertIn( @@ -173,18 +150,26 @@ class TestValidate(unittest.TestCase): def test_invalid_validate_plugin_config_options(self): """Check passing invalid validate plugin options""" - args = [DATA, [CRITERIA_CRC_ERROR_CHECK, CRITERIA_ENABLED_CHECK, CRITERIA_OPER_STATUS_UP_CHECK]] - kwargs = {'engine': 'ansible.utils.jsonschema', 'draft': 'draft0'} + args = [ + DATA, + [ + CRITERIA_CRC_ERROR_CHECK, + CRITERIA_ENABLED_CHECK, + CRITERIA_OPER_STATUS_UP_CHECK, + ], + ] + kwargs = {"engine": "ansible.utils.jsonschema", "draft": "draft0"} with self.assertRaises(AnsibleFilterError) as error: validate(*args, **kwargs) self.assertIn( - "value of draft must be one of: draft3, draft4, draft6, draft7, got: draft0", str(error.exception) + "value of draft must be one of: draft3, draft4, draft6, draft7, got: draft0", + str(error.exception), ) def test_valid_data(self): """Check passing valid data as per criteria""" args = [DATA, CRITERIA_IN_RATE_CHECK] - kwargs = {'engine': 'ansible.utils.jsonschema'} + kwargs = {"engine": "ansible.utils.jsonschema"} result = validate(*args, **kwargs) self.assertEqual(result, []) diff --git a/tests/unit/plugins/lookup/test_validate.py b/tests/unit/plugins/lookup/test_validate.py index e051c3b..16a54a0 100644 --- a/tests/unit/plugins/lookup/test_validate.py +++ b/tests/unit/plugins/lookup/test_validate.py @@ -10,93 +10,74 @@ __metaclass__ = type import unittest from ansible.errors import AnsibleLookupError -from ansible_collections.ansible.utils.plugins.lookup.validate import LookupModule +from ansible_collections.ansible.utils.plugins.lookup.validate import ( + LookupModule, +) DATA = { - "GigabitEthernet0/0/0/0": { - "auto_negotiate": False, - "counters": { - "in_crc_errors": 0, - "in_errors": 0, - "rate": { - "in_rate": 0, - "out_rate": 0 - } + "GigabitEthernet0/0/0/0": { + "auto_negotiate": False, + "counters": { + "in_crc_errors": 0, + "in_errors": 0, + "rate": {"in_rate": 0, "out_rate": 0}, + }, + "description": "configured using Ansible", + "duplex_mode": "full", + "enabled": True, + "line_protocol": "up", + "mtu": 1514, + "oper_status": "down", + "type": "GigabitEthernet", }, - "description": "configured using Ansible", - "duplex_mode": "full", - "enabled": True, - "line_protocol": "up", - "mtu": 1514, - "oper_status": "down", - "type": "GigabitEthernet" - }, - "GigabitEthernet0/0/0/1": { - "auto_negotiate": False, - "counters": { - "in_crc_errors": 10, - "in_errors": 0, - "rate": { - "in_rate": 0, - "out_rate": 0 - } + "GigabitEthernet0/0/0/1": { + "auto_negotiate": False, + "counters": { + "in_crc_errors": 10, + "in_errors": 0, + "rate": {"in_rate": 0, "out_rate": 0}, + }, + "description": "# interface is configures with Ansible", + "duplex_mode": "full", + "enabled": False, + "line_protocol": "up", + "mtu": 1514, + "oper_status": "up", + "type": "GigabitEthernet", }, - "description": "# interface is configures with Ansible", - "duplex_mode": "full", - "enabled": False, - "line_protocol": "up", - "mtu": 1514, - "oper_status": "up", - "type": "GigabitEthernet" - } } CRITERIA_CRC_ERROR_CHECK = { - "type" : "object", + "type": "object", "patternProperties": { "^.*": { "type": "object", "properties": { "counters": { "properties": { - "in_crc_errors": { - "type": "number", - "maximum": 0 - } + "in_crc_errors": {"type": "number", "maximum": 0} } } - } + }, } - } + }, } CRITERIA_ENABLED_CHECK = { - "type" : "object", + "type": "object", "patternProperties": { - "^.*": { - "type": "object", - "properties": { - "enabled": { - "enum": [True] - } - } - } - } + "^.*": {"type": "object", "properties": {"enabled": {"enum": [True]}}} + }, } CRITERIA_OPER_STATUS_UP_CHECK = { - "type" : "object", + "type": "object", "patternProperties": { "^.*": { "type": "object", - "properties": { - "oper_status": { - "type": "string", - "pattern": "up" - } - } + "properties": {"oper_status": {"type": "string", "pattern": "up"}}, } - } + }, } CRITERIA_IN_RATE_CHECK = { @@ -108,18 +89,15 @@ CRITERIA_IN_RATE_CHECK = { "counters": { "properties": { "rate": { - "properties": { - "in_rate": { - "type": "number", - "maximum": 0 + "properties": { + "in_rate": {"type": "number", "maximum": 0} } - } } } } - } + }, } - } + }, } @@ -138,25 +116,24 @@ class TestValidate(unittest.TestCase): ) terms = [DATA, [CRITERIA_IN_RATE_CHECK]] - kwargs = {'engine': 'ansible.utils.sample'} + kwargs = {"engine": "ansible.utils.sample"} variables = {} with self.assertRaises(AnsibleLookupError) as error: self._lp.run(terms, variables, **kwargs) self.assertIn( - "For engine 'ansible.utils.sample' error loading", str(error.exception) + "For engine 'ansible.utils.sample' error loading", + str(error.exception), ) terms = ["invalid data", [CRITERIA_IN_RATE_CHECK]] - kwargs = {'engine': 'ansible.utils.jsonschema'} + kwargs = {"engine": "ansible.utils.jsonschema"} variables = {} with self.assertRaises(AnsibleLookupError) as error: self._lp.run(terms, variables, **kwargs) - self.assertIn( - "'data' option value is invalid", str(error.exception) - ) + self.assertIn("'data' option value is invalid", str(error.exception)) terms = [DATA, "invalid criteria"] - kwargs = {'engine': 'ansible.utils.jsonschema'} + kwargs = {"engine": "ansible.utils.jsonschema"} variables = {} with self.assertRaises(AnsibleLookupError) as error: self._lp.run(terms, variables, **kwargs) @@ -167,20 +144,31 @@ class TestValidate(unittest.TestCase): def test_invalid_validate_plugin_config_options(self): """Check passing invalid validate plugin options""" - terms = [DATA, [CRITERIA_CRC_ERROR_CHECK, CRITERIA_ENABLED_CHECK, CRITERIA_OPER_STATUS_UP_CHECK]] - kwargs = {'engine': 'ansible.utils.jsonschema'} + terms = [ + DATA, + [ + CRITERIA_CRC_ERROR_CHECK, + CRITERIA_ENABLED_CHECK, + CRITERIA_OPER_STATUS_UP_CHECK, + ], + ] + kwargs = {"engine": "ansible.utils.jsonschema"} variables = {} result = self._lp.run(terms, variables, **kwargs) - self.assertIn("GigabitEthernet0/0/0/1.counters.in_crc_errors", result[0]['data_path']) - self.assertIn("GigabitEthernet0/0/0/1.enabled", result[1]['data_path']) - self.assertIn("GigabitEthernet0/0/0/0.oper_status", result[2]['data_path']) + self.assertIn( + "GigabitEthernet0/0/0/1.counters.in_crc_errors", + result[0]["data_path"], + ) + self.assertIn("GigabitEthernet0/0/0/1.enabled", result[1]["data_path"]) + self.assertIn( + "GigabitEthernet0/0/0/0.oper_status", result[2]["data_path"] + ) def test_valid_data(self): """Check passing valid data as per criteria""" terms = [DATA, CRITERIA_IN_RATE_CHECK] - kwargs = {'engine': 'ansible.utils.jsonschema'} + kwargs = {"engine": "ansible.utils.jsonschema"} variables = {} result = self._lp.run(terms, variables, **kwargs) self.assertEqual(result, []) - diff --git a/tests/unit/plugins/test/test_validate.py b/tests/unit/plugins/test/test_validate.py index 0459cc0..63fef9b 100644 --- a/tests/unit/plugins/test/test_validate.py +++ b/tests/unit/plugins/test/test_validate.py @@ -13,90 +13,69 @@ from ansible.errors import AnsibleError from ansible_collections.ansible.utils.plugins.test.validate import validate DATA = { - "GigabitEthernet0/0/0/0": { - "auto_negotiate": False, - "counters": { - "in_crc_errors": 0, - "in_errors": 0, - "rate": { - "in_rate": 0, - "out_rate": 0 - } + "GigabitEthernet0/0/0/0": { + "auto_negotiate": False, + "counters": { + "in_crc_errors": 0, + "in_errors": 0, + "rate": {"in_rate": 0, "out_rate": 0}, + }, + "description": "configured using Ansible", + "duplex_mode": "full", + "enabled": True, + "line_protocol": "up", + "mtu": 1514, + "oper_status": "down", + "type": "GigabitEthernet", }, - "description": "configured using Ansible", - "duplex_mode": "full", - "enabled": True, - "line_protocol": "up", - "mtu": 1514, - "oper_status": "down", - "type": "GigabitEthernet" - }, - "GigabitEthernet0/0/0/1": { - "auto_negotiate": False, - "counters": { - "in_crc_errors": 10, - "in_errors": 0, - "rate": { - "in_rate": 0, - "out_rate": 0 - } + "GigabitEthernet0/0/0/1": { + "auto_negotiate": False, + "counters": { + "in_crc_errors": 10, + "in_errors": 0, + "rate": {"in_rate": 0, "out_rate": 0}, + }, + "description": "# interface is configures with Ansible", + "duplex_mode": "full", + "enabled": False, + "line_protocol": "up", + "mtu": 1514, + "oper_status": "up", + "type": "GigabitEthernet", }, - "description": "# interface is configures with Ansible", - "duplex_mode": "full", - "enabled": False, - "line_protocol": "up", - "mtu": 1514, - "oper_status": "up", - "type": "GigabitEthernet" - } } CRITERIA_CRC_ERROR_CHECK = { - "type" : "object", + "type": "object", "patternProperties": { "^.*": { "type": "object", "properties": { "counters": { "properties": { - "in_crc_errors": { - "type": "number", - "maximum": 0 - } + "in_crc_errors": {"type": "number", "maximum": 0} } } - } + }, } - } + }, } CRITERIA_ENABLED_CHECK = { - "type" : "object", + "type": "object", "patternProperties": { - "^.*": { - "type": "object", - "properties": { - "enabled": { - "enum": [True] - } - } - } - } + "^.*": {"type": "object", "properties": {"enabled": {"enum": [True]}}} + }, } CRITERIA_OPER_STATUS_UP_CHECK = { - "type" : "object", + "type": "object", "patternProperties": { "^.*": { "type": "object", - "properties": { - "oper_status": { - "type": "string", - "pattern": "up" - } - } + "properties": {"oper_status": {"type": "string", "pattern": "up"}}, } - } + }, } CRITERIA_IN_RATE_CHECK = { @@ -108,18 +87,15 @@ CRITERIA_IN_RATE_CHECK = { "counters": { "properties": { "rate": { - "properties": { - "in_rate": { - "type": "number", - "maximum": 0 + "properties": { + "in_rate": {"type": "number", "maximum": 0} } - } } } } - } + }, } - } + }, } @@ -135,27 +111,36 @@ class TestValidate(unittest.TestCase): kwargs = {} with self.assertRaises(AnsibleError) as error: validate(*args, **kwargs) - self.assertIn( - "missing required arguments: criteria", str(error.exception) + msg = "missing required arguments: criteria" + self.assertTrue( + set(str(error.exception).split()).issuperset(set(msg.split())) ) - kwargs = {'criteria': CRITERIA_IN_RATE_CHECK, 'engine': 'ansible.utils.sample'} + kwargs = { + "criteria": CRITERIA_IN_RATE_CHECK, + "engine": "ansible.utils.sample", + } with self.assertRaises(AnsibleError) as error: validate(*args, **kwargs) self.assertIn( - "For engine 'ansible.utils.sample' error loading", str(error.exception) + "For engine 'ansible.utils.sample' error loading", + str(error.exception), ) args = ["invalid data"] - kwargs = {'criteria': [CRITERIA_IN_RATE_CHECK], 'engine': 'ansible.utils.jsonschema'} + kwargs = { + "criteria": [CRITERIA_IN_RATE_CHECK], + "engine": "ansible.utils.jsonschema", + } with self.assertRaises(AnsibleError) as error: validate(*args, **kwargs) - self.assertIn( - "'data' option value is invalid", str(error.exception) - ) + self.assertIn("'data' option value is invalid", str(error.exception)) args = [DATA] - kwargs = {'criteria': 'invalid criteria', 'engine': 'ansible.utils.jsonschema'} + kwargs = { + "criteria": "invalid criteria", + "engine": "ansible.utils.jsonschema", + } with self.assertRaises(AnsibleError) as error: validate(*args, **kwargs) self.assertIn( @@ -165,24 +150,39 @@ class TestValidate(unittest.TestCase): def test_invalid_validate_plugin_config_options(self): """Check passing invalid validate plugin options""" args = [DATA] - kwargs = {'criteria': 'invalid criteria', 'engine': 'ansible.utils.jsonschema', 'draft': 'draft0'} + kwargs = { + "criteria": "invalid criteria", + "engine": "ansible.utils.jsonschema", + "draft": "draft0", + } with self.assertRaises(AnsibleError) as error: validate(*args, **kwargs) self.assertIn( - "value of draft must be one of: draft3, draft4, draft6, draft7, got: draft0", str(error.exception) + "value of draft must be one of: draft3, draft4, draft6, draft7, got: draft0", + str(error.exception), ) def test_invalid_data(self): """Check passing invalid data as per criteria""" args = [DATA] - kwargs = {'criteria': [CRITERIA_ENABLED_CHECK, CRITERIA_OPER_STATUS_UP_CHECK, CRITERIA_CRC_ERROR_CHECK], 'engine': 'ansible.utils.jsonschema'} + kwargs = { + "criteria": [ + CRITERIA_ENABLED_CHECK, + CRITERIA_OPER_STATUS_UP_CHECK, + CRITERIA_CRC_ERROR_CHECK, + ], + "engine": "ansible.utils.jsonschema", + } result = validate(*args, **kwargs) self.assertEqual(result, False) def test_valid_data(self): """Check passing valid data as per criteria""" args = [DATA] - kwargs = {'criteria': CRITERIA_IN_RATE_CHECK, 'engine': 'ansible.utils.jsonschema'} + kwargs = { + "criteria": CRITERIA_IN_RATE_CHECK, + "engine": "ansible.utils.jsonschema", + } result = validate(*args, **kwargs) self.assertEqual(result, True) diff --git a/tests/unit/requirements.txt b/tests/unit/requirements.txt index e69de29..46fbfa4 100644 --- a/tests/unit/requirements.txt +++ b/tests/unit/requirements.txt @@ -0,0 +1 @@ +unittest2 ; python_version < '2.7'