diff --git a/ironic/api/validation/__init__.py b/ironic/api/validation/__init__.py index 91647ecc92..cab00e3c7c 100644 --- a/ironic/api/validation/__init__.py +++ b/ironic/api/validation/__init__.py @@ -16,7 +16,6 @@ import functools import inspect import typing as ty -import jsonschema.exceptions from oslo_config import cfg from oslo_log import log from oslo_serialization import jsonutils @@ -24,6 +23,7 @@ from webob import exc as webob_exc from ironic import api from ironic.api.validation import validators +from ironic.common import exception from ironic.common.i18n import _ CONF = cfg.CONF @@ -381,7 +381,7 @@ def response_body_schema( max_version, is_body=True, ) - except jsonschema.exceptions.ValidationError: + except exception.InvalidParameterValue: if CONF.api.response_validation == 'warn': LOG.exception('Schema failed to validate') else: diff --git a/ironic/tests/unit/api/validation/test_validators.py b/ironic/tests/unit/api/validation/test_validators.py index da3c1d79c2..a01ae14359 100644 --- a/ironic/tests/unit/api/validation/test_validators.py +++ b/ironic/tests/unit/api/validation/test_validators.py @@ -10,6 +10,9 @@ # License for the specific language governing permissions and limitations # under the License. +from unittest import mock + +from ironic.api import validation from ironic.api.validation import validators from ironic.common import exception from ironic.tests import base as test_base @@ -44,3 +47,51 @@ class TestSchemaValidator(test_base.TestCase): validator.validate, 'invalid date-time' ) + + +class TestResponseBodyValidation(test_base.TestCase): + + def setUp(self): + super().setUp() + + self.schema = { + 'type': 'object', + 'properties': {'foo': {'type': 'string'}}, + 'required': ['foo'], + } + + @mock.patch.object(validation, 'LOG', autospec=True) + def test_response_validation__error(self, mock_log): + self.config(response_validation='error', group='api') + + @validation.response_body_schema(self.schema) + def test_func(): + return {'foo': 123} + + self.assertRaises(exception.InvalidParameterValue, test_func) + mock_log.exception.assert_not_called() + + @mock.patch.object(validation, 'LOG', autospec=True) + def test_response_validation__warn(self, mock_log): + self.config(response_validation='warn', group='api') + + @validation.response_body_schema(self.schema) + def test_func(): + return {'foo': 123} + + result = test_func() + self.assertEqual({'foo': 123}, result) + mock_log.exception.assert_called_once_with('Schema failed to validate') + + @mock.patch.object(validation, 'LOG', autospec=True) + def test_response_validation__ignore(self, mock_log): + self.config(response_validation='ignore', group='api') + + @validation.response_body_schema(self.schema) + def test_func(): + return {'foo': 123} + + # Should not call validator at all in ignore mode + result = test_func() + self.assertEqual({'foo': 123}, result) + mock_log.exception.assert_not_called()