From f3098418f26b0fff0f63f9e4a6cc0d3a8570a22b Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Fri, 23 Oct 2020 18:32:28 +0200 Subject: [PATCH] core: fix backup task not being registered, add fallback for api to remove info on ImportError celery only discovers tasks from installed apps, which `lib` is not, hence the schedule didn't trigger it --- passbook/admin/api/tasks.py | 32 ++++++++++------- .../templates/administration/task/list.html | 2 +- passbook/api/v2/urls.py | 6 ++-- passbook/core/tasks.py | 28 +++++++++++++++ passbook/lib/{tasks/__init__.py => tasks.py} | 4 +++ passbook/lib/tasks/backup.py | 34 ------------------- passbook/root/settings.py | 2 +- 7 files changed, 57 insertions(+), 51 deletions(-) rename passbook/lib/{tasks/__init__.py => tasks.py} (97%) delete mode 100644 passbook/lib/tasks/backup.py diff --git a/passbook/admin/api/tasks.py b/passbook/admin/api/tasks.py index a11741f82..3ba020d96 100644 --- a/passbook/admin/api/tasks.py +++ b/passbook/admin/api/tasks.py @@ -50,15 +50,23 @@ class TaskViewSet(ViewSet): task = TaskInfo.by_name(pk) if not task: raise Http404 - task_module = import_module(task.task_call_module) - task_func = getattr(task_module, task.task_call_func) - task_func.delay(*task.task_call_args, **task.task_call_kwargs) - messages.success( - self.request, - _("Successfully re-scheduled Task %(name)s!" % {"name": task.task_name}), - ) - return Response( - { - "successful": True, - } - ) + try: + task_module = import_module(task.task_call_module) + task_func = getattr(task_module, task.task_call_func) + task_func.delay(*task.task_call_args, **task.task_call_kwargs) + messages.success( + self.request, + _( + "Successfully re-scheduled Task %(name)s!" + % {"name": task.task_name} + ), + ) + return Response( + { + "successful": True, + } + ) + except ImportError: + # if we get an import error, the module path has probably changed + task.delete() + return Response({"successful": False}) diff --git a/passbook/admin/templates/administration/task/list.html b/passbook/admin/templates/administration/task/list.html index b98197ebe..d3f38ebb9 100644 --- a/passbook/admin/templates/administration/task/list.html +++ b/passbook/admin/templates/administration/task/list.html @@ -21,7 +21,7 @@ {% trans 'Identifier' %} {% trans 'Description' %} - {% trans 'Last Status' %} + {% trans 'Last Run' %} {% trans 'Status' %} {% trans 'Messages' %} diff --git a/passbook/api/v2/urls.py b/passbook/api/v2/urls.py index 72240cfc7..9b2dd54d8 100644 --- a/passbook/api/v2/urls.py +++ b/passbook/api/v2/urls.py @@ -68,6 +68,9 @@ router.register("core/tokens", TokenViewSet) router.register("outposts/outposts", OutpostViewSet) router.register("outposts/proxy", OutpostConfigViewSet) +router.register("flows/instances", FlowViewSet) +router.register("flows/bindings", FlowStageBindingViewSet) + router.register("crypto/certificatekeypairs", CertificateKeyPairViewSet) router.register("audit/events", EventViewSet) @@ -114,9 +117,6 @@ router.register("stages/user_login", UserLoginStageViewSet) router.register("stages/user_logout", UserLogoutStageViewSet) router.register("stages/user_write", UserWriteStageViewSet) -router.register("flows/instances", FlowViewSet) -router.register("flows/bindings", FlowStageBindingViewSet) - router.register("stages/dummy", DummyStageViewSet) router.register("policies/dummy", DummyPolicyViewSet) diff --git a/passbook/core/tasks.py b/passbook/core/tasks.py index 2822458d4..65d9da22d 100644 --- a/passbook/core/tasks.py +++ b/passbook/core/tasks.py @@ -1,4 +1,11 @@ """passbook core tasks""" +from datetime import datetime +from io import StringIO + +from boto3.exceptions import Boto3Error +from botocore.exceptions import BotoCoreError, ClientError +from django.contrib.humanize.templatetags.humanize import naturaltime +from django.core import management from django.utils.timezone import now from structlog import get_logger @@ -24,3 +31,24 @@ def clean_expired_models(self: MonitoredTask): LOGGER.debug("Deleted expired models", model=cls, amount=amount) messages.append(f"Deleted {amount} expired {cls._meta.verbose_name_plural}") self.set_status(TaskResult(TaskResultStatus.SUCCESSFUL, messages)) + + +@CELERY_APP.task(bind=True, base=MonitoredTask) +def backup_database(self: MonitoredTask): # pragma: no cover + """Database backup""" + try: + start = datetime.now() + out = StringIO() + management.call_command("dbbackup", quiet=True, stdout=out) + self.set_status( + TaskResult( + TaskResultStatus.SUCCESSFUL, + [ + f"Successfully finished database backup {naturaltime(start)}", + out.getvalue(), + ], + ) + ) + LOGGER.info("Successfully backed up database.") + except (IOError, BotoCoreError, ClientError, Boto3Error) as exc: + self.set_status(TaskResult(TaskResultStatus.ERROR).with_error(exc)) diff --git a/passbook/lib/tasks/__init__.py b/passbook/lib/tasks.py similarity index 97% rename from passbook/lib/tasks/__init__.py rename to passbook/lib/tasks.py index 6e9473a18..e00d3cb3d 100644 --- a/passbook/lib/tasks/__init__.py +++ b/passbook/lib/tasks.py @@ -62,6 +62,10 @@ class TaskInfo: """Get TaskInfo Object by name""" return cache.get(f"task_{name}") + def delete(self): + """Delete task info from cache""" + return cache.delete(f"task_{self.task_name}") + def save(self): """Save task into cache""" key = f"task_{self.task_name}" diff --git a/passbook/lib/tasks/backup.py b/passbook/lib/tasks/backup.py deleted file mode 100644 index 94707df54..000000000 --- a/passbook/lib/tasks/backup.py +++ /dev/null @@ -1,34 +0,0 @@ -"""Database backup task""" -from datetime import datetime -from io import StringIO - -from botocore.exceptions import BotoCoreError, ClientError -from django.contrib.humanize.templatetags.humanize import naturaltime -from django.core import management -from structlog import get_logger - -from passbook.lib.tasks import MonitoredTask, TaskResult, TaskResultStatus -from passbook.root.celery import CELERY_APP - -LOGGER = get_logger() - - -@CELERY_APP.task(bind=True, base=MonitoredTask) -def backup_database(self: MonitoredTask): # pragma: no cover - """Database backup""" - try: - start = datetime.now() - out = StringIO() - management.call_command("dbbackup", quiet=True, stdout=out) - self.set_status( - TaskResult( - TaskResultStatus.SUCCESSFUL, - [ - f"Successfully finished database backup {naturaltime(start)}", - out.getvalue(), - ], - ) - ) - LOGGER.info("Successfully backed up database.") - except (IOError, BotoCoreError, ClientError) as exc: - self.set_status(TaskResult(TaskResultStatus.ERROR).with_error(exc)) diff --git a/passbook/root/settings.py b/passbook/root/settings.py index 9e4e46ed5..cd3b8ef8c 100644 --- a/passbook/root/settings.py +++ b/passbook/root/settings.py @@ -273,7 +273,7 @@ CELERY_BEAT_SCHEDULE = { "options": {"queue": "passbook_scheduled"}, }, "db_backup": { - "task": "passbook.lib.tasks.backup.backup_database", + "task": "passbook.core.tasks.backup_database", "schedule": crontab(minute=0, hour=0), "options": {"queue": "passbook_scheduled"}, },