(feature) queue manual backups from the Django host page
Add a staff-only manual backup form to host detail pages with safe dry-run defaults and optional retention settings. Queue manual BackupRun records through the existing worker-backed runner path instead of executing backups inside the web request. Validate disabled hosts, missing global config, and invalid methods with view tests covering the new UI flow.
This commit is contained in:
@@ -180,6 +180,8 @@ class ViewTests(TestCase):
|
||||
self.assertContains(response, "Discover snapshots")
|
||||
self.assertContains(response, "Edit schedule")
|
||||
self.assertContains(response, "Edit config")
|
||||
self.assertContains(response, "Queue Manual Backup")
|
||||
self.assertContains(response, reverse("queue_manual_backup", args=[host.host]))
|
||||
self.assertContains(response, reverse("run_detail", args=[BackupRun.objects.get().id]))
|
||||
self.assertContains(response, reverse("snapshot_detail", args=[snapshot.id]))
|
||||
|
||||
@@ -190,6 +192,66 @@ class ViewTests(TestCase):
|
||||
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
def test_queue_manual_backup_creates_queued_run_and_redirects_to_run_detail(self) -> None:
|
||||
self.client.force_login(self.staff_user)
|
||||
GlobalConfig.objects.create(name="default", backup_root="/backups")
|
||||
host = HostConfig.objects.create(host="web-01", address="web-01.example.test")
|
||||
|
||||
response = self.client.post(
|
||||
reverse("queue_manual_backup", args=[host.host]),
|
||||
{
|
||||
"dry_run": "on",
|
||||
"prune": "on",
|
||||
"prune_max_delete": "4",
|
||||
"prune_protect_bases": "on",
|
||||
},
|
||||
follow=True,
|
||||
)
|
||||
|
||||
run = BackupRun.objects.get(host=host)
|
||||
self.assertRedirects(response, reverse("run_detail", args=[run.id]))
|
||||
self.assertContains(response, f"Queued manual backup run {run.id} for web-01.")
|
||||
self.assertEqual(run.status, BackupRun.Status.QUEUED)
|
||||
self.assertEqual(run.run_type, BackupRun.RunType.MANUAL)
|
||||
self.assertEqual(
|
||||
run.result["requested"],
|
||||
{
|
||||
"dry_run": True,
|
||||
"prune": True,
|
||||
"prune_max_delete": 4,
|
||||
"prune_protect_bases": True,
|
||||
},
|
||||
)
|
||||
|
||||
def test_queue_manual_backup_requires_default_global_config(self) -> None:
|
||||
self.client.force_login(self.staff_user)
|
||||
host = HostConfig.objects.create(host="web-01", address="web-01.example.test")
|
||||
|
||||
response = self.client.post(reverse("queue_manual_backup", args=[host.host]), {"dry_run": "on"}, follow=True)
|
||||
|
||||
self.assertRedirects(response, reverse("host_detail", args=[host.host]))
|
||||
self.assertContains(response, "Create the default global config before queueing backups.")
|
||||
self.assertFalse(BackupRun.objects.exists())
|
||||
|
||||
def test_queue_manual_backup_rejects_disabled_host(self) -> None:
|
||||
self.client.force_login(self.staff_user)
|
||||
GlobalConfig.objects.create(name="default", backup_root="/backups")
|
||||
host = HostConfig.objects.create(host="web-01", address="web-01.example.test", enabled=False)
|
||||
|
||||
response = self.client.post(reverse("queue_manual_backup", args=[host.host]), {"dry_run": "on"}, follow=True)
|
||||
|
||||
self.assertRedirects(response, reverse("host_detail", args=[host.host]))
|
||||
self.assertContains(response, "Cannot queue backup for disabled host web-01.")
|
||||
self.assertFalse(BackupRun.objects.exists())
|
||||
|
||||
def test_queue_manual_backup_requires_post(self) -> None:
|
||||
self.client.force_login(self.staff_user)
|
||||
host = HostConfig.objects.create(host="web-01", address="web-01.example.test")
|
||||
|
||||
response = self.client.get(reverse("queue_manual_backup", args=[host.host]))
|
||||
|
||||
self.assertEqual(response.status_code, 405)
|
||||
|
||||
def test_run_detail_renders_result_payload(self) -> None:
|
||||
self.client.force_login(self.staff_user)
|
||||
host = HostConfig.objects.create(host="web-01", address="web-01.example.test")
|
||||
|
||||
Reference in New Issue
Block a user