Extract exception message from chain for API errors (#2100)

* Get message from excepiton chain

* cleanup
This commit is contained in:
Joakim Sørensen 2020-10-06 15:53:58 +02:00 committed by GitHub
parent 9dc2f43ffb
commit 17559bfc8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 11 deletions

View File

@ -567,7 +567,7 @@ class Addon(AddonModel):
raise AddonsError() from err
except DockerError as err:
self.state = AddonState.ERROR
raise AddonsError(err) from err
raise AddonsError() from err
else:
self.state = AddonState.STARTED

View File

@ -17,7 +17,8 @@ from ..const import (
RESULT_ERROR,
RESULT_OK,
)
from ..exceptions import APIError, APIForbidden, HassioError
from ..exceptions import APIError, APIForbidden, DockerAPIError, HassioError
from ..utils import check_exception_chain, get_message_from_exception_chain
from ..utils.log_format import format_message
@ -57,12 +58,8 @@ def api_process(method):
"""Return API information."""
try:
answer = await method(api, *args, **kwargs)
except (APIError, APIForbidden) as err:
return api_return_error(message=str(err))
except HassioError as err:
return api_return_error(
message=str(err) if err else "Unknown Error, see logs"
)
except (APIError, APIForbidden, HassioError) as err:
return api_return_error(error=err)
if isinstance(answer, dict):
return api_return_ok(data=answer)
@ -100,10 +97,17 @@ def api_process_raw(content):
return wrap_method
def api_return_error(message: Optional[str] = None) -> web.Response:
def api_return_error(error: Optional[Any] = None) -> web.Response:
"""Return an API error message."""
message = get_message_from_exception_chain(error)
if check_exception_chain(error, DockerAPIError):
message = format_message(message)
return web.json_response(
{JSON_RESULT: RESULT_ERROR, JSON_MESSAGE: format_message(message)}, status=400
{
JSON_RESULT: RESULT_ERROR,
JSON_MESSAGE: message or "Unknown error, see supervisor",
},
status=400,
)

View File

@ -121,3 +121,14 @@ def check_exception_chain(err: Exception, object_type: Any) -> bool:
return False
return check_exception_chain(err.__context__, object_type)
def get_message_from_exception_chain(err: Exception) -> str:
"""Get the first message from the exception chain."""
if str(err):
return str(err)
if not err.__context__:
return ""
return get_message_from_exception_chain(err.__context__)

View File

@ -1,6 +1,6 @@
"""Test exception helpers."""
from supervisor.utils import check_exception_chain
from supervisor.utils import check_exception_chain, get_message_from_exception_chain
def test_simple_chain_exception():
@ -55,3 +55,33 @@ def test_list_nested_chain_exception_not():
raise KeyError() from err
except KeyError as err:
assert not check_exception_chain(err, (AssertionError, OSError))
def test_simple_chain_exception_message():
"""Test simple chain of excepiton."""
try:
raise ValueError("error")
except ValueError as err:
assert get_message_from_exception_chain(err) == "error"
def test_simple_chain_exception_not_message():
"""Test simple chain of excepiton."""
try:
raise ValueError()
except ValueError as err:
assert not get_message_from_exception_chain(err)
def test_simple_nested_chain_exception_message():
"""Test simple nested chain of excepiton."""
try:
try:
raise ValueError("error")
except ValueError as err:
raise KeyError() from err
except KeyError as err:
assert get_message_from_exception_chain(err) == "error"