[docs]classDockerNotFoundException(Exception):""" Exception if docker client cannot communicate with dockerd"""
[docs]classDockerImageException(Exception):""" Exception while handling a docker image in the workspace"""
[docs]classDockerNetworkException(Exception):""" Exception while handling docker networks in the workspace """
[docs]classDockerContainerException(Exception):""" Exception while handling a docker container in the workspace"""
[docs]classRuntime400Exception(Exception):"""Exception for all errors in Daemon - Should only be used in `api/endpoints/*.py`. - Should always be chained. - Handled by `daemon_runtime_exception_handler` """
[docs]classPartialDaemon400Exception(Exception):"""Exception for all errors in Partial Daemon This can be raised from 2 places: 1. Inside partial daemon: - Should always be chained and raised in `a[i/partial/endpoints/*.py`. - This way it has a `__cause__` and stacktrace can be retrieved in `partial_daemon_exception_handler` 2. Inside main store: - Should be raised whenever main-daemon receives a 400 from partial-daemon. - Don't chain it. Raise it like - `PartialDaemon400Exception('original traceback')` - Gets handled via `daemon_runtime_exception_handler` when chained with `Runtime400Exception` """def__init__(self,message:Union[List,str]=None,*args:object)->None:self.message=message
[docs]classPartialDaemonConnectionException(PartialDaemon400Exception):""" Exception if JinaD cannot connect to Partial Daemon"""
def_get_exception(ex:Exception)->Exception:"""Get exception cause/context from chained exceptions :param ex: chained exception :return: cause of chained exception if any """ifex.__cause__:returnex.__cause__elifex.__context__:returnex.__context__else:returnex
[docs]defjson_response(status_code:HTTPStatus,detail:str,body:str)->JSONResponse:"""json response from status, detail & body :param status_code: http status code :param detail: exception name in detail :param body: error stacktrace :return: JSONResponse object """returnJSONResponse(status_code=status_code,content=jsonable_encoder({'detail':detail,'body':body,}),)
[docs]asyncdefpartial_daemon_exception_handler(request:Request,ex:'PartialDaemon400Exception'):"""Exception handler for all PartialDaemon400Exceptions Since `PartialDaemon400Exception` is always chained, we access the `__cause__` and send that as `body`. This handler makes sure, in case of exceptions (Pod/Deployment/Flow start/update/delete failures), the response from Partial Daemon whould always look like - ```{ "detail": "PartialDaemon400Exception", "body": [ "stack trace line1" "stack trace line2: ] }``` :param request: starlette request :param ex: actual PartialDaemon400Exception :return: json response representing the error """exception=_get_exception(ex)returnjson_response(status_code=HTTPStatus.BAD_REQUEST,detail=ex.__class__.__name__,body=traceback.format_exception(etype=type(exception),value=exception,tb=exception.__traceback__),)
[docs]asyncdefdaemon_runtime_exception_handler(request:Request,ex:'Runtime400Exception'):"""Exception handler for all Runtime400Exceptions `Runtime400Exception` is always chained. - When `__cause__` is `PartialDaemon400Exception`, we know, it is due to an error inside the Partial Daemon container and `ex.message` carries the actual stack trace. - All other errors are inside the main Daemon itself, so we get the stack trace using traceback. :param request: starlette request :param ex: actual Runtime400Exception :return: json response representing the error """exception=_get_exception(ex)returnjson_response(status_code=HTTPStatus.BAD_REQUEST,detail=ex.__class__.__name__,body=exception.messageifisinstance(exception,PartialDaemon400Exception)elsetraceback.format_exception(etype=type(exception),value=exception,tb=exception.__traceback__),)
[docs]asyncdefvalidation_exception_handler(request:Request,ex:'RequestValidationError'):"""Exception handler for all RequestValidationError raised by pydantic :param request: starlette request :param ex: actual Validation exception :return: json response representing the error """returnjson_response(status_code=HTTPStatus.UNPROCESSABLE_ENTITY,detail=ex.errors(),body=str(ex),)