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"},
},