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 exceptions
from designate import notifications from designate import notifications
from designate import context from designate import context
from designate import objects
from designate.i18n import _LI from designate.i18n import _LI
from designate.i18n import _LW from designate.i18n import _LW
from designate.i18n import _LE from designate.i18n import _LE
@ -268,3 +269,66 @@ class FaultWrapperMiddleware(base.Middleware):
return flask.Response(status=status, headers=headers, return flask.Response(status=status, headers=headers,
response=json.dumps(response)) 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 = cls()
e.relative_path = ".".join([str(x) for x in js_error.relative_path]) e.relative_path = js_error.relative_path
e.absolute_path = ".".join([str(x) for x in js_error.absolute_path]) e.absolute_path = js_error.absolute_path
e.message = js_error.message e.message = js_error.message
e.validator = js_error.validator e.validator = js_error.validator
e.validator_value = js_error.validator_value 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 = middleware.FaultWrapperMiddleware(
self.app.wsgi_app) self.app.wsgi_app)
# Inject the ValidationError middleware
self.app.wsgi_app = middleware.APIv1ValidationErrorMiddleware(
self.app.wsgi_app)
# Inject the TestAuth middleware # Inject the TestAuth middleware
self.app.wsgi_app = middleware.TestContextMiddleware( self.app.wsgi_app = middleware.TestContextMiddleware(
self.app.wsgi_app, self.admin_context.tenant, self.app.wsgi_app, self.admin_context.tenant,

View File

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

View File

@ -381,8 +381,9 @@ class DesignateObjectTest(tests.TestCase):
self.assertEqual('format', error.validator) self.assertEqual('format', error.validator)
# Ensure the nested ID field has triggered the failure. # Ensure the nested ID field has triggered the failure.
self.assertEqual('nested.id', error.absolute_path) # For some reason testtools turns lists into deques :/
self.assertEqual('nested.id', error.relative_path) 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 # Set the Nested ID field to a valid value
obj.nested.id = 'ffded5c4-e4f6-4e02-a175-48e13c5c12a0' 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] [composite:osapi_dns_v1]
use = call:designate.api.middleware:auth_pipeline_factory use = call:designate.api.middleware:auth_pipeline_factory
noauth = request_id noauthcontext 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 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] [app:osapi_dns_app_v1]
paste.app_factory = designate.api.v1:factory paste.app_factory = designate.api.v1:factory
[composite:osapi_dns_v2] [composite:osapi_dns_v2]
use = call:designate.api.middleware:auth_pipeline_factory use = call:designate.api.middleware:auth_pipeline_factory
noauth = request_id faultwrapper noauthcontext maintenance normalizeuri osapi_dns_app_v2 noauth = request_id faultwrapper validation_API_v2 noauthcontext maintenance normalizeuri osapi_dns_app_v2
keystone = request_id faultwrapper authtoken keystonecontext 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] [app:osapi_dns_app_v2]
paste.app_factory = designate.api.v2:factory paste.app_factory = designate.api.v2:factory
@ -43,3 +43,9 @@ paste.filter_factory = designate.api.middleware:NormalizeURIMiddleware.factory
[filter:faultwrapper] [filter:faultwrapper]
paste.filter_factory = designate.api.middleware:FaultWrapperMiddleware.factory 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