refactor: stop using legacy JSON for runtime config
Build runtime pobsync configuration exclusively from structured SQL fields, leaving legacy JSON only for import and audit context. Add SQL-first management commands for global and host configuration and cover them with tests.
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
|
||||
from pobsync.cli import parse_retention
|
||||
from pobsync.commands.install import DEFAULT_EXCLUDES, DEFAULT_RSYNC_ARGS
|
||||
from pobsync.util import is_absolute_non_root
|
||||
from pobsync_backend.models import GlobalConfig
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Create or update the SQL-backed global pobsync configuration."
|
||||
|
||||
def add_arguments(self, parser) -> None:
|
||||
parser.add_argument("--name", default="default")
|
||||
parser.add_argument("--backup-root", required=True)
|
||||
parser.add_argument("--pobsync-home", default=settings.POBSYNC_HOME)
|
||||
parser.add_argument("--ssh-user", default="root")
|
||||
parser.add_argument("--ssh-port", type=int, default=22)
|
||||
parser.add_argument("--source-root", default="/")
|
||||
parser.add_argument("--retention", default="daily=14,weekly=8,monthly=12,yearly=0")
|
||||
parser.add_argument("--force", action="store_true", help="Update existing config")
|
||||
|
||||
def handle(self, *args: Any, **options: Any) -> None:
|
||||
backup_root = options["backup_root"]
|
||||
if not is_absolute_non_root(backup_root):
|
||||
raise CommandError("--backup-root must be an absolute path and must not be '/'")
|
||||
|
||||
pobsync_home = str(Path(options["pobsync_home"]))
|
||||
retention = parse_retention(options["retention"])
|
||||
defaults = {
|
||||
"backup_root": backup_root,
|
||||
"pobsync_home": pobsync_home,
|
||||
"ssh_user": options["ssh_user"],
|
||||
"ssh_port": options["ssh_port"],
|
||||
"ssh_options": ["-oBatchMode=yes", "-oStrictHostKeyChecking=accept-new"],
|
||||
"rsync_binary": "rsync",
|
||||
"rsync_args": DEFAULT_RSYNC_ARGS,
|
||||
"rsync_extra_args": [],
|
||||
"rsync_timeout_seconds": 0,
|
||||
"rsync_bwlimit_kbps": 0,
|
||||
"default_source_root": options["source_root"],
|
||||
"default_destination_subdir": "",
|
||||
"excludes_default": DEFAULT_EXCLUDES,
|
||||
"retention_daily": retention["daily"],
|
||||
"retention_weekly": retention["weekly"],
|
||||
"retention_monthly": retention["monthly"],
|
||||
"retention_yearly": retention["yearly"],
|
||||
}
|
||||
|
||||
if GlobalConfig.objects.filter(name=options["name"]).exists() and not options["force"]:
|
||||
raise CommandError(f"GlobalConfig {options['name']!r} already exists; use --force to update")
|
||||
|
||||
_obj, created = GlobalConfig.objects.update_or_create(name=options["name"], defaults=defaults)
|
||||
action = "Created" if created else "Updated"
|
||||
self.stdout.write(self.style.SUCCESS(f"{action} GlobalConfig {options['name']!r}."))
|
||||
Reference in New Issue
Block a user