Fix --cron silence, add snapshot cleanup, fix .gitignore
--cron now sets Vaultik.Stdout to io.Discard so all user-facing output is suppressed, not just the scanner progress. Errors still go to stderr via the structured logger. snapshot list now warns when local snapshot records have no matching remote metadata, and suggests 'vaultik snapshot cleanup' instead of silently deleting them. snapshot cleanup is a new subcommand that explicitly removes stale local snapshot records. syncWithRemote (used by purge) still does this automatically since purge is already destructive. .gitignore changed from 'vaultik' to '/vaultik' so it only matches the binary at the repo root, not the internal/vaultik/ directory.
This commit is contained in:
@@ -409,7 +409,26 @@ func (v *Vaultik) ListSnapshots(jsonOutput bool) error {
|
||||
return encoder.Encode(snapshots)
|
||||
}
|
||||
|
||||
return v.printSnapshotTable(snapshots)
|
||||
if err := v.printSnapshotTable(snapshots); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Warn about local snapshots that don't exist in remote storage.
|
||||
var stale []string
|
||||
for id := range localSnapshotMap {
|
||||
if !remoteSnapshots[id] {
|
||||
stale = append(stale, id)
|
||||
}
|
||||
}
|
||||
if len(stale) > 0 {
|
||||
v.printfStdout("\nWarning: %d local snapshot(s) not found in remote storage:\n", len(stale))
|
||||
for _, id := range stale {
|
||||
v.printfStdout(" %s\n", id)
|
||||
}
|
||||
v.printlnStdout("Run 'vaultik snapshot cleanup' to remove stale local records.")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// listRemoteSnapshotIDs returns a set of snapshot IDs found in remote storage
|
||||
@@ -873,6 +892,41 @@ func (v *Vaultik) outputVerifyJSON(result *VerifyResult) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CleanupLocalSnapshots removes local snapshot records that have no
|
||||
// corresponding metadata in remote storage. These are typically left
|
||||
// behind by incomplete or interrupted backups.
|
||||
func (v *Vaultik) CleanupLocalSnapshots() error {
|
||||
remoteSnapshots, err := v.listRemoteSnapshotIDs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
localSnapshots, err := v.Repositories.Snapshots.ListRecent(v.ctx, 10000)
|
||||
if err != nil {
|
||||
return fmt.Errorf("listing local snapshots: %w", err)
|
||||
}
|
||||
|
||||
var removed int
|
||||
for _, snap := range localSnapshots {
|
||||
id := snap.ID.String()
|
||||
if !remoteSnapshots[id] {
|
||||
v.printfStdout("Removing stale local record: %s\n", id)
|
||||
if err := v.deleteSnapshotFromLocalDB(id); err != nil {
|
||||
log.Error("Failed to delete local snapshot", "snapshot_id", id, "error", err)
|
||||
continue
|
||||
}
|
||||
removed++
|
||||
}
|
||||
}
|
||||
|
||||
if removed == 0 {
|
||||
v.printlnStdout("No stale local snapshots found.")
|
||||
} else {
|
||||
v.printfStdout("Removed %d stale local snapshot record(s).\n", removed)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Helper methods that were previously on SnapshotApp
|
||||
|
||||
func (v *Vaultik) downloadManifest(snapshotID string) (*snapshot.Manifest, error) {
|
||||
|
||||
Reference in New Issue
Block a user