From 45eb99fb948b598893a6850930a7631453ba9e01 Mon Sep 17 00:00:00 2001 From: Ashwini Mhatre Date: Mon, 28 Jun 2021 18:57:51 +0530 Subject: [PATCH] Add support for the validation of formats to the json schema validator (#83) Add support for the validation of formats to the json schema validator SUMMARY fixes: #81 ISSUE TYPE Bugfix Pull Request COMPONENT NAME ADDITIONAL INFORMATION Reviewed-by: Ganesh Nalawade --- .../fragments/81_add_support_for_format.yaml | 4 + plugins/sub_plugins/validate/jsonschema.py | 16 +++- .../files/criteria/format_checker.json | 10 +++ .../files/data/test_format_checker.json | 4 + .../targets/validate/tasks/include/test.yaml | 13 ++++ tests/unit/plugins/action/test_validate.py | 77 +++++++++++++++++++ 6 files changed, 120 insertions(+), 4 deletions(-) create mode 100644 changelogs/fragments/81_add_support_for_format.yaml create mode 100644 tests/integration/targets/validate/files/criteria/format_checker.json create mode 100644 tests/integration/targets/validate/files/data/test_format_checker.json diff --git a/changelogs/fragments/81_add_support_for_format.yaml b/changelogs/fragments/81_add_support_for_format.yaml new file mode 100644 index 0000000..34ba87c --- /dev/null +++ b/changelogs/fragments/81_add_support_for_format.yaml @@ -0,0 +1,4 @@ +--- +bugfixes: + - Add support for the validation of formats to the jsonschema validator. + - Improve test coverage diff --git a/plugins/sub_plugins/validate/jsonschema.py b/plugins/sub_plugins/validate/jsonschema.py index 98697b7..e749500 100644 --- a/plugins/sub_plugins/validate/jsonschema.py +++ b/plugins/sub_plugins/validate/jsonschema.py @@ -160,13 +160,21 @@ class Validate(ValidateBase): for criteria in self._criteria: if draft == "draft3": - validator = jsonschema.Draft3Validator(criteria) + validator = jsonschema.Draft3Validator( + criteria, format_checker=jsonschema.draft3_format_checker + ) elif draft == "draft4": - validator = jsonschema.Draft4Validator(criteria) + validator = jsonschema.Draft4Validator( + criteria, format_checker=jsonschema.draft4_format_checker + ) elif draft == "draft6": - validator = jsonschema.Draft6Validator(criteria) + validator = jsonschema.Draft6Validator( + criteria, format_checker=jsonschema.draft6_format_checker + ) else: - validator = jsonschema.Draft7Validator(criteria) + validator = jsonschema.Draft7Validator( + criteria, format_checker=jsonschema.draft7_format_checker + ) validation_errors = sorted( validator.iter_errors(self._data), key=lambda e: e.path diff --git a/tests/integration/targets/validate/files/criteria/format_checker.json b/tests/integration/targets/validate/files/criteria/format_checker.json new file mode 100644 index 0000000..07031f9 --- /dev/null +++ b/tests/integration/targets/validate/files/criteria/format_checker.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://json-schema.org/schema#", + + "type": "object", + "properties": { + "name": {"type": "string"}, + "email": {"format": "email"} + }, + "required": ["email"] +} diff --git a/tests/integration/targets/validate/files/data/test_format_checker.json b/tests/integration/targets/validate/files/data/test_format_checker.json new file mode 100644 index 0000000..f83d495 --- /dev/null +++ b/tests/integration/targets/validate/files/data/test_format_checker.json @@ -0,0 +1,4 @@ +{ + "name": "ansible", + "email": "ansible@redhat.com" +} diff --git a/tests/integration/targets/validate/tasks/include/test.yaml b/tests/integration/targets/validate/tasks/include/test.yaml index ff1fce2..e265e4e 100644 --- a/tests/integration/targets/validate/tasks/include/test.yaml +++ b/tests/integration/targets/validate/tasks/include/test.yaml @@ -87,3 +87,16 @@ - assert: that: - "is_data_valid == true" + +- name: read data and criteria from file + ansible.builtin.set_fact: + data: "{{ lookup('ansible.builtin.file', 'data/test_format_checker.json') }}" + criteria_1: "{{ lookup('ansible.builtin.file', 'criteria/format_checker.json') }}" + +- name: validate data using jsonschema engine (valid data read from file) + ansible.builtin.set_fact: + is_data_valid: "{{ data is ansible.utils.validate(engine='ansible.utils.jsonschema', criteria=[criteria_1], draft='draft7') }}" + +- assert: + that: + - "is_data_valid == true" diff --git a/tests/unit/plugins/action/test_validate.py b/tests/unit/plugins/action/test_validate.py index df4103f..c7b42f6 100644 --- a/tests/unit/plugins/action/test_validate.py +++ b/tests/unit/plugins/action/test_validate.py @@ -108,6 +108,17 @@ CRITERIA_IN_RATE_CHECK = { }, } +VALID_DATA = {"name": "ansible", "email": "ansible@redhat.com"} + +IN_VALID_DATA = {"name": "ansible", "email": "redhatcom"} + +CRITERIA_FORMAT_SUPPORT_CHECK = { + "$schema": "https://json-schema.org/schema#", + "type": "object", + "properties": {"name": {"type": "string"}, "email": {"format": "email"}}, + "required": ["email"], +} + class TestValidate(unittest.TestCase): def setUp(self): @@ -190,6 +201,48 @@ class TestValidate(unittest.TestCase): result["msg"], ) + def test_validate_plugin_config_options_with_draft3(self): + """Check passing invalid validate plugin options""" + + self._plugin._task.args = { + "engine": "ansible.utils.jsonschema", + "data": DATA, + "criteria": CRITERIA_IN_RATE_CHECK, + } + + result = self._plugin.run( + task_vars={"ansible_validate_jsonschema_draft": "draft3"} + ) + self.assertIn("all checks passed", result["msg"]) + + def test_validate_plugin_config_options_with_draft4(self): + """Check passing invalid validate plugin options""" + + self._plugin._task.args = { + "engine": "ansible.utils.jsonschema", + "data": DATA, + "criteria": CRITERIA_IN_RATE_CHECK, + } + + result = self._plugin.run( + task_vars={"ansible_validate_jsonschema_draft": "draft4"} + ) + self.assertIn("all checks passed", result["msg"]) + + def test_validate_plugin_config_options_with_draft6(self): + """Check passing invalid validate plugin options""" + + self._plugin._task.args = { + "engine": "ansible.utils.jsonschema", + "data": DATA, + "criteria": CRITERIA_IN_RATE_CHECK, + } + + result = self._plugin.run( + task_vars={"ansible_validate_jsonschema_draft": "draft6"} + ) + self.assertIn("all checks passed", result["msg"]) + def test_invalid_data(self): """Check passing invalid data as per criteria""" @@ -227,3 +280,27 @@ class TestValidate(unittest.TestCase): result = self._plugin.run(task_vars=None) self.assertIn("all checks passed", result["msg"]) + + def test_support_for_format(self): + """Check passing valid data as per criteria""" + + self._plugin._task.args = { + "engine": "ansible.utils.jsonschema", + "data": VALID_DATA, + "criteria": CRITERIA_FORMAT_SUPPORT_CHECK, + } + + result = self._plugin.run(task_vars=None) + self.assertIn("all checks passed", result["msg"]) + + def test_support_for_format_with_invalid_data(self): + """Check passing valid data as per criteria""" + + self._plugin._task.args = { + "engine": "ansible.utils.jsonschema", + "data": IN_VALID_DATA, + "criteria": CRITERIA_FORMAT_SUPPORT_CHECK, + } + + result = self._plugin.run(task_vars=None) + self.assertIn("Validation errors were found", result["msg"])