Merge "Added ValidationErrorMiddleware"

This commit is contained in:
Jenkins 2015-03-19 14:59:36 +00:00 committed by Gerrit Code Review
commit 82fae73bcd
6 changed files with 86 additions and 8 deletions

View File

@ -26,6 +26,7 @@ from oslo_utils import strutils
from designate import exceptions
from designate import notifications
from designate import context
from designate import objects
from designate.i18n import _LI
from designate.i18n import _LW
from designate.i18n import _LE
@ -268,3 +269,66 @@ class FaultWrapperMiddleware(base.Middleware):
return flask.Response(status=status, headers=headers,
response=json.dumps(response))
class ValidationErrorMiddleware(base.Middleware):
def __init__(self, application):
super(ValidationErrorMiddleware, self).__init__(application)
LOG.info(_LI('Starting designate validation middleware'))
@webob.dec.wsgify
def __call__(self, request):
try:
return request.get_response(self.application)
except exceptions.InvalidObject as e:
# Allow current views validation to pass through to FaultWapper
if not isinstance(e.errors, objects.ValidationErrorList):
raise
return self._handle_errors(request, e)
def _handle_errors(self, request, exception):
response = {}
headers = [
('Content-Type', 'application/json'),
]
url = getattr(request, 'url', None)
response['code'] = exception.error_code
response['type'] = exception.error_type or 'unknown'
response['errors'] = list()
for error in exception.errors:
response['errors'].append(error.to_dict())
# Return the new response
if 'context' in request.environ:
response['request_id'] = request.environ['context'].request_id
notifications.send_api_fault(request.environ['context'], url,
response['code'], exception)
else:
# TODO(ekarlso): Remove after verifying that there's actually a
# context always set
LOG.error(_LE('Missing context in request, please check.'))
return flask.Response(status=exception.error_code, headers=headers,
response=json.dumps(response))
class APIv1ValidationErrorMiddleware(ValidationErrorMiddleware):
def __init__(self, application):
super(APIv1ValidationErrorMiddleware, self).__init__(application)
self.api_version = 'API_v1'
class APIv2ValidationErrorMiddleware(ValidationErrorMiddleware):
def __init__(self, application):
super(APIv2ValidationErrorMiddleware, self).__init__(application)
self.api_version = 'API_v2'

View File

@ -30,8 +30,8 @@ class ValidationError(base.DesignateObject):
"""
e = cls()
e.relative_path = ".".join([str(x) for x in js_error.relative_path])
e.absolute_path = ".".join([str(x) for x in js_error.absolute_path])
e.relative_path = js_error.relative_path
e.absolute_path = js_error.absolute_path
e.message = js_error.message
e.validator = js_error.validator
e.validator_value = js_error.validator_value

View File

@ -42,6 +42,10 @@ class ApiV1Test(ApiTestCase):
self.app.wsgi_app = middleware.FaultWrapperMiddleware(
self.app.wsgi_app)
# Inject the ValidationError middleware
self.app.wsgi_app = middleware.APIv1ValidationErrorMiddleware(
self.app.wsgi_app)
# Inject the TestAuth middleware
self.app.wsgi_app = middleware.TestContextMiddleware(
self.app.wsgi_app, self.admin_context.tenant,

View File

@ -49,6 +49,9 @@ class ApiV2TestCase(ApiTestCase):
# Inject the FaultWrapper middleware
self.app = middleware.FaultWrapperMiddleware(self.app)
# Inject the ValidationError middleware
self.app = middleware.APIv2ValidationErrorMiddleware(self.app)
# Inject the TestContext middleware
self.app = middleware.TestContextMiddleware(
self.app, self.admin_context.tenant,

View File

@ -381,8 +381,9 @@ class DesignateObjectTest(tests.TestCase):
self.assertEqual('format', error.validator)
# Ensure the nested ID field has triggered the failure.
self.assertEqual('nested.id', error.absolute_path)
self.assertEqual('nested.id', error.relative_path)
# For some reason testtools turns lists into deques :/
self.assertEqual(list(error.absolute_path), ['nested', 'id'])
self.assertEqual(list(error.relative_path), ['nested', 'id'])
# Set the Nested ID field to a valid value
obj.nested.id = 'ffded5c4-e4f6-4e02-a175-48e13c5c12a0'

View File

@ -9,16 +9,16 @@ paste.app_factory = designate.api.versions:factory
[composite:osapi_dns_v1]
use = call:designate.api.middleware:auth_pipeline_factory
noauth = request_id noauthcontext maintenance faultwrapper normalizeuri osapi_dns_app_v1
keystone = request_id authtoken keystonecontext maintenance faultwrapper normalizeuri osapi_dns_app_v1
noauth = request_id noauthcontext maintenance validation_API_v1 faultwrapper normalizeuri osapi_dns_app_v1
keystone = request_id authtoken keystonecontext maintenance validation_API_v1 faultwrapper normalizeuri osapi_dns_app_v1
[app:osapi_dns_app_v1]
paste.app_factory = designate.api.v1:factory
[composite:osapi_dns_v2]
use = call:designate.api.middleware:auth_pipeline_factory
noauth = request_id faultwrapper noauthcontext maintenance normalizeuri osapi_dns_app_v2
keystone = request_id faultwrapper authtoken keystonecontext maintenance normalizeuri osapi_dns_app_v2
noauth = request_id faultwrapper validation_API_v2 noauthcontext maintenance normalizeuri osapi_dns_app_v2
keystone = request_id faultwrapper validation_API_v2 authtoken keystonecontext maintenance normalizeuri osapi_dns_app_v2
[app:osapi_dns_app_v2]
paste.app_factory = designate.api.v2:factory
@ -43,3 +43,9 @@ paste.filter_factory = designate.api.middleware:NormalizeURIMiddleware.factory
[filter:faultwrapper]
paste.filter_factory = designate.api.middleware:FaultWrapperMiddleware.factory
[filter:validation_API_v1]
paste.filter_factory = designate.api.middleware:APIv1ValidationErrorMiddleware.factory
[filter:validation_API_v2]
paste.filter_factory = designate.api.middleware:APIv2ValidationErrorMiddleware.factory