Source code for ironic.api.validation.validators
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Internal implementation of request/response validating middleware."""
import jsonschema
from oslo_utils import timeutils
from oslo_utils import uuidutils
from ironic.common import exception
from ironic.common.i18n import _
_FORMAT_CHECKER = jsonschema.FormatChecker()
@_FORMAT_CHECKER.checks('date-time')
def _validate_datetime_format(instance: object) -> bool:
# format checks constrain to the relevant primitive type
# https://github.com/OAI/OpenAPI-Specification/issues/3148
if not isinstance(instance, str):
return True
try:
timeutils.parse_isotime(instance)
except ValueError:
return False
else:
return True
@_FORMAT_CHECKER.checks('uuid')
def _validate_uuid_format(instance: object) -> bool:
# format checks constrain to the relevant primitive type
# https://github.com/OAI/OpenAPI-Specification/issues/3148
if not isinstance(instance, str):
return True
return uuidutils.is_uuid_like(instance)
[docs]
class SchemaValidator:
"""A validator class
This class is changed from Draft202012Validator to add format checkers for
data formats that are common in the Ironic API as well as add better error
messages.
"""
validator = None
validator_org = jsonschema.Draft202012Validator
def __init__(
self, schema, is_body=True
):
self.is_body = is_body
validator_cls = jsonschema.validators.extend(self.validator_org)
try:
self.validator = validator_cls(
schema, format_checker=_FORMAT_CHECKER
)
except Exception:
raise
[docs]
def validate(self, *args, **kwargs):
try:
self.validator.validate(*args, **kwargs)
except jsonschema.ValidationError as e:
error_msg = _('Schema error: %s') % e.message
# Sometimes the root message is too generic, try to find a possible
# root cause:
cause = None
current = e
while current.context:
current = jsonschema.exceptions.best_match(current.context)
cause = current.message
if cause is not None:
error_msg += _('. Possible root cause: %s') % cause
raise exception.InvalidParameterValue(error_msg)