(feature) add Django setup flow for initial pobsync configuration
Add staff-only UI routes for creating/editing the default GlobalConfig and creating the first HostConfig from the dashboard. Improve the empty dashboard state so a fresh database guides the user towards the next useful setup action instead of only showing empty tables. Cover the setup flow with view tests for empty state prompts, global config creation, and host creation.
This commit is contained in:
@@ -47,6 +47,102 @@ class ViewTests(TestCase):
|
||||
self.assertContains(response, "20260519-021500Z__ABCDEFGH")
|
||||
self.assertContains(response, "success")
|
||||
|
||||
def test_dashboard_prompts_for_global_config_when_database_is_empty(self) -> None:
|
||||
self.client.force_login(self.staff_user)
|
||||
|
||||
response = self.client.get(reverse("dashboard"))
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "No default global config exists yet.")
|
||||
self.assertContains(response, reverse("edit_global_config"))
|
||||
self.assertContains(response, "Create global config")
|
||||
|
||||
def test_dashboard_prompts_for_first_host_after_global_config_exists(self) -> None:
|
||||
self.client.force_login(self.staff_user)
|
||||
GlobalConfig.objects.create(name="default", backup_root="/opt/pobsync/backups")
|
||||
|
||||
response = self.client.get(reverse("dashboard"))
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Global config is ready.")
|
||||
self.assertContains(response, reverse("create_host_config"))
|
||||
self.assertContains(response, "Add first host")
|
||||
|
||||
def test_global_config_form_creates_default_config(self) -> None:
|
||||
self.client.force_login(self.staff_user)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("edit_global_config"),
|
||||
{
|
||||
"name": "default",
|
||||
"backup_root": "/backups",
|
||||
"pobsync_home": "/opt/pobsync",
|
||||
"ssh_user": "backup",
|
||||
"ssh_port": "2222",
|
||||
"ssh_options": "StrictHostKeyChecking=no\nBatchMode=yes",
|
||||
"rsync_binary": "rsync",
|
||||
"rsync_args": "-a\n--numeric-ids",
|
||||
"rsync_extra_args": "--delete",
|
||||
"rsync_timeout_seconds": "60",
|
||||
"rsync_bwlimit_kbps": "1000",
|
||||
"default_source_root": "/srv",
|
||||
"default_destination_subdir": "rootfs",
|
||||
"excludes_default": "*.tmp\ncache/",
|
||||
"retention_daily": "7",
|
||||
"retention_weekly": "4",
|
||||
"retention_monthly": "2",
|
||||
"retention_yearly": "1",
|
||||
},
|
||||
follow=True,
|
||||
)
|
||||
|
||||
self.assertRedirects(response, reverse("dashboard"))
|
||||
self.assertContains(response, "Global config saved for default.")
|
||||
config = GlobalConfig.objects.get(name="default")
|
||||
self.assertEqual(config.backup_root, "/backups")
|
||||
self.assertEqual(config.ssh_user, "backup")
|
||||
self.assertEqual(config.ssh_port, 2222)
|
||||
self.assertEqual(config.ssh_options, ["StrictHostKeyChecking=no", "BatchMode=yes"])
|
||||
self.assertEqual(config.rsync_args, ["-a", "--numeric-ids"])
|
||||
self.assertEqual(config.rsync_extra_args, ["--delete"])
|
||||
self.assertEqual(config.excludes_default, ["*.tmp", "cache/"])
|
||||
self.assertEqual(config.retention_daily, 7)
|
||||
self.assertEqual(config.retention_yearly, 1)
|
||||
|
||||
def test_create_host_config_form_creates_host(self) -> None:
|
||||
self.client.force_login(self.staff_user)
|
||||
|
||||
response = self.client.post(
|
||||
reverse("create_host_config"),
|
||||
{
|
||||
"host": "web-01",
|
||||
"address": "web-01.example.test",
|
||||
"enabled": "on",
|
||||
"ssh_user": "backup",
|
||||
"ssh_port": "2222",
|
||||
"source_root": "/srv",
|
||||
"includes": "/srv/www\n/srv/db",
|
||||
"excludes_add": "*.tmp",
|
||||
"excludes_replace": "",
|
||||
"rsync_extra_args": "--numeric-ids",
|
||||
"retention_daily": "7",
|
||||
"retention_weekly": "4",
|
||||
"retention_monthly": "2",
|
||||
"retention_yearly": "1",
|
||||
},
|
||||
follow=True,
|
||||
)
|
||||
|
||||
self.assertRedirects(response, reverse("host_detail", args=["web-01"]))
|
||||
self.assertContains(response, "Host config created for web-01.")
|
||||
host = HostConfig.objects.get(host="web-01")
|
||||
self.assertEqual(host.address, "web-01.example.test")
|
||||
self.assertEqual(host.ssh_user, "backup")
|
||||
self.assertEqual(host.includes, ["/srv/www", "/srv/db"])
|
||||
self.assertEqual(host.excludes_add, ["*.tmp"])
|
||||
self.assertEqual(host.rsync_extra_args, ["--numeric-ids"])
|
||||
self.assertEqual(host.retention_weekly, 4)
|
||||
|
||||
def test_host_detail_renders_config_schedule_runs_and_snapshots(self) -> None:
|
||||
self.client.force_login(self.staff_user)
|
||||
host = HostConfig.objects.create(
|
||||
|
||||
Reference in New Issue
Block a user