outposts/k8s: improve error handling

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-08-28 14:51:04 +02:00
parent f61736e3d1
commit 582ad92c76
4 changed files with 17 additions and 15 deletions

View file

@ -3,10 +3,11 @@ from typing import TYPE_CHECKING, Generic, TypeVar
from django.utils.text import slugify from django.utils.text import slugify
from kubernetes.client import V1ObjectMeta from kubernetes.client import V1ObjectMeta
from kubernetes.client.exceptions import ApiException, OpenApiException
from kubernetes.client.models.v1_deployment import V1Deployment from kubernetes.client.models.v1_deployment import V1Deployment
from kubernetes.client.models.v1_pod import V1Pod from kubernetes.client.models.v1_pod import V1Pod
from kubernetes.client.rest import ApiException
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
from urllib3.exceptions import HTTPError
from authentik import __version__ from authentik import __version__
from authentik.lib.sentry import SentryIgnoredException from authentik.lib.sentry import SentryIgnoredException
@ -72,8 +73,9 @@ class KubernetesObjectReconciler(Generic[T]):
try: try:
try: try:
current = self.retrieve() current = self.retrieve()
except ApiException as exc: except (OpenApiException, HTTPError) as exc:
if exc.status == 404: # pylint: disable=no-member
if isinstance(exc, ApiException) and exc.status == 404:
self.logger.debug("Failed to get current, triggering recreate") self.logger.debug("Failed to get current, triggering recreate")
raise NeedsRecreate from exc raise NeedsRecreate from exc
self.logger.debug("Other unhandled error", exc=exc) self.logger.debug("Other unhandled error", exc=exc)
@ -104,8 +106,9 @@ class KubernetesObjectReconciler(Generic[T]):
current = self.retrieve() current = self.retrieve()
self.delete(current) self.delete(current)
self.logger.debug("Removing") self.logger.debug("Removing")
except ApiException as exc: except (OpenApiException, HTTPError) as exc:
if exc.status == 404: # pylint: disable=no-member
if isinstance(exc, ApiException) and exc.status == 404:
self.logger.debug("Failed to get current, assuming non-existant") self.logger.debug("Failed to get current, assuming non-existant")
return return
self.logger.debug("Other unhandled error", exc=exc) self.logger.debug("Other unhandled error", exc=exc)

View file

@ -3,8 +3,9 @@ from io import StringIO
from typing import Type from typing import Type
from kubernetes.client.api_client import ApiClient from kubernetes.client.api_client import ApiClient
from kubernetes.client.exceptions import ApiException from kubernetes.client.exceptions import OpenApiException
from structlog.testing import capture_logs from structlog.testing import capture_logs
from urllib3.exceptions import HTTPError
from yaml import dump_all from yaml import dump_all
from authentik.outposts.controllers.base import BaseController, ControllerException from authentik.outposts.controllers.base import BaseController, ControllerException
@ -12,7 +13,7 @@ from authentik.outposts.controllers.k8s.base import KubernetesObjectReconciler
from authentik.outposts.controllers.k8s.deployment import DeploymentReconciler from authentik.outposts.controllers.k8s.deployment import DeploymentReconciler
from authentik.outposts.controllers.k8s.secret import SecretReconciler from authentik.outposts.controllers.k8s.secret import SecretReconciler
from authentik.outposts.controllers.k8s.service import ServiceReconciler from authentik.outposts.controllers.k8s.service import ServiceReconciler
from authentik.outposts.models import KubernetesServiceConnection, Outpost from authentik.outposts.models import KubernetesServiceConnection, Outpost, ServiceConnectionInvalid
class KubernetesController(BaseController): class KubernetesController(BaseController):
@ -40,7 +41,7 @@ class KubernetesController(BaseController):
reconciler = self.reconcilers[reconcile_key](self) reconciler = self.reconcilers[reconcile_key](self)
reconciler.up() reconciler.up()
except ApiException as exc: except (OpenApiException, HTTPError, ServiceConnectionInvalid) as exc:
raise ControllerException(str(exc)) from exc raise ControllerException(str(exc)) from exc
def up_with_logs(self) -> list[str]: def up_with_logs(self) -> list[str]:
@ -55,7 +56,7 @@ class KubernetesController(BaseController):
reconciler.up() reconciler.up()
all_logs += [f"{reconcile_key.title()}: {x['event']}" for x in logs] all_logs += [f"{reconcile_key.title()}: {x['event']}" for x in logs]
return all_logs return all_logs
except ApiException as exc: except (OpenApiException, HTTPError, ServiceConnectionInvalid) as exc:
raise ControllerException(str(exc)) from exc raise ControllerException(str(exc)) from exc
def down(self): def down(self):
@ -65,7 +66,7 @@ class KubernetesController(BaseController):
self.logger.debug("Tearing down object", name=reconcile_key) self.logger.debug("Tearing down object", name=reconcile_key)
reconciler.down() reconciler.down()
except ApiException as exc: except (OpenApiException, HTTPError, ServiceConnectionInvalid) as exc:
raise ControllerException(str(exc)) from exc raise ControllerException(str(exc)) from exc
def down_with_logs(self) -> list[str]: def down_with_logs(self) -> list[str]:
@ -80,7 +81,7 @@ class KubernetesController(BaseController):
reconciler.down() reconciler.down()
all_logs += [f"{reconcile_key.title()}: {x['event']}" for x in logs] all_logs += [f"{reconcile_key.title()}: {x['event']}" for x in logs]
return all_logs return all_logs
except ApiException as exc: except (OpenApiException, HTTPError, ServiceConnectionInvalid) as exc:
raise ControllerException(str(exc)) from exc raise ControllerException(str(exc)) from exc
def get_static_deployment(self) -> str: def get_static_deployment(self) -> str:

View file

@ -365,7 +365,7 @@ class Outpost(ManagedModel):
) )
try: try:
assign_perm(code_name, user, model_or_perm) assign_perm(code_name, user, model_or_perm)
except Permission.DoesNotExist as exc: except (Permission.DoesNotExist, AttributeError) as exc:
LOGGER.warning( LOGGER.warning(
"permission doesn't exist", "permission doesn't exist",
code_name=code_name, code_name=code_name,

View file

@ -32,9 +32,7 @@ PLAN_CONTEXT_METHOD_ARGS = "auth_method_args"
SESSION_INVALID_TRIES = "user_invalid_tries" SESSION_INVALID_TRIES = "user_invalid_tries"
def authenticate( def authenticate(request: HttpRequest, backends: list[str], **credentials: Any) -> Optional[User]:
request: HttpRequest, backends: list[str], **credentials: dict[str, Any]
) -> Optional[User]:
"""If the given credentials are valid, return a User object. """If the given credentials are valid, return a User object.
Customized version of django's authenticate, which accepts a list of backends""" Customized version of django's authenticate, which accepts a list of backends"""