outposts/k8s: improve error handling
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
f61736e3d1
commit
582ad92c76
|
@ -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)
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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"""
|
||||||
|
|
Reference in a new issue