Make ApiValidator to work with jsonschema>=4.0.0
As of Zed jsonschema version has been bumped to 4.14.0 in
upper-constraints, which means project should support running with
this version. This patch aims to fix ApiValidator that is not compatible
with new jsonschema.
Other deprecations, like FormatChecker.cls_checks decorator are left
intact and must be covered with follow-up patches.
We also move zuul queues to project scope as otherwise jobs do not
run due to config error.
We also replace iteritems with six method as iteritems have been dropped
from Python 3.
Change-Id: Ia8b69587aa9b3d04ffcdea7c6b97a8ae65f67534
(cherry picked from commit ebc6d74bf8
)
This commit is contained in:
parent
c943f4a510
commit
aab24afe34
|
@ -1,4 +1,5 @@
|
|||
- project:
|
||||
queue: sahara
|
||||
templates:
|
||||
- openstack-python3-zed-jobs
|
||||
- periodic-stable-jobs
|
||||
|
@ -22,7 +23,6 @@
|
|||
- openstack-ansible-deploy-aio_sahara_metal-ubuntu-focal:
|
||||
voting: false
|
||||
gate:
|
||||
queue: sahara
|
||||
jobs:
|
||||
- sahara-tests-scenario:
|
||||
voting: false
|
||||
|
|
|
@ -259,7 +259,7 @@ class ApiValidatorTest(testtools.TestCase):
|
|||
def test_validate_hostname(self):
|
||||
schema = {
|
||||
"type": "string",
|
||||
"format": "hostname",
|
||||
"format": "idn-hostname",
|
||||
}
|
||||
|
||||
self._validate_success(schema, "abcd")
|
||||
|
|
|
@ -97,85 +97,70 @@ def validate_posix_path(entry):
|
|||
return res is not None
|
||||
|
||||
|
||||
class ConfigTypeMeta(type):
|
||||
def __instancecheck__(cls, instance):
|
||||
# configs should be dict
|
||||
if not isinstance(instance, dict):
|
||||
def is_config(cls, instance):
|
||||
# configs should be dict
|
||||
if not isinstance(instance, dict):
|
||||
return False
|
||||
|
||||
# check dict content
|
||||
for applicable_target, configs in six.iteritems(instance):
|
||||
# upper-level dict keys (applicable targets) should be strings
|
||||
if not isinstance(applicable_target, six.string_types):
|
||||
return False
|
||||
|
||||
# check dict content
|
||||
for applicable_target, configs in six.iteritems(instance):
|
||||
# upper-level dict keys (applicable targets) should be strings
|
||||
if not isinstance(applicable_target, six.string_types):
|
||||
return False
|
||||
|
||||
# upper-level dict values should be dicts
|
||||
if not isinstance(configs, dict):
|
||||
return False
|
||||
|
||||
# check internal dict content
|
||||
for config_name, config_value in six.iteritems(configs):
|
||||
# internal dict keys should be strings
|
||||
if not isinstance(config_name, six.string_types):
|
||||
return False
|
||||
|
||||
# internal dict values should be strings or integers or bools
|
||||
if not isinstance(config_value,
|
||||
(six.string_types, six.integer_types)):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class SimpleConfigTypeMeta(type):
|
||||
def __instancecheck__(cls, instance):
|
||||
# configs should be dict
|
||||
if not isinstance(instance, dict):
|
||||
# upper-level dict values should be dicts
|
||||
if not isinstance(configs, dict):
|
||||
return False
|
||||
|
||||
# check dict content
|
||||
for conf_name, conf_value in six.iteritems(instance):
|
||||
# keys should be strings, values should be int, string or bool
|
||||
if not isinstance(conf_name, six.string_types):
|
||||
# check internal dict content
|
||||
for config_name, config_value in six.iteritems(configs):
|
||||
# internal dict keys should be strings
|
||||
if not isinstance(config_name, six.string_types):
|
||||
return False
|
||||
if not isinstance(conf_value,
|
||||
|
||||
# internal dict values should be strings or integers or bools
|
||||
if not isinstance(config_value,
|
||||
(six.string_types, six.integer_types)):
|
||||
return False
|
||||
return True
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@six.add_metaclass(ConfigTypeMeta)
|
||||
class ConfigsType(dict):
|
||||
pass
|
||||
def is_simple_config(cls, instance):
|
||||
# configs should be dict
|
||||
if not isinstance(instance, dict):
|
||||
return False
|
||||
|
||||
# check dict content
|
||||
for conf_name, conf_value in six.iteritems(instance):
|
||||
# keys should be strings, values should be int, string or bool
|
||||
if not isinstance(conf_name, six.string_types):
|
||||
return False
|
||||
if not isinstance(conf_value,
|
||||
(six.string_types, six.integer_types)):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
@six.add_metaclass(SimpleConfigTypeMeta)
|
||||
class SimpleConfigsType(dict):
|
||||
pass
|
||||
|
||||
|
||||
class FlavorTypeMeta(type):
|
||||
def __instancecheck__(cls, instance):
|
||||
try:
|
||||
int(instance)
|
||||
except (ValueError, TypeError):
|
||||
return (isinstance(instance, six.string_types)
|
||||
and uuidutils.is_uuid_like(instance))
|
||||
return (isinstance(instance, six.integer_types + six.string_types)
|
||||
and type(instance) != bool)
|
||||
|
||||
|
||||
@six.add_metaclass(FlavorTypeMeta)
|
||||
class FlavorType(object):
|
||||
pass
|
||||
def is_flavor_type(cls, instance):
|
||||
try:
|
||||
int(instance)
|
||||
except (ValueError, TypeError):
|
||||
return (isinstance(instance, six.string_types)
|
||||
and uuidutils.is_uuid_like(instance))
|
||||
return (isinstance(instance, six.integer_types + six.string_types)
|
||||
and type(instance) != bool)
|
||||
|
||||
|
||||
class ApiValidator(jsonschema.Draft4Validator):
|
||||
def __init__(self, schema):
|
||||
format_checker = jsonschema.FormatChecker()
|
||||
|
||||
TYPE_CHECKER = jsonschema.Draft4Validator.TYPE_CHECKER.redefine_many({
|
||||
"configs": is_config,
|
||||
"flavor": is_flavor_type,
|
||||
"simple_config": is_simple_config,
|
||||
})
|
||||
|
||||
def __init__(self, schema, resolver=None,
|
||||
format_checker=jsonschema.FormatChecker()):
|
||||
super(ApiValidator, self).__init__(
|
||||
schema, format_checker=format_checker, types={
|
||||
"configs": ConfigsType,
|
||||
"flavor": FlavorType,
|
||||
"simple_config": SimpleConfigsType,
|
||||
})
|
||||
schema, format_checker=format_checker)
|
||||
|
|
|
@ -50,7 +50,7 @@ def wrap_entity(func):
|
|||
|
||||
def _get_all_tags(image_props):
|
||||
tags = []
|
||||
for key, value in image_props.iteritems():
|
||||
for key, value in six.iteritems(image_props):
|
||||
if key.startswith(PROP_TAG) and value:
|
||||
tags.append(key)
|
||||
return tags
|
||||
|
@ -69,7 +69,7 @@ def _parse_tags(image_props):
|
|||
|
||||
def _serialize_metadata(image):
|
||||
data = {}
|
||||
for key, value in image.iteritems():
|
||||
for key, value in six.iteritems(image):
|
||||
if key.startswith('_sahara') and value:
|
||||
data[key] = value
|
||||
return data
|
||||
|
|
Loading…
Reference in New Issue