CI cleanup (#23)

CI cleanup

Reviewed-by: https://github.com/apps/ansible-zuul
pull/30/head
Bradley A. Thornton 2020-10-30 14:36:30 -07:00 committed by GitHub
parent f5ab1d1b6a
commit 3d762f7800
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 339 additions and 344 deletions

View File

@ -0,0 +1,3 @@
---
bugfixes:
- linting and formatting for CI

View File

@ -1,3 +1,3 @@
--- ---
major_changes: minor_changes:
- Added validate module/lookup/filter/test plugin to validate data based on given criteria - Added fact_diff plugin and sub plugin

View File

@ -1,3 +0,0 @@
---
major_changes:
- test ci.

View File

@ -0,0 +1,3 @@
---
minor_changes:
- Added validate module/lookup/filter/test plugin to validate data based on given criteria

View File

@ -68,7 +68,9 @@ class ActionModule(ActionBase):
return argspec_result return argspec_result
self._task_vars = task_vars 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( self._validator_engine, validator_result = load_validator(
engine=updated_params["engine"], engine=updated_params["engine"],

View File

@ -40,10 +40,8 @@ def load_validator(
return None, result return None, result
cref = dict(zip(["corg", "cname", "plugin"], engine.split("."))) cref = dict(zip(["corg", "cname", "plugin"], engine.split(".")))
validatorlib = ( validatorlib = "ansible_collections.{corg}.{cname}.plugins.validate.{plugin}".format(
"ansible_collections.{corg}.{cname}.plugins.validate.{plugin}".format( **cref
**cref
)
) )
try: try:

View File

@ -147,7 +147,7 @@ def validate(*args, **kwargs):
class TestModule(object): class TestModule(object):
"""data validation test""" """data validation test"""
# For testing
test_map = {"validate": validate} test_map = {"validate": validate}
def tests(self): def tests(self):

View File

@ -46,12 +46,20 @@ from ansible.module_utils.basic import missing_required_lib
from ansible.errors import AnsibleError from ansible.errors import AnsibleError
from ansible.module_utils.six import string_types 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 ( from ansible_collections.ansible.utils.plugins.module_utils.common.utils import (
to_list, to_list,
) )
# PY2 compatiblilty for JSONDecodeError
try:
from json.decoder import JSONDecodeError
except ImportError:
JSONDecodeError = ValueError
try: try:
import jsonschema import jsonschema
@ -100,7 +108,7 @@ class Validate(ValidateBase):
) )
raise AnsibleError(msg) raise AnsibleError(msg)
except (TypeError, json.decoder.JSONDecodeError) as exe: except (TypeError, JSONDecodeError) as exe:
msg = ( msg = (
"'data' option value is invalid, value should of type dict or str format of dict." "'data' option value is invalid, value should of type dict or str format of dict."
" Failed to read with error '{err}'".format( " Failed to read with error '{err}'".format(
@ -123,7 +131,7 @@ class Validate(ValidateBase):
raise AnsibleError(msg) raise AnsibleError(msg)
self._criteria = criteria self._criteria = criteria
except (TypeError, json.decoder.JSONDecodeError) as exe: except (TypeError, JSONDecodeError) as exe:
msg = ( msg = (
"'criteria' option value is invalid, value should of type dict or str format of dict." "'criteria' option value is invalid, value should of type dict or str format of dict."
" Failed to read with error '{err}'".format( " Failed to read with error '{err}'".format(
@ -200,11 +208,9 @@ class Validate(ValidateBase):
"found": validation_error.instance, "found": validation_error.instance,
} }
self._result["errors"].append(error) self._result["errors"].append(error)
error_message = ( error_message = "At '{schema_path}' {message}. ".format(
"At '{schema_path}' {message}. ".format( schema_path=error["schema_path"],
schema_path=error["schema_path"], message=error["message"],
message=error["message"],
)
) )
error_messages.append(error_message) error_messages.append(error_message)
if error_messages: if error_messages:

View File

@ -9,7 +9,6 @@ __metaclass__ = type
import re import re
import unittest import unittest
from mock import MagicMock
from ansible.playbook.task import Task from ansible.playbook.task import Task
from ansible.template import Templar from ansible.template import Templar
@ -17,6 +16,11 @@ from ansible_collections.ansible.utils.plugins.action.fact_diff import (
ActionModule, ActionModule,
) )
try:
from unittest.mock import MagicMock # pylint:disable=syntax-error
except ImportError:
from mock import MagicMock
class TestUpdate_Fact(unittest.TestCase): class TestUpdate_Fact(unittest.TestCase):
def setUp(self): def setUp(self):

View File

@ -10,7 +10,6 @@ __metaclass__ = type
import copy import copy
import unittest import unittest
from jinja2 import Template, TemplateSyntaxError from jinja2 import Template, TemplateSyntaxError
from mock import MagicMock
from ansible.playbook.task import Task from ansible.playbook.task import Task
from ansible.template import Templar from ansible.template import Templar
@ -18,6 +17,12 @@ from ansible_collections.ansible.utils.plugins.action.update_fact import (
ActionModule, ActionModule,
) )
try:
from unittest.mock import MagicMock # pylint:disable=syntax-error
except ImportError:
from mock import MagicMock
VALID_DATA = { VALID_DATA = {
"a": { "a": {
"b": {"4.4": [{"1": {5: {"foo": 123}}}], 5.5: "float5.5"}, "b": {"4.4": [{"1": {5: {"foo": 123}}}], 5.5: "float5.5"},

View File

@ -7,10 +7,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
import copy
import unittest import unittest
from jinja2 import Template, TemplateSyntaxError
from mock import MagicMock
from ansible.playbook.task import Task from ansible.playbook.task import Task
from ansible.template import Templar from ansible.template import Templar
from ansible.errors import AnsibleActionFail from ansible.errors import AnsibleActionFail
@ -19,91 +16,76 @@ from ansible_collections.ansible.utils.plugins.action.validate import (
ActionModule, ActionModule,
) )
try:
from unittest.mock import MagicMock # pylint:disable=syntax-error
except ImportError:
from mock import MagicMock
DATA = { DATA = {
"GigabitEthernet0/0/0/0": { "GigabitEthernet0/0/0/0": {
"auto_negotiate": False, "auto_negotiate": False,
"counters": { "counters": {
"in_crc_errors": 0, "in_crc_errors": 0,
"in_errors": 0, "in_errors": 0,
"rate": { "rate": {"in_rate": 0, "out_rate": 0},
"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", "GigabitEthernet0/0/0/1": {
"duplex_mode": "full", "auto_negotiate": False,
"enabled": True, "counters": {
"line_protocol": "up", "in_crc_errors": 10,
"mtu": 1514, "in_errors": 0,
"oper_status": "down", "rate": {"in_rate": 0, "out_rate": 0},
"type": "GigabitEthernet" },
}, "description": "# interface is configures with Ansible",
"GigabitEthernet0/0/0/1": { "duplex_mode": "full",
"auto_negotiate": False, "enabled": False,
"counters": { "line_protocol": "up",
"in_crc_errors": 10, "mtu": 1514,
"in_errors": 0, "oper_status": "up",
"rate": { "type": "GigabitEthernet",
"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"
}
} }
CRITERIA_CRC_ERROR_CHECK = { CRITERIA_CRC_ERROR_CHECK = {
"type" : "object", "type": "object",
"patternProperties": { "patternProperties": {
"^.*": { "^.*": {
"type": "object", "type": "object",
"properties": { "properties": {
"counters": { "counters": {
"properties": { "properties": {
"in_crc_errors": { "in_crc_errors": {"type": "number", "maximum": 0}
"type": "number",
"maximum": 0
}
} }
} }
} },
} }
} },
} }
CRITERIA_ENABLED_CHECK = { CRITERIA_ENABLED_CHECK = {
"type" : "object", "type": "object",
"patternProperties": { "patternProperties": {
"^.*": { "^.*": {"type": "object", "properties": {"enabled": {"enum": [True]}}}
"type": "object", },
"properties": {
"enabled": {
"enum": [True]
}
}
}
}
} }
CRITERIA_OPER_STATUS_UP_CHECK = { CRITERIA_OPER_STATUS_UP_CHECK = {
"type" : "object", "type": "object",
"patternProperties": { "patternProperties": {
"^.*": { "^.*": {
"type": "object", "type": "object",
"properties": { "properties": {"oper_status": {"type": "string", "pattern": "up"}},
"oper_status": {
"type": "string",
"pattern": "up"
}
}
} }
} },
} }
CRITERIA_IN_RATE_CHECK = { CRITERIA_IN_RATE_CHECK = {
@ -115,18 +97,15 @@ CRITERIA_IN_RATE_CHECK = {
"counters": { "counters": {
"properties": { "properties": {
"rate": { "rate": {
"properties": { "properties": {
"in_rate": { "in_rate": {"type": "number", "maximum": 0}
"type": "number",
"maximum": 0
} }
}
} }
} }
} }
} },
} }
} },
} }
@ -154,41 +133,48 @@ class TestValidate(unittest.TestCase):
# missing required arguments # missing required arguments
self._plugin._task.args = {"engine": "ansible.utils.jsonschema"} self._plugin._task.args = {"engine": "ansible.utils.jsonschema"}
result = self._plugin.run(task_vars=None) 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 # invalid engine option value
self._plugin._task.args = { self._plugin._task.args = {
"engine": "ansible.utils.sample", "engine": "ansible.utils.sample",
"data": DATA, "data": DATA,
"criteria": CRITERIA_OPER_STATUS_UP_CHECK "criteria": CRITERIA_OPER_STATUS_UP_CHECK,
} }
result = self._plugin.run(task_vars=None) 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 # invalid data option value
self._plugin._task.args = { self._plugin._task.args = {
"engine": "ansible.utils.jsonschema", "engine": "ansible.utils.jsonschema",
"data": "invalid data", "data": "invalid data",
"criteria": CRITERIA_OPER_STATUS_UP_CHECK "criteria": CRITERIA_OPER_STATUS_UP_CHECK,
} }
with self.assertRaises(AnsibleActionFail) as error: with self.assertRaises(AnsibleActionFail) as error:
self._plugin.run(task_vars=None) self._plugin.run(task_vars=None)
self.assertIn( 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 # invalid criteria option value
self._plugin._task.args = { self._plugin._task.args = {
"engine": "ansible.utils.jsonschema", "engine": "ansible.utils.jsonschema",
"data": DATA, "data": DATA,
"criteria": "invalid criteria" "criteria": "invalid criteria",
} }
with self.assertRaises(AnsibleActionFail) as error: with self.assertRaises(AnsibleActionFail) as error:
self._plugin.run(task_vars=None) self._plugin.run(task_vars=None)
self.assertIn( 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): def test_invalid_validate_plugin_config_options(self):
@ -197,11 +183,16 @@ class TestValidate(unittest.TestCase):
self._plugin._task.args = { self._plugin._task.args = {
"engine": "ansible.utils.jsonschema", "engine": "ansible.utils.jsonschema",
"data": DATA, "data": DATA,
"criteria": CRITERIA_IN_RATE_CHECK "criteria": CRITERIA_IN_RATE_CHECK,
} }
result = self._plugin.run(task_vars={'ansible_validate_jsonschema_draft': 'draft0'}) result = self._plugin.run(
self.assertIn("value of draft must be one of: draft3, draft4, draft6, draft7, got: draft0", result["msg"]) 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): def test_invalid_data(self):
"""Check passing invalid data as per criteria""" """Check passing invalid data as per criteria"""
@ -209,13 +200,25 @@ class TestValidate(unittest.TestCase):
self._plugin._task.args = { self._plugin._task.args = {
"engine": "ansible.utils.jsonschema", "engine": "ansible.utils.jsonschema",
"data": DATA, "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) result = self._plugin.run(task_vars=None)
self.assertIn("patternProperties.^.*.properties.counters.properties.in_crc_errors.maximum", result["msg"]) self.assertIn(
self.assertIn("patternProperties.^.*.properties.enabled.enum", result["msg"]) "patternProperties.^.*.properties.counters.properties.in_crc_errors.maximum",
self.assertIn("'patternProperties.^.*.properties.oper_status.pattern", result["msg"]) result["msg"],
)
self.assertIn(
"patternProperties.^.*.properties.enabled.enum", result["msg"]
)
self.assertIn(
"'patternProperties.^.*.properties.oper_status.pattern",
result["msg"],
)
def test_valid_data(self): def test_valid_data(self):
"""Check passing valid data as per criteria""" """Check passing valid data as per criteria"""
@ -223,7 +226,7 @@ class TestValidate(unittest.TestCase):
self._plugin._task.args = { self._plugin._task.args = {
"engine": "ansible.utils.jsonschema", "engine": "ansible.utils.jsonschema",
"data": DATA, "data": DATA,
"criteria": CRITERIA_IN_RATE_CHECK "criteria": CRITERIA_IN_RATE_CHECK,
} }
result = self._plugin.run(task_vars=None) result = self._plugin.run(task_vars=None)

View File

@ -13,90 +13,69 @@ from ansible.errors import AnsibleFilterError
from ansible_collections.ansible.utils.plugins.filter.validate import validate from ansible_collections.ansible.utils.plugins.filter.validate import validate
DATA = { DATA = {
"GigabitEthernet0/0/0/0": { "GigabitEthernet0/0/0/0": {
"auto_negotiate": False, "auto_negotiate": False,
"counters": { "counters": {
"in_crc_errors": 0, "in_crc_errors": 0,
"in_errors": 0, "in_errors": 0,
"rate": { "rate": {"in_rate": 0, "out_rate": 0},
"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", "GigabitEthernet0/0/0/1": {
"duplex_mode": "full", "auto_negotiate": False,
"enabled": True, "counters": {
"line_protocol": "up", "in_crc_errors": 10,
"mtu": 1514, "in_errors": 0,
"oper_status": "down", "rate": {"in_rate": 0, "out_rate": 0},
"type": "GigabitEthernet" },
}, "description": "# interface is configures with Ansible",
"GigabitEthernet0/0/0/1": { "duplex_mode": "full",
"auto_negotiate": False, "enabled": False,
"counters": { "line_protocol": "up",
"in_crc_errors": 10, "mtu": 1514,
"in_errors": 0, "oper_status": "up",
"rate": { "type": "GigabitEthernet",
"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"
}
} }
CRITERIA_CRC_ERROR_CHECK = { CRITERIA_CRC_ERROR_CHECK = {
"type" : "object", "type": "object",
"patternProperties": { "patternProperties": {
"^.*": { "^.*": {
"type": "object", "type": "object",
"properties": { "properties": {
"counters": { "counters": {
"properties": { "properties": {
"in_crc_errors": { "in_crc_errors": {"type": "number", "maximum": 0}
"type": "number",
"maximum": 0
}
} }
} }
} },
} }
} },
} }
CRITERIA_ENABLED_CHECK = { CRITERIA_ENABLED_CHECK = {
"type" : "object", "type": "object",
"patternProperties": { "patternProperties": {
"^.*": { "^.*": {"type": "object", "properties": {"enabled": {"enum": [True]}}}
"type": "object", },
"properties": {
"enabled": {
"enum": [True]
}
}
}
}
} }
CRITERIA_OPER_STATUS_UP_CHECK = { CRITERIA_OPER_STATUS_UP_CHECK = {
"type" : "object", "type": "object",
"patternProperties": { "patternProperties": {
"^.*": { "^.*": {
"type": "object", "type": "object",
"properties": { "properties": {"oper_status": {"type": "string", "pattern": "up"}},
"oper_status": {
"type": "string",
"pattern": "up"
}
}
} }
} },
} }
CRITERIA_IN_RATE_CHECK = { CRITERIA_IN_RATE_CHECK = {
@ -108,18 +87,15 @@ CRITERIA_IN_RATE_CHECK = {
"counters": { "counters": {
"properties": { "properties": {
"rate": { "rate": {
"properties": { "properties": {
"in_rate": { "in_rate": {"type": "number", "maximum": 0}
"type": "number",
"maximum": 0
} }
}
} }
} }
} }
} },
} }
} },
} }
@ -136,34 +112,35 @@ class TestValidate(unittest.TestCase):
with self.assertRaises(AnsibleFilterError) as error: with self.assertRaises(AnsibleFilterError) as error:
validate(*args, **kwargs) validate(*args, **kwargs)
self.assertIn( 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 # missing required arguments
with self.assertRaises(AnsibleFilterError) as error: with self.assertRaises(AnsibleFilterError) as error:
validate([DATA], {}) validate([DATA], {})
self.assertIn( 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]] args = [DATA, [CRITERIA_IN_RATE_CHECK]]
kwargs = {'engine': 'ansible.utils.sample'} kwargs = {"engine": "ansible.utils.sample"}
with self.assertRaises(AnsibleFilterError) as error: with self.assertRaises(AnsibleFilterError) as error:
validate(*args, **kwargs) validate(*args, **kwargs)
self.assertIn( 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]] args = ["invalid data", [CRITERIA_IN_RATE_CHECK]]
kwargs = {'engine': 'ansible.utils.jsonschema'} kwargs = {"engine": "ansible.utils.jsonschema"}
with self.assertRaises(AnsibleFilterError) as error: with self.assertRaises(AnsibleFilterError) as error:
validate(*args, **kwargs) validate(*args, **kwargs)
self.assertIn( self.assertIn("'data' option value is invalid", str(error.exception))
"'data' option value is invalid", str(error.exception)
)
args = [DATA, "invalid criteria"] args = [DATA, "invalid criteria"]
kwargs = {'engine': 'ansible.utils.jsonschema'} kwargs = {"engine": "ansible.utils.jsonschema"}
with self.assertRaises(AnsibleFilterError) as error: with self.assertRaises(AnsibleFilterError) as error:
validate(*args, **kwargs) validate(*args, **kwargs)
self.assertIn( self.assertIn(
@ -173,18 +150,26 @@ class TestValidate(unittest.TestCase):
def test_invalid_validate_plugin_config_options(self): def test_invalid_validate_plugin_config_options(self):
"""Check passing invalid validate plugin options""" """Check passing invalid validate plugin options"""
args = [DATA, [CRITERIA_CRC_ERROR_CHECK, CRITERIA_ENABLED_CHECK, CRITERIA_OPER_STATUS_UP_CHECK]] args = [
kwargs = {'engine': 'ansible.utils.jsonschema', 'draft': 'draft0'} 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: with self.assertRaises(AnsibleFilterError) as error:
validate(*args, **kwargs) validate(*args, **kwargs)
self.assertIn( 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): def test_valid_data(self):
"""Check passing valid data as per criteria""" """Check passing valid data as per criteria"""
args = [DATA, CRITERIA_IN_RATE_CHECK] args = [DATA, CRITERIA_IN_RATE_CHECK]
kwargs = {'engine': 'ansible.utils.jsonschema'} kwargs = {"engine": "ansible.utils.jsonschema"}
result = validate(*args, **kwargs) result = validate(*args, **kwargs)
self.assertEqual(result, []) self.assertEqual(result, [])

View File

@ -10,93 +10,74 @@ __metaclass__ = type
import unittest import unittest
from ansible.errors import AnsibleLookupError 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 = { DATA = {
"GigabitEthernet0/0/0/0": { "GigabitEthernet0/0/0/0": {
"auto_negotiate": False, "auto_negotiate": False,
"counters": { "counters": {
"in_crc_errors": 0, "in_crc_errors": 0,
"in_errors": 0, "in_errors": 0,
"rate": { "rate": {"in_rate": 0, "out_rate": 0},
"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", "GigabitEthernet0/0/0/1": {
"duplex_mode": "full", "auto_negotiate": False,
"enabled": True, "counters": {
"line_protocol": "up", "in_crc_errors": 10,
"mtu": 1514, "in_errors": 0,
"oper_status": "down", "rate": {"in_rate": 0, "out_rate": 0},
"type": "GigabitEthernet" },
}, "description": "# interface is configures with Ansible",
"GigabitEthernet0/0/0/1": { "duplex_mode": "full",
"auto_negotiate": False, "enabled": False,
"counters": { "line_protocol": "up",
"in_crc_errors": 10, "mtu": 1514,
"in_errors": 0, "oper_status": "up",
"rate": { "type": "GigabitEthernet",
"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"
}
} }
CRITERIA_CRC_ERROR_CHECK = { CRITERIA_CRC_ERROR_CHECK = {
"type" : "object", "type": "object",
"patternProperties": { "patternProperties": {
"^.*": { "^.*": {
"type": "object", "type": "object",
"properties": { "properties": {
"counters": { "counters": {
"properties": { "properties": {
"in_crc_errors": { "in_crc_errors": {"type": "number", "maximum": 0}
"type": "number",
"maximum": 0
}
} }
} }
} },
} }
} },
} }
CRITERIA_ENABLED_CHECK = { CRITERIA_ENABLED_CHECK = {
"type" : "object", "type": "object",
"patternProperties": { "patternProperties": {
"^.*": { "^.*": {"type": "object", "properties": {"enabled": {"enum": [True]}}}
"type": "object", },
"properties": {
"enabled": {
"enum": [True]
}
}
}
}
} }
CRITERIA_OPER_STATUS_UP_CHECK = { CRITERIA_OPER_STATUS_UP_CHECK = {
"type" : "object", "type": "object",
"patternProperties": { "patternProperties": {
"^.*": { "^.*": {
"type": "object", "type": "object",
"properties": { "properties": {"oper_status": {"type": "string", "pattern": "up"}},
"oper_status": {
"type": "string",
"pattern": "up"
}
}
} }
} },
} }
CRITERIA_IN_RATE_CHECK = { CRITERIA_IN_RATE_CHECK = {
@ -108,18 +89,15 @@ CRITERIA_IN_RATE_CHECK = {
"counters": { "counters": {
"properties": { "properties": {
"rate": { "rate": {
"properties": { "properties": {
"in_rate": { "in_rate": {"type": "number", "maximum": 0}
"type": "number",
"maximum": 0
} }
}
} }
} }
} }
} },
} }
} },
} }
@ -138,25 +116,24 @@ class TestValidate(unittest.TestCase):
) )
terms = [DATA, [CRITERIA_IN_RATE_CHECK]] terms = [DATA, [CRITERIA_IN_RATE_CHECK]]
kwargs = {'engine': 'ansible.utils.sample'} kwargs = {"engine": "ansible.utils.sample"}
variables = {} variables = {}
with self.assertRaises(AnsibleLookupError) as error: with self.assertRaises(AnsibleLookupError) as error:
self._lp.run(terms, variables, **kwargs) self._lp.run(terms, variables, **kwargs)
self.assertIn( 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]] terms = ["invalid data", [CRITERIA_IN_RATE_CHECK]]
kwargs = {'engine': 'ansible.utils.jsonschema'} kwargs = {"engine": "ansible.utils.jsonschema"}
variables = {} variables = {}
with self.assertRaises(AnsibleLookupError) as error: with self.assertRaises(AnsibleLookupError) as error:
self._lp.run(terms, variables, **kwargs) self._lp.run(terms, variables, **kwargs)
self.assertIn( self.assertIn("'data' option value is invalid", str(error.exception))
"'data' option value is invalid", str(error.exception)
)
terms = [DATA, "invalid criteria"] terms = [DATA, "invalid criteria"]
kwargs = {'engine': 'ansible.utils.jsonschema'} kwargs = {"engine": "ansible.utils.jsonschema"}
variables = {} variables = {}
with self.assertRaises(AnsibleLookupError) as error: with self.assertRaises(AnsibleLookupError) as error:
self._lp.run(terms, variables, **kwargs) self._lp.run(terms, variables, **kwargs)
@ -167,20 +144,31 @@ class TestValidate(unittest.TestCase):
def test_invalid_validate_plugin_config_options(self): def test_invalid_validate_plugin_config_options(self):
"""Check passing invalid validate plugin options""" """Check passing invalid validate plugin options"""
terms = [DATA, [CRITERIA_CRC_ERROR_CHECK, CRITERIA_ENABLED_CHECK, CRITERIA_OPER_STATUS_UP_CHECK]] terms = [
kwargs = {'engine': 'ansible.utils.jsonschema'} DATA,
[
CRITERIA_CRC_ERROR_CHECK,
CRITERIA_ENABLED_CHECK,
CRITERIA_OPER_STATUS_UP_CHECK,
],
]
kwargs = {"engine": "ansible.utils.jsonschema"}
variables = {} variables = {}
result = self._lp.run(terms, variables, **kwargs) result = self._lp.run(terms, variables, **kwargs)
self.assertIn("GigabitEthernet0/0/0/1.counters.in_crc_errors", result[0]['data_path']) self.assertIn(
self.assertIn("GigabitEthernet0/0/0/1.enabled", result[1]['data_path']) "GigabitEthernet0/0/0/1.counters.in_crc_errors",
self.assertIn("GigabitEthernet0/0/0/0.oper_status", result[2]['data_path']) 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): def test_valid_data(self):
"""Check passing valid data as per criteria""" """Check passing valid data as per criteria"""
terms = [DATA, CRITERIA_IN_RATE_CHECK] terms = [DATA, CRITERIA_IN_RATE_CHECK]
kwargs = {'engine': 'ansible.utils.jsonschema'} kwargs = {"engine": "ansible.utils.jsonschema"}
variables = {} variables = {}
result = self._lp.run(terms, variables, **kwargs) result = self._lp.run(terms, variables, **kwargs)
self.assertEqual(result, []) self.assertEqual(result, [])

View File

@ -13,90 +13,69 @@ from ansible.errors import AnsibleError
from ansible_collections.ansible.utils.plugins.test.validate import validate from ansible_collections.ansible.utils.plugins.test.validate import validate
DATA = { DATA = {
"GigabitEthernet0/0/0/0": { "GigabitEthernet0/0/0/0": {
"auto_negotiate": False, "auto_negotiate": False,
"counters": { "counters": {
"in_crc_errors": 0, "in_crc_errors": 0,
"in_errors": 0, "in_errors": 0,
"rate": { "rate": {"in_rate": 0, "out_rate": 0},
"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", "GigabitEthernet0/0/0/1": {
"duplex_mode": "full", "auto_negotiate": False,
"enabled": True, "counters": {
"line_protocol": "up", "in_crc_errors": 10,
"mtu": 1514, "in_errors": 0,
"oper_status": "down", "rate": {"in_rate": 0, "out_rate": 0},
"type": "GigabitEthernet" },
}, "description": "# interface is configures with Ansible",
"GigabitEthernet0/0/0/1": { "duplex_mode": "full",
"auto_negotiate": False, "enabled": False,
"counters": { "line_protocol": "up",
"in_crc_errors": 10, "mtu": 1514,
"in_errors": 0, "oper_status": "up",
"rate": { "type": "GigabitEthernet",
"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"
}
} }
CRITERIA_CRC_ERROR_CHECK = { CRITERIA_CRC_ERROR_CHECK = {
"type" : "object", "type": "object",
"patternProperties": { "patternProperties": {
"^.*": { "^.*": {
"type": "object", "type": "object",
"properties": { "properties": {
"counters": { "counters": {
"properties": { "properties": {
"in_crc_errors": { "in_crc_errors": {"type": "number", "maximum": 0}
"type": "number",
"maximum": 0
}
} }
} }
} },
} }
} },
} }
CRITERIA_ENABLED_CHECK = { CRITERIA_ENABLED_CHECK = {
"type" : "object", "type": "object",
"patternProperties": { "patternProperties": {
"^.*": { "^.*": {"type": "object", "properties": {"enabled": {"enum": [True]}}}
"type": "object", },
"properties": {
"enabled": {
"enum": [True]
}
}
}
}
} }
CRITERIA_OPER_STATUS_UP_CHECK = { CRITERIA_OPER_STATUS_UP_CHECK = {
"type" : "object", "type": "object",
"patternProperties": { "patternProperties": {
"^.*": { "^.*": {
"type": "object", "type": "object",
"properties": { "properties": {"oper_status": {"type": "string", "pattern": "up"}},
"oper_status": {
"type": "string",
"pattern": "up"
}
}
} }
} },
} }
CRITERIA_IN_RATE_CHECK = { CRITERIA_IN_RATE_CHECK = {
@ -108,18 +87,15 @@ CRITERIA_IN_RATE_CHECK = {
"counters": { "counters": {
"properties": { "properties": {
"rate": { "rate": {
"properties": { "properties": {
"in_rate": { "in_rate": {"type": "number", "maximum": 0}
"type": "number",
"maximum": 0
} }
}
} }
} }
} }
} },
} }
} },
} }
@ -135,27 +111,36 @@ class TestValidate(unittest.TestCase):
kwargs = {} kwargs = {}
with self.assertRaises(AnsibleError) as error: with self.assertRaises(AnsibleError) as error:
validate(*args, **kwargs) validate(*args, **kwargs)
self.assertIn( msg = "missing required arguments: criteria"
"missing required arguments: criteria", str(error.exception) 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: with self.assertRaises(AnsibleError) as error:
validate(*args, **kwargs) validate(*args, **kwargs)
self.assertIn( 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"] 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: with self.assertRaises(AnsibleError) as error:
validate(*args, **kwargs) validate(*args, **kwargs)
self.assertIn( self.assertIn("'data' option value is invalid", str(error.exception))
"'data' option value is invalid", str(error.exception)
)
args = [DATA] args = [DATA]
kwargs = {'criteria': 'invalid criteria', 'engine': 'ansible.utils.jsonschema'} kwargs = {
"criteria": "invalid criteria",
"engine": "ansible.utils.jsonschema",
}
with self.assertRaises(AnsibleError) as error: with self.assertRaises(AnsibleError) as error:
validate(*args, **kwargs) validate(*args, **kwargs)
self.assertIn( self.assertIn(
@ -165,24 +150,39 @@ class TestValidate(unittest.TestCase):
def test_invalid_validate_plugin_config_options(self): def test_invalid_validate_plugin_config_options(self):
"""Check passing invalid validate plugin options""" """Check passing invalid validate plugin options"""
args = [DATA] 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: with self.assertRaises(AnsibleError) as error:
validate(*args, **kwargs) validate(*args, **kwargs)
self.assertIn( 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): def test_invalid_data(self):
"""Check passing invalid data as per criteria""" """Check passing invalid data as per criteria"""
args = [DATA] 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) result = validate(*args, **kwargs)
self.assertEqual(result, False) self.assertEqual(result, False)
def test_valid_data(self): def test_valid_data(self):
"""Check passing valid data as per criteria""" """Check passing valid data as per criteria"""
args = [DATA] 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) result = validate(*args, **kwargs)
self.assertEqual(result, True) self.assertEqual(result, True)

View File

@ -0,0 +1 @@
unittest2 ; python_version < '2.7'