feat(archive): BAK-07 gestaffelte Aufbewahrungsfrist fuer Backup-Snapshots
internal/backup.PruneTiered: reine GFS-Funktion (Tag/Woche/Monat) fuer Datenbank-Generationen, behaelt strukturell immer die neueste Generation (Sicherheitsnetz gegen Legal-Hold-Kollision). internal/objectbackup. PruneTiered: duenner Wrapper um restics native --keep-daily/-weekly/ -monthly-Staffelung. Beide CLIs nutzen die Staffelung, wenn konfiguriert, bleiben sonst abwaertskompatibel zur flachen "letzte N"-Regel. Real gegen zeitversetzt erzeugte restic-Snapshots getestet (Fund: restics --time-Flag erwartet eigenes Format, nicht RFC3339), Pruning-Sicherheit nach dem Loeschen alter Snapshots ueber vollstaendigen Restore + restic check --read-data bewiesen. Beide Rotationswege real ueber systemd auf 131 ausgeloest.
This commit is contained in:
@@ -36,6 +36,16 @@ func loadConfig() backup.Config {
|
||||
return cfg
|
||||
}
|
||||
|
||||
func envInt(name string, def int) int {
|
||||
v := os.Getenv(name)
|
||||
if v == "" {
|
||||
return def
|
||||
}
|
||||
n := def
|
||||
_, _ = fmt.Sscanf(v, "%d", &n)
|
||||
return n
|
||||
}
|
||||
|
||||
func latestManifest(backupDir string) (string, error) {
|
||||
generations, err := backup.ListGenerations(backupDir)
|
||||
if err != nil {
|
||||
@@ -91,6 +101,23 @@ func main() {
|
||||
fmt.Printf("inkrementelle sicherung %q erstellt und verifiziert: %s\n", incID, newManifest)
|
||||
|
||||
case "rotate":
|
||||
// BAK-07: gestaffelte Aufbewahrungsfrist (KeepDaily/Weekly/Monthly),
|
||||
// falls konfiguriert - ersetzt die flache "letzte N"-Regel
|
||||
// (NEXARCH_BACKUP_KEEP_GENERATIONS), bleibt aber abwaertskompatibel,
|
||||
// wenn keine Staffelung gesetzt ist.
|
||||
policy := backup.RetentionPolicy{
|
||||
KeepDaily: envInt("NEXARCH_BACKUP_KEEP_DAILY", 0),
|
||||
KeepWeekly: envInt("NEXARCH_BACKUP_KEEP_WEEKLY", 0),
|
||||
KeepMonthly: envInt("NEXARCH_BACKUP_KEEP_MONTHLY", 0),
|
||||
}
|
||||
if policy.KeepDaily > 0 || policy.KeepWeekly > 0 || policy.KeepMonthly > 0 {
|
||||
removed, err := backup.PruneRotate(cfg.BackupDir, policy)
|
||||
if err != nil {
|
||||
log.Fatalf("gestaffelte rotation fehlgeschlagen: %v", err)
|
||||
}
|
||||
fmt.Printf("gestaffelte rotation abgeschlossen, %d generation(en) entfernt: %v\n", len(removed), removed)
|
||||
return
|
||||
}
|
||||
keep := 7
|
||||
if v := os.Getenv("NEXARCH_BACKUP_KEEP_GENERATIONS"); v != "" {
|
||||
_, _ = fmt.Sscanf(v, "%d", &keep)
|
||||
|
||||
Reference in New Issue
Block a user