Set 'code' in error response

Run this command:

$ zun --debug show non-existing-container
...
RESP BODY: {"errors": [{"status": 404, "code": "", "links": [], "title":
"Container non-existing-container could not be found.", "detail": "Container
non-existing-container could not be found.", "request_id": "}]}
...

As showed above, the "code" is empty because Zun doesn't pass 'faultcode'.
This patch will add 'faultcode' and set 'code' in error response which
follow convention in [1]

[1] https://specs.openstack.org/openstack/api-wg/guidelines/errors.html

Change-Id: Ic95d70756c91027cbfcc28cfea41c3f34787c177
Closes-Bug: #1685571
This commit is contained in:
Kien Nguyen 2017-10-18 14:55:31 +07:00
parent 242e9b5017
commit f843513137
2 changed files with 19 additions and 3 deletions

View File

@ -26,6 +26,7 @@ from zun.common.i18n import _
class ParsableErrorMiddleware(object): class ParsableErrorMiddleware(object):
"""Replace error body with something the client can parse.""" """Replace error body with something the client can parse."""
def __init__(self, app): def __init__(self, app):
self.app = app self.app = app
@ -74,7 +75,11 @@ class ParsableErrorMiddleware(object):
title = '' title = ''
desc = '' desc = ''
code = err['faultcode'].lower() if 'faultcode' in err else '' error_code = err['faultstring'].lower() \
if 'faultstring' in err else ''
# 'container' is the service-name. The general form of the
# code is service-name.error-code.
code = '.'.join(['container', error_code])
errs.append({ errs.append({
'request_id': '', 'request_id': '',

View File

@ -20,16 +20,17 @@ Includes decorator for re-raising Zun-type exceptions.
import functools import functools
import inspect import inspect
from oslo_utils import uuidutils import re
import sys import sys
from webob import util as woutil
from keystoneclient import exceptions as keystone_exceptions from keystoneclient import exceptions as keystone_exceptions
from oslo_config import cfg from oslo_config import cfg
from oslo_log import log as logging from oslo_log import log as logging
from oslo_utils import excutils from oslo_utils import excutils
from oslo_utils import uuidutils
import pecan import pecan
import six import six
from webob import util as woutil
from zun.common.i18n import _ from zun.common.i18n import _
import zun.conf import zun.conf
@ -129,11 +130,19 @@ def wrap_controller_exception(func, func_server_error, func_client_error):
return wrapped return wrapped
def convert_excp_to_err_code(excp_name):
"""Convert Exception class name (CamelCase) to error-code (Snake-case)"""
words = re.findall(r'[A-Z]?[a-z]+|[A-Z]{2,}(?=[A-Z][a-z]|\d|\W|$)|\d+',
excp_name)
return '-'.join([str.lower(word) for word in words])
def wrap_pecan_controller_exception(func): def wrap_pecan_controller_exception(func):
"""This decorator wraps pecan controllers to handle exceptions.""" """This decorator wraps pecan controllers to handle exceptions."""
def _func_server_error(log_correlation_id, status_code): def _func_server_error(log_correlation_id, status_code):
pecan.response.status = status_code pecan.response.status = status_code
return { return {
'faultcode': 'Server',
'status_code': status_code, 'status_code': status_code,
'title': woutil.status_reasons[status_code], 'title': woutil.status_reasons[status_code],
'description': six.text_type(OBFUSCATED_MSG % log_correlation_id), 'description': six.text_type(OBFUSCATED_MSG % log_correlation_id),
@ -142,6 +151,8 @@ def wrap_pecan_controller_exception(func):
def _func_client_error(excp, status_code): def _func_client_error(excp, status_code):
pecan.response.status = status_code pecan.response.status = status_code
return { return {
'faultcode': 'Client',
'faultstring': convert_excp_to_err_code(excp.__class__.__name__),
'status_code': status_code, 'status_code': status_code,
'title': six.text_type(excp), 'title': six.text_type(excp),
'description': six.text_type(excp), 'description': six.text_type(excp),