Fix exceptions in distil

Change-Id: Iabe1d9491dbbbe1d0de17b9dd12be2a423675b0b
This commit is contained in:
Lingxian Kong 2017-01-24 13:40:39 +13:00
parent 857f2e80ee
commit 32b9fb6c62
8 changed files with 35 additions and 100 deletions

View File

@ -42,7 +42,7 @@ class AuthTokenMiddleware(auth_token.AuthProtocol):
msg = _('Cannot compile public API routes: %s') % e
LOG.error(msg)
raise exceptions.InvalidConfig(error_msg=msg)
raise exceptions.InvalidConfig(msg)
super(AuthTokenMiddleware, self).__init__(app, conf)

View File

@ -55,19 +55,15 @@ def _get_usage_args():
@acl.enforce("rating:costs:get")
def costs_get():
project_id, start, end = _get_usage_args()
try:
# NOTE(flwang): Here using 'usage' instead of 'costs' for backward
# compatibility.
return api.render(usage=costs.get_costs(project_id, start, end))
except (exceptions.DateTimeException, exceptions.NotFoundException) as e:
return api.render(status=400, error=str(e))
# NOTE(flwang): Here using 'usage' instead of 'costs' for backward
# compatibility.
return api.render(usage=costs.get_costs(project_id, start, end))
@rest.get('/usages')
@acl.enforce("rating:usages:get")
def usage_get():
project_id, start, end = _get_usage_args()
try:
return api.render(usage=costs.get_usage(project_id, start, end))
except (exceptions.DateTimeException, exceptions.NotFoundException) as e:
return api.render(status=400, error=str(e))
return api.render(usage=costs.get_usage(project_id, start, end))

View File

@ -76,12 +76,11 @@ class Rest(flask.Blueprint):
try:
return func(**kwargs)
except ex.Forbidden as e:
return access_denied(e)
except ex.DistilException as e:
return bad_request(e)
LOG.error('Error during API call: %s' % str(e))
return render_error_message(e.code, e.message)
except Exception as e:
return internal_error(500, 'Internal Server Error', e)
return render_error_message(500, str(e))
f_rule = rule
self.add_url_rule(f_rule, endpoint, handler, **options)
@ -195,61 +194,13 @@ def abort_and_log(status_code, descr, exc=None):
flask.abort(status_code, description=descr)
def render_error_message(error_code, error_message, error_name):
def render_error_message(error_code, error_message):
message = {
"error_code": error_code,
"error_message": error_message,
"error_name": error_name
}
resp = render(message)
resp.status_code = error_code
return resp
def internal_error(status_code, descr, exc=None):
LOG.error(_LE("Request aborted with status code %(code)s and "
"message '%(message)s'"),
{'code': status_code, 'message': descr})
if exc is not None:
LOG.error(traceback.format_exc())
error_code = "INTERNAL_SERVER_ERROR"
if status_code == 501:
error_code = "NOT_IMPLEMENTED_ERROR"
return render_error_message(status_code, descr, error_code)
def bad_request(error):
error_code = 400
LOG.debug("Validation Error occurred: "
"error_code=%s, error_message=%s, error_name=%s",
error_code, error.message, error.code)
return render_error_message(error_code, error.message, error.code)
def access_denied(error):
error_code = 403
LOG.error(_LE("Access Denied: "
"error_code={code}, error_message={message}, "
"error_name={name}").format(code=error_code,
message=error.message,
name=error.code))
return render_error_message(error_code, error.message, error.code)
def not_found(error):
error_code = 404
LOG.debug("Not Found exception occurred: "
"error_code=%s, error_message=%s, error_name=%s",
error_code, error.message, error.code)
return render_error_message(error_code, error.message, error.code)

View File

@ -81,8 +81,9 @@ class JSONDeserializer(TextDeserializer):
try:
return jsonutils.loads(datastring)
except ValueError:
msg = _("cannot understand JSON")
raise exceptions.MalformedRequestBody(reason=msg)
raise exceptions.MalformedRequestBody(
"Malformed message body: cannot understand JSON"
)
def default(self, datastring):
return {'body': self._from_json(datastring)}

View File

@ -150,7 +150,9 @@ def project_get(project_id):
try:
return query.one()
except Exception:
raise exceptions.NotFoundException(project_id)
raise exceptions.NotFoundException(
"Project %s not found." % project_id
)
def usage_get(project_id, start, end):

View File

@ -12,7 +12,6 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_utils import uuidutils
import sys
from distil.i18n import _
@ -28,43 +27,35 @@ class DistilException(Exception):
a 'message' and 'code' properties.
"""
message = _("An unknown exception occurred")
code = "UNKNOWN_EXCEPTION"
code = 500
def __str__(self):
return self.message
def __init__(self):
def __init__(self, message=None):
if message is not None:
self.message = message
super(DistilException, self).__init__(
'%s: %s' % (self.code, self.message))
self.uuid = uuidutils.generate_uuid()
self.message = (_('%(message)s\nError ID: %(id)s')
% {'message': self.message, 'id': self.uuid})
class IncorrectStateError(DistilException):
code = "INCORRECT_STATE_ERROR"
def __init__(self, message):
self.message = message
message = _("Incorrect state.")
class NotFoundException(DistilException):
message = _("Object '%s' is not found")
value = None
def __init__(self, value, message=None):
self.code = "NOT_FOUND"
self.value = value
if message:
self.message = message % value
code = 404
message = _("Object not found.")
class DuplicateException(DistilException):
code = 409
message = _("An object with the same identifier already exists.")
class InvalidConfig(DistilException):
message = _("Invalid configuration file. %(error_msg)s")
message = _("Invalid configuration.")
class DBException(DistilException):
@ -72,21 +63,15 @@ class DBException(DistilException):
class MalformedRequestBody(DistilException):
message = _("Malformed message body: %(reason)s")
def __init__(self, reason):
formatted_message = self.message % {"reason": reason}
super(MalformedRequestBody, self).__init__(formatted_message)
code = 400
message = _("Malformed message body.")
class DateTimeException(DistilException):
code = 400
message = _("An unexpected date, date format, or date range was given.")
def __init__(self, message=None):
self.code = 400
self.message = message
class Forbidden(DistilException):
code = "FORBIDDEN"
code = 403
message = _("You are not authorized to complete this action")

View File

@ -40,8 +40,9 @@ class FileRater(rater.BaseRater):
} for row in reader
}
except Exception as e:
log.critical('Failed to load rates file: `%s`' % e)
exceptions.InvalidConfig(e)
msg = 'Failed to load rates file: `%s`' % e
log.critical(msg)
raise exceptions.InvalidConfig(msg)
def rate(self, name, region=None):
return {

View File

@ -60,8 +60,7 @@ def _validate_project_and_range(project_id, start, end):
message="End date must be greater than start.")
if not project_id:
raise exceptions.NotFoundException(value='project_id',
message="Missing parameter: %s")
raise exceptions.NotFoundException("Missing parameter: project_id")
valid_project = db_api.project_get(project_id)
return valid_project, start, end