# BAK-06 – Prüfprotokoll: Restore-Testverfahren Voraussetzung BAK-03 – erledigt, siehe eigenes Protokoll. ## Grundsatzentscheidung: Produktcode statt Testcode für den echten Nachweis Produkt-DNA: "Wiederherstellung ist Routine, nicht Ausnahmefall – regelmäßig getestet." Ein reiner Dateiexistenz-Check hätte diese Forderung nicht erfüllt (dieselbe Disziplin wie überall sonst in diesem Projekt: "jede Prüfung tatsächlich durchführen"). `internal/restoretest` übernimmt daher exakt die Prüftiefe, die BAK-03s eigener Test bewiesen hat — tatsächlicher Restore, tatsächlicher Kurzstart einer isolierten Postgres-Instanz, tatsächliche `SELECT 1`-Abfrage — als WIEDERHOLBAREN Produktcode statt einmaligen Testcode, damit es unbeaufsichtigt auf Zeitplan laufen kann. Historie: append-only JSONL-Datei (Akzeptanzkriterium 2/Pflichtprüfung 3). Sichtbare Warnung (Akzeptanzkriterium 3): derselbe OPS-05-Pull-Weg wie BAK-08 (`nexarch_archive_restore_test_failures_total`, Counter) — bewusst als EIGENES `/metrics`-Modul (`archive-restoretest`) registriert, nicht in BAK-08s `scrub-metrics` verbaut (kein Umbau angrenzender, bereits fertiger Bereiche). ## Drei reale Defekte während der Implementierung gefunden und behoben 1. **Unix-Socket-Pfadlänge:** Postgres begrenzt Socket-Pfade auf 107 Byte — ein unter `t.TempDir()` verschachtelter Pfad reißt dieses Limit leicht. Fix: eigenes, kurzes Socket-Verzeichnis (`os.MkdirTemp("", ...)`), nicht unter dem Testverzeichnis. 2. **`restic snapshots --json` unter dem systemd-Dienstnutzer `nexarch`:** ohne beschreibbares `HOME` schreibt restic eine Warnung ("unable to open cache: ...") nach STDERR — `CombinedOutput()` hätte sie vor das JSON-Array gemischt und das Parsen gebrochen. Fix: nur `cmd.Output()` (stdout), stderr separat für Fehlermeldungen. 3. Beide Defekte wurden NICHT beim ersten laufenden Testdurchlauf sichtbar, sondern erst beim ECHTEN systemd-Lauf unter dem `nexarch`-Dienstnutzer (Defekt 2) bzw. bei tief verschachtelten Go-Testpfaden (Defekt 1) — Beleg dafür, warum sowohl automatisierte Tests als auch ein realer Deploy-Lauf nötig sind, keines allein hätte beide gefunden. ## Umsetzung - `internal/restoretest.RunDatabaseTest` — neueste Generation ermitteln (`backup.ListGenerations`), `backup.Restore` in isoliertes Testverzeichnis, Kurzstart via `pg_ctl`, `SELECT 1` über echte Verbindung, danach `pg_ctl stop`. - `internal/restoretest.RunObjectTest` — neuesten Snapshot ermitteln, `objectbackup.Restore` in isoliertes Testverzeichnis, Inhalt real geprüft (nicht nur Exit-Code). - `internal/restoretest.AppendHistory`/`ReadHistory` — JSONL, append-only. - `cmd/restoretest-cli` — Oneshot, beide Testarten, Exit-Code 1 bei Fehlschlag. - `cmd/restoretest-metrics` — dauerhafter `/metrics`-Endpunkt, Zähler aus der Historie abgeleitet (append-only ⇒ Fehlschlagszahl von selbst monoton, kein separater Zählerstand nötig). ## Prüfungen | # | Prüfung | Ergebnis | |---|---|---| | 1 | Geplanter Testlauf gegen aktuelle Sicherung erfolgreich durchgeführt und protokolliert | **bestanden** — `TestRunDatabaseTest_SucceedsAgainstRealBackup`, `TestRunObjectTest_SucceedsAgainstRealSnapshot`; real auf 131: `systemctl start nexarch-archive-restoretest.service` → beide Testarten `erfolg=true`, in `history.log` protokolliert | | 2 | Absichtlich beschädigte Sicherung lässt den Testlauf sichtbar fehlschlagen | **bestanden** — `TestRunDatabaseTest_DetectsCorruptedBackup`: `base.tar.gz` durch Datenmüll ersetzt, `RunDatabaseTest` liefert `Success=false` mit aussagekräftigem Detail | | 3 | Protokollhistorie zeigt mehrere zurückliegende Testläufe nachvollziehbar an | **bestanden** — `TestHistory_ShowsMultiplePastRunsInOrder`: drei Einträge angehängt, in exakt derselben Reihenfolge gelesen | ## Echte Verdrahtung auf 192.168.1.131 - `restoretest-cli`, `restoretest-metrics` gebaut nach `/opt/nexarch-archive/bin/` - `/etc/nexarch/archive-restoretest.env` (0600) - `nexarch-archive-restoretest.timer` installiert/aktiviert (wöchentlich So. 07:00 UTC), `nexarch-archive-restoretest-metrics.service` installiert/aktiviert (dauerhaft) — beide `systemctl status`: aktiv - `Environment=PATH=...` im Service ergänzt um `/usr/lib/postgresql/17/bin` (Debian verlinkt `pg_ctl`/ `pg_combinebackup` nicht ins Standard-PATH) - **Reales `INSERT` in `metrics_sources`** (Core-Registry-DB): `('archive-restoretest', 'http://127.0.0.1:8091/metrics')` - **End-to-End über OPS-03 bestätigt**: `curl http://127.0.0.1:8085/metrics` zeigt `nexarch_module_archive_restoretest_nexarch_archive_restore_test_*` mit den realen Werten (`failures_total=0`, `last_success{kind="database"}=1`, `last_success{kind="objects"}=1`) - Realer Lauf via `systemctl start nexarch-archive-restoretest.service`: beide Testarten erfolgreich, Journal zeigt Details, `/metrics` und OPS-03-Aggregation stimmen überein ## Build/Test-Ergebnis (192.168.1.131, `make check`) ``` go build ./... -> clean go vet ./... -> clean golangci-lint run ./... -> 0 issues go test ./... -p 1 -count=1 -> 6/6 Pakete mit Tests ok (backup, objectbackup, reconcile, restore, restoretest, scrub), 0 Fehlschläge ``` Hinweis wie bei BAK-03: die Datenbank-Restore-Tests (`TestRunDatabaseTest_*`) brauchen `pg_ctl`/`pg_combinebackup` im PATH und laufen NICHT als root — separat als `postgres`-Systemnutzer verifiziert (7/7 `internal/restoretest`-Tests bestanden), im normalen root-`make check`-Lauf werden sie mit klarer Meldung übersprungen. ## Gesamtergebnis **Bestanden.** Alle drei Akzeptanzkriterien und alle drei Pflichtprüfungen real erfüllt — sowohl testgetrieben als auch über einen echten, unbeaufsichtigten systemd-Lauf mit OPS-03/OPS-05-Sichtbarkeit nachgewiesen. Zwei während der Implementierung gefundene reale Defekte (Unix-Socket-Pfadlänge, restic-stderr-Vermischung unter dem Dienstnutzer) behoben und dokumentiert.