From e990605babd299bddab96763530dbe19af7c6d59 Mon Sep 17 00:00:00 2001 From: Mike Fedosin Date: Fri, 17 Mar 2017 15:29:16 +0300 Subject: [PATCH] Remove the remaining code after glare-ectomy After glare-ectomy (I3026ca6287a65ab5287bf3843f2a9d756ce15139) some glare related code was left in glance repo. This patch removes these leftovers. Change-Id: I2b792b9c5a99c7794f0277a40b3e903086ff3bef Partially-implements: blueprint glare-ectomy --- glance/common/exception.py | 17 ---- glance/common/jsonpatchvalidator.py | 124 ----------------------- glance/tests/unit/test_jsonpatchmixin.py | 74 -------------- 3 files changed, 215 deletions(-) delete mode 100644 glance/common/jsonpatchvalidator.py delete mode 100644 glance/tests/unit/test_jsonpatchmixin.py diff --git a/glance/common/exception.py b/glance/common/exception.py index 7c6ab7cff2..097957a70f 100644 --- a/glance/common/exception.py +++ b/glance/common/exception.py @@ -452,23 +452,6 @@ class MetadefTagNotFound(NotFound): " namespace=%(namespace_name)s.") -class JsonPatchException(GlanceException): - message = _("Invalid jsonpatch request") - - -class InvalidJsonPatchBody(JsonPatchException): - message = _("The provided body %(body)s is invalid " - "under given schema: %(schema)s") - - -class InvalidJsonPatchPath(JsonPatchException): - message = _("The provided path '%(path)s' is invalid: %(explanation)s") - - def __init__(self, message=None, *args, **kwargs): - self.explanation = kwargs.get("explanation") - super(InvalidJsonPatchPath, self).__init__(message, *args, **kwargs) - - class InvalidDataMigrationScript(GlanceException): message = _("Invalid data migration script '%(script)s'. A valid data " "migration script must implement functions 'has_migrations' " diff --git a/glance/common/jsonpatchvalidator.py b/glance/common/jsonpatchvalidator.py deleted file mode 100644 index 7269bb77e2..0000000000 --- a/glance/common/jsonpatchvalidator.py +++ /dev/null @@ -1,124 +0,0 @@ -# Copyright 2015 OpenStack Foundation. -# All Rights Reserved. -# -# 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. - - -""" -A mixin that validates the given body for jsonpatch-compatibility. -The methods supported are limited to listed in METHODS_ALLOWED -""" - -import re - -import jsonschema - -import glance.common.exception as exc -from glance.i18n import _ - - -class JsonPatchValidatorMixin(object): - # a list of allowed methods allowed according to RFC 6902 - ALLOWED = ["replace", "test", "remove", "add", "copy"] - PATH_REGEX_COMPILED = re.compile("^/[^/]+(/[^/]+)*$") - - def __init__(self, methods_allowed=None): - if methods_allowed is None: - methods_allowed = ["replace", "remove"] - self.schema = self._gen_schema(methods_allowed) - self.methods_allowed = [m for m in methods_allowed - if m in self.ALLOWED] - - @staticmethod - def _gen_schema(methods_allowed): - """ - Generates a jsonschema for jsonpatch request based on methods_allowed - """ - # op replace needs no 'value' param, so needs a special schema if - # present in methods_allowed - basic_schema = { - "type": "array", - "items": {"properties": {"op": {"type": "string", - "enum": methods_allowed}, - "path": {"type": "string"}, - "value": {"type": ["string", - "object", - "integer", - "array", - "boolean"]} - }, - "required": ["op", "path", "value"], - "type": "object"}, - "$schema": "http://json-schema.org/draft-04/schema#" - } - if "remove" in methods_allowed: - methods_allowed.remove("remove") - no_remove_op_schema = { - "type": "object", - "properties": { - "op": {"type": "string", "enum": methods_allowed}, - "path": {"type": "string"}, - "value": {"type": ["string", "object", - "integer", "array", "boolean"]} - }, - "required": ["op", "path", "value"]} - op_remove_only_schema = { - "type": "object", - "properties": { - "op": {"type": "string", "enum": ["remove"]}, - "path": {"type": "string"} - }, - "required": ["op", "path"]} - - basic_schema = { - "type": "array", - "items": { - "oneOf": [no_remove_op_schema, op_remove_only_schema]}, - "$schema": "http://json-schema.org/draft-04/schema#" - } - return basic_schema - - def validate_body(self, body): - try: - jsonschema.validate(body, self.schema) - # now make sure everything is ok with path - return [{"path": self._decode_json_pointer(e["path"]), - "value": e.get("value", None), - "op": e["op"]} for e in body] - except jsonschema.ValidationError: - raise exc.InvalidJsonPatchBody(body=body, schema=self.schema) - - def _check_for_path_errors(self, pointer): - if not re.match(self.PATH_REGEX_COMPILED, pointer): - msg = _("Json path should start with a '/', " - "end with no '/', no 2 subsequent '/' are allowed.") - raise exc.InvalidJsonPatchPath(path=pointer, explanation=msg) - if re.search('~[^01]', pointer) or pointer.endswith('~'): - msg = _("Pointer contains '~' which is not part of" - " a recognized escape sequence [~0, ~1].") - raise exc.InvalidJsonPatchPath(path=pointer, explanation=msg) - - def _decode_json_pointer(self, pointer): - """Parses a json pointer. Returns a pointer as a string. - - Json Pointers are defined in - http://tools.ietf.org/html/draft-pbryan-zyp-json-pointer . - The pointers use '/' for separation between object attributes. - A '/' character in an attribute name is encoded as "~1" and - a '~' character is encoded as "~0". - """ - self._check_for_path_errors(pointer) - ret = [] - for part in pointer.lstrip('/').split('/'): - ret.append(part.replace('~1', '/').replace('~0', '~').strip()) - return '/'.join(ret) diff --git a/glance/tests/unit/test_jsonpatchmixin.py b/glance/tests/unit/test_jsonpatchmixin.py deleted file mode 100644 index 108b1c454f..0000000000 --- a/glance/tests/unit/test_jsonpatchmixin.py +++ /dev/null @@ -1,74 +0,0 @@ -# Copyright (c) 2015 Mirantis, Inc. -# -# 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. - - -import glance.common.exception as exc -import glance.common.jsonpatchvalidator as jpv -import glance.tests.utils as utils - - -class TestValidator(jpv.JsonPatchValidatorMixin): - def __init__(self, methods_allowed=None): - if methods_allowed is None: - methods_allowed = ["replace", "add"] - - super(TestValidator, self).__init__(methods_allowed) - - -class TestJsonPatchMixin(utils.BaseTestCase): - def test_body_validation(self): - validator = TestValidator() - validator.validate_body( - [{"op": "replace", "path": "/param", "value": "ok"}]) - # invalid if not a list of [{"op": "", "path": "", "value": ""}] - # is passed - self.assertRaises(exc.JsonPatchException, validator.validate_body, - {"op": "replace", "path": "/me", - "value": "should be a list"}) - - def test_value_validation(self): - # a string, a list and a dict are valid value types - validator = TestValidator() - validator.validate_body( - [{"op": "replace", "path": "/param", "value": "ok string"}]) - validator.validate_body( - [{"op": "replace", "path": "/param", - "value": ["ok list", "really ok"]}]) - validator.validate_body( - [{"op": "replace", "path": "/param", "value": {"ok": "dict"}}]) - - def test_op_validation(self): - validator = TestValidator(methods_allowed=["replace", "add", "copy"]) - validator.validate_body( - [{"op": "copy", "path": "/param", "value": "ok"}, - {"op": "replace", "path": "/param/1", "value": "ok"}]) - self.assertRaises( - exc.JsonPatchException, validator.validate_body, - [{"op": "test", "path": "/param", "value": "not allowed"}]) - self.assertRaises(exc.JsonPatchException, validator.validate_body, - [{"op": "nosuchmethodatall", "path": "/param", - "value": "no way"}]) - - def test_path_validation(self): - validator = TestValidator() - bad_body_part = {"op": "add", "value": "bad path"} - for bad_path in ["/param/", "param", "//param", "/param~2", "/param~"]: - bad_body_part["path"] = bad_path - bad_body = [bad_body_part] - self.assertRaises(exc.JsonPatchException, - validator.validate_body, bad_body) - ok_body = [{"op": "add", "value": "some value", - "path": "/param~1/param~0"}] - body = validator.validate_body(ok_body)[0] - self.assertEqual("param//param~", body["path"])