(feature) Add global and effective host config checks

Introduce reusable configuration checks for global settings and effective
host runtime configuration. The checks now surface risky backup settings
such as missing recursive rsync args, missing critical root excludes,
invalid SSH settings, missing credentials, and retention gaps.

Show these checks on the global config form, host edit form, and host
detail page so operators can validate the compounded host/global config
before starting real backup runs.
This commit is contained in:
2026-05-19 20:24:29 +02:00
parent 7e5d31d53b
commit 088f43279e
6 changed files with 336 additions and 25 deletions

View File

@@ -5,6 +5,7 @@ from pathlib import Path
from pobsync.snapshot_meta import resolve_host_root
from .config_checks import collect_effective_host_config_checks
from .models import GlobalConfig, HostConfig
from .self_check import SelfCheck
from .ssh_keys import identity_path
@@ -78,31 +79,10 @@ def collect_host_checks(host: HostConfig, global_config: GlobalConfig | None = N
checks.append(_host_path_check("Host backup root", host_root, must_exist=True, must_be_writable=True))
for subdir in HOST_BACKUP_SUBDIRS:
checks.append(_host_path_check(f"Host directory: {subdir}", host_root / subdir, must_exist=True, must_be_writable=True))
checks.append(_rsync_recursion_check(host, global_config))
checks.extend(collect_effective_host_config_checks(host, global_config))
return checks
def _rsync_recursion_check(host: HostConfig, global_config: GlobalConfig) -> SelfCheck:
args = [*list(global_config.rsync_args or []), *list(global_config.rsync_extra_args or []), *list(host.rsync_extra_args or [])]
if _has_recursive_rsync_arg(args):
return SelfCheck("Host rsync recursion", "ok", "Rsync args include archive or recursive transfer.", " ".join(args))
return SelfCheck(
"Host rsync recursion",
"failed",
"Rsync args do not include archive or recursive transfer.",
"Add --archive or --recursive before running a real backup.",
)
def _has_recursive_rsync_arg(args: list[str]) -> bool:
for arg in args:
if arg in {"--archive", "--recursive"}:
return True
if arg.startswith("-") and not arg.startswith("--") and any(flag in arg for flag in ("a", "r")):
return True
return False
def _host_path_check(
name: str,
path: Path,