(feature) Add staff-only service status API

Add /api/status/ for quick inspection of database backend, object counts, latest
backup run, and latest scheduler activity. Link it from the API index and reuse
schedule serialization between host summaries and status output.

Cover the endpoint with a focused API test and document the new status URL.
This commit is contained in:
2026-05-19 11:46:22 +02:00
parent ccd89119da
commit 2778a589ea
4 changed files with 88 additions and 9 deletions

View File

@@ -4,6 +4,7 @@ from datetime import datetime, timezone
from django.contrib.auth import get_user_model
from django.test import TestCase
from django.utils import timezone as django_timezone
from pobsync_backend.models import BackupRun, HostConfig, ScheduleConfig, SnapshotRecord
@@ -80,10 +81,47 @@ class ApiTests(TestCase):
self.assertEqual(response.status_code, 200)
endpoints = response.json()["endpoints"]
self.assertEqual(endpoints["status"], "http://testserver/api/status/")
self.assertEqual(endpoints["hosts"], "http://testserver/api/hosts/")
self.assertEqual(endpoints["snapshots"], "http://testserver/api/snapshots/")
self.assertEqual(endpoints["runs"], "http://testserver/api/runs/")
def test_status_endpoint_returns_counts_and_latest_activity(self) -> None:
self.client.force_login(self.staff_user)
host = HostConfig.objects.create(host="web-01", address="web-01.example.test")
schedule = ScheduleConfig.objects.create(
host=host,
cron_expr="15 2 * * *",
enabled=True,
prune=True,
last_due_key="202605190215",
last_status="success",
last_started_at=django_timezone.now(),
)
snapshot = self._snapshot(host, "20260519-021500Z__ABCDEFGH")
BackupRun.objects.create(
host=host,
status=BackupRun.Status.SUCCESS,
snapshot=snapshot,
started_at=datetime(2026, 5, 19, 2, 15, tzinfo=timezone.utc),
)
response = self.client.get("/api/status/")
self.assertEqual(response.status_code, 200)
payload = response.json()
self.assertTrue(payload["ok"])
self.assertEqual(payload["database"]["vendor"], "sqlite")
self.assertEqual(payload["counts"]["hosts"], 1)
self.assertEqual(payload["counts"]["enabled_hosts"], 1)
self.assertEqual(payload["counts"]["enabled_schedules"], 1)
self.assertEqual(payload["counts"]["snapshots"], 1)
self.assertEqual(payload["counts"]["runs"], 1)
self.assertEqual(payload["latest_run"]["host"], host.host)
self.assertEqual(payload["latest_run"]["snapshot"]["dirname"], snapshot.dirname)
self.assertEqual(payload["latest_schedule"]["host"], host.host)
self.assertEqual(payload["latest_schedule"]["last_due_key"], schedule.last_due_key)
def _snapshot(
self,
host: HostConfig,