refactor: use injected config sources for retention

Allow retention planning and pruning to use the same ConfigSource
abstraction as scheduled backups. This removes the remaining SQL-to-YAML
export dependency from Django backup runs with pruning, keeping YAML only
as a legacy CLI compatibility path.
This commit is contained in:
2026-05-19 05:00:15 +02:00
parent bb44f8a09c
commit 100215bf11
6 changed files with 74 additions and 16 deletions

View File

@@ -9,7 +9,6 @@ from django.utils import timezone
from pobsync.commands.run_scheduled import run_scheduled
from pobsync.paths import PobsyncPaths
from pobsync_backend.config_repository import export_runtime_configs
from pobsync_backend.config_source import DjangoConfigSource
from pobsync_backend.models import BackupRun, HostConfig
@@ -33,11 +32,6 @@ class Command(BaseCommand):
except HostConfig.DoesNotExist as exc:
raise CommandError(f"Missing enabled HostConfig {host_name!r}") from exc
# Compatibility bridge: retention planning still reads runtime YAML.
# The backup run itself receives config directly from Django.
if options["prune"]:
export_runtime_configs(prefix=paths.home, host=host.host)
run = BackupRun.objects.create(
host=host,
run_type=BackupRun.RunType.SCHEDULED,

View File

@@ -0,0 +1,53 @@
from __future__ import annotations
from datetime import datetime, timezone
from pathlib import Path
from tempfile import TemporaryDirectory
from django.test import SimpleTestCase
from pobsync.commands.retention_plan import run_retention_plan
from pobsync.util import write_yaml_atomic
class FakeConfigSource:
def __init__(self, backup_root: str) -> None:
self.backup_root = backup_root
def effective_config_for_host(self, host: str) -> dict:
return {
"backup_root": self.backup_root,
"host": host,
"address": "example.test",
"retention": {"daily": 1, "weekly": 0, "monthly": 0, "yearly": 0},
}
class RetentionConfigSourceTests(SimpleTestCase):
def test_retention_plan_uses_injected_config_source(self) -> None:
with TemporaryDirectory() as tmp:
root = Path(tmp) / "backups"
snap_dir = root / "web-01" / "scheduled" / "20260519-021500Z__ABCDEFGH"
meta_dir = snap_dir / "meta"
meta_dir.mkdir(parents=True)
write_yaml_atomic(
meta_dir / "meta.yaml",
{
"status": "success",
"started_at": datetime(2026, 5, 19, 2, 15, tzinfo=timezone.utc)
.isoformat()
.replace("+00:00", "Z"),
},
)
plan = run_retention_plan(
prefix=Path("/missing-prefix"),
host="web-01",
kind="scheduled",
protect_bases=False,
config_source=FakeConfigSource(str(root)),
)
self.assertTrue(plan["ok"])
self.assertEqual(plan["keep"], ["20260519-021500Z__ABCDEFGH"])
self.assertEqual(plan["delete"], [])