internal/restoretest wiederholt BAK-03s eigene Pruefdiskt als Produktcode: echter Restore der neuesten Sicherung, echter Kurzstart einer isolierten Postgres-Instanz, echte SELECT-1-Abfrage; Objekt-Seite echter restic-Restore + Inhaltspruefung. JSONL-Historie (append-only), sichtbare Warnung ueber denselben OPS-05-Pull-Weg wie BAK-08, eigenes /metrics-Modul (archive-restoretest). Zwei reale Defekte gefunden und behoben: Unix-Socket-Pfadlaenge unter tief verschachtelten Testpfaden, restic-stderr-Vermischung beim JSON-Parsen unter dem Dienstnutzer. Real auf 131 verdrahtet und ausgeloest (beide Testarten erfolgreich, End-zu-Ende ueber OPS-03 bestaetigt).
72 lines
2.1 KiB
Go
72 lines
2.1 KiB
Go
// restoretest-cli ist der Aufrufpunkt fuer BAK-06 (systemd-Timer,
|
|
// regelmaessiger Zeitplan) - fuehrt einen vollstaendigen Restore-Test
|
|
// (Datenbank UND Objekt-Storage) gegen die jeweils neueste Sicherung in
|
|
// eine isolierte Testumgebung durch und protokolliert das Ergebnis.
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
"os"
|
|
|
|
"gitea.perlbach24.de/scripte/nexarch/archive/internal/backup"
|
|
"gitea.perlbach24.de/scripte/nexarch/archive/internal/objectbackup"
|
|
"gitea.perlbach24.de/scripte/nexarch/archive/internal/restoretest"
|
|
)
|
|
|
|
func main() {
|
|
testRoot := os.Getenv("NEXARCH_RESTORETEST_DIR")
|
|
logPath := os.Getenv("NEXARCH_RESTORETEST_LOG")
|
|
if testRoot == "" || logPath == "" {
|
|
log.Fatal("NEXARCH_RESTORETEST_DIR und NEXARCH_RESTORETEST_LOG muessen gesetzt sein")
|
|
}
|
|
if err := os.MkdirAll(testRoot, 0o750); err != nil {
|
|
log.Fatalf("testverzeichnis anlegen: %v", err)
|
|
}
|
|
|
|
ctx := context.Background()
|
|
failed := false
|
|
|
|
dbCfg := backup.Config{
|
|
Host: os.Getenv("NEXARCH_BACKUP_PG_HOST"),
|
|
Port: os.Getenv("NEXARCH_BACKUP_PG_PORT"),
|
|
User: os.Getenv("NEXARCH_BACKUP_PG_USER"),
|
|
Password: os.Getenv("NEXARCH_BACKUP_PG_PASSWORD"),
|
|
BackupDir: os.Getenv("NEXARCH_BACKUP_DIR"),
|
|
}
|
|
pgCfg := restoretest.PgConfig{TestPort: envOr("NEXARCH_RESTORETEST_PG_PORT", "55433")}
|
|
dbResult := restoretest.RunDatabaseTest(ctx, dbCfg, pgCfg, testRoot)
|
|
logResult(logPath, dbResult)
|
|
if !dbResult.Success {
|
|
failed = true
|
|
}
|
|
|
|
objCfg := objectbackup.Config{
|
|
RepoDir: os.Getenv("NEXARCH_OBJECTBACKUP_REPO_DIR"),
|
|
Password: os.Getenv("NEXARCH_OBJECTBACKUP_PASSWORD"),
|
|
}
|
|
objResult := restoretest.RunObjectTest(ctx, objCfg, testRoot)
|
|
logResult(logPath, objResult)
|
|
if !objResult.Success {
|
|
failed = true
|
|
}
|
|
|
|
if failed {
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func logResult(logPath string, r restoretest.Result) {
|
|
log.Printf("restoretest %s: quelle=%s erfolg=%t detail=%s", r.Kind, r.Source, r.Success, r.Detail)
|
|
if err := restoretest.AppendHistory(logPath, r); err != nil {
|
|
log.Fatalf("protokoll schreiben: %v", err)
|
|
}
|
|
}
|
|
|
|
func envOr(key, fallback string) string {
|
|
if v := os.Getenv(key); v != "" {
|
|
return v
|
|
}
|
|
return fallback
|
|
}
|