From b939e016e3bac8f0d0bf0a2d21fd2a4255447941 Mon Sep 17 00:00:00 2001 From: clawbot Date: Sat, 21 Mar 2026 16:48:14 -0700 Subject: [PATCH] refactor: remove backward compat wrapper and legacy snapshot support - Remove PurgeSnapshots wrapper; callers use PurgeSnapshotsWithOptions directly - Update snapshot create --prune to call PurgeSnapshotsWithOptions - Remove TestSnapshotPurgeOptions (tested Go struct assignment, no value) - Remove legacy no-name snapshot tests (TestPurgeKeepLatest_LegacyNoNameSnapshots, TestPurgeKeepLatest_MixedNamedAndLegacy) - Remove legacy format test cases from TestParseSnapshotName - Update parseSnapshotName doc to not mention legacy format --- internal/vaultik/helpers.go | 5 +-- internal/vaultik/helpers_test.go | 43 ---------------------- internal/vaultik/purge_per_name_test.go | 47 ------------------------- internal/vaultik/snapshot.go | 18 +++------- 4 files changed, 8 insertions(+), 105 deletions(-) diff --git a/internal/vaultik/helpers.go b/internal/vaultik/helpers.go index f81525a..16c1ed4 100644 --- a/internal/vaultik/helpers.go +++ b/internal/vaultik/helpers.go @@ -80,8 +80,9 @@ func parseSnapshotTimestamp(snapshotID string) (time.Time, error) { } // parseSnapshotName extracts the snapshot name from a snapshot ID. -// Format: hostname_snapshotname_timestamp (3 parts) or hostname_timestamp (2 parts, no name). -// Returns the snapshot name, or empty string if no name component is present. +// Format: hostname_snapshotname_timestamp — the middle part(s) between hostname +// and the RFC3339 timestamp are the snapshot name (may contain underscores). +// Returns the snapshot name, or empty string if the ID is malformed. func parseSnapshotName(snapshotID string) string { parts := strings.Split(snapshotID, "_") if len(parts) < 3 { diff --git a/internal/vaultik/helpers_test.go b/internal/vaultik/helpers_test.go index e609a73..ef7bf5b 100644 --- a/internal/vaultik/helpers_test.go +++ b/internal/vaultik/helpers_test.go @@ -20,26 +20,11 @@ func TestParseSnapshotName(t *testing.T) { snapshotID: "server1_system_2026-02-15T09:30:00Z", want: "system", }, - { - name: "no snapshot name (legacy format)", - snapshotID: "myhost_2026-01-12T14:41:15Z", - want: "", - }, { name: "name with underscores", snapshotID: "myhost_my_special_backup_2026-03-01T00:00:00Z", want: "my_special_backup", }, - { - name: "single part (edge case)", - snapshotID: "nounderscore", - want: "", - }, - { - name: "empty string", - snapshotID: "", - want: "", - }, } for _, tt := range tests { @@ -89,31 +74,3 @@ func TestParseSnapshotTimestamp(t *testing.T) { }) } } - -func TestSnapshotPurgeOptions(t *testing.T) { - opts := &SnapshotPurgeOptions{ - KeepLatest: true, - Name: "home", - Force: true, - } - if !opts.KeepLatest { - t.Error("Expected KeepLatest to be true") - } - if opts.Name != "home" { - t.Errorf("Expected Name to be 'home', got %q", opts.Name) - } - if !opts.Force { - t.Error("Expected Force to be true") - } - - opts2 := &SnapshotPurgeOptions{ - OlderThan: "30d", - Name: "system", - } - if opts2.OlderThan != "30d" { - t.Errorf("Expected OlderThan to be '30d', got %q", opts2.OlderThan) - } - if opts2.Name != "system" { - t.Errorf("Expected Name to be 'system', got %q", opts2.Name) - } -} diff --git a/internal/vaultik/purge_per_name_test.go b/internal/vaultik/purge_per_name_test.go index f46c64d..cb3ecc4 100644 --- a/internal/vaultik/purge_per_name_test.go +++ b/internal/vaultik/purge_per_name_test.go @@ -228,53 +228,6 @@ func TestPurgeOlderThan_WithNameFilter(t *testing.T) { assert.Contains(t, remaining, "testhost_home_2026-01-01T00:00:00Z") } -func TestPurgeKeepLatest_LegacyNoNameSnapshots(t *testing.T) { - // Legacy snapshots without a name component (hostname_timestamp). - // Should be grouped together under empty-name. - snapshotIDs := []string{ - "testhost_2026-01-01T00:00:00Z", - "testhost_2026-01-01T01:00:00Z", - "testhost_2026-01-01T02:00:00Z", - } - - v := setupPurgeTest(t, snapshotIDs) - - err := v.PurgeSnapshotsWithOptions(&vaultik.SnapshotPurgeOptions{ - KeepLatest: true, - Force: true, - }) - require.NoError(t, err) - - remaining := listRemainingSnapshots(t, v) - assert.Len(t, remaining, 1) - assert.Contains(t, remaining, "testhost_2026-01-01T02:00:00Z") -} - -func TestPurgeKeepLatest_MixedNamedAndLegacy(t *testing.T) { - // Mix of named snapshots and legacy ones (no name). - snapshotIDs := []string{ - "testhost_2026-01-01T00:00:00Z", - "testhost_home_2026-01-01T01:00:00Z", - "testhost_2026-01-01T02:00:00Z", - "testhost_home_2026-01-01T03:00:00Z", - } - - v := setupPurgeTest(t, snapshotIDs) - - err := v.PurgeSnapshotsWithOptions(&vaultik.SnapshotPurgeOptions{ - KeepLatest: true, - Force: true, - }) - require.NoError(t, err) - - remaining := listRemainingSnapshots(t, v) - - // Should keep latest of each group: latest legacy + latest home - assert.Len(t, remaining, 2) - assert.Contains(t, remaining, "testhost_2026-01-01T02:00:00Z") - assert.Contains(t, remaining, "testhost_home_2026-01-01T03:00:00Z") -} - func TestPurgeKeepLatest_ThreeNames(t *testing.T) { // Three different snapshot names with multiple snapshots each. snapshotIDs := []string{ diff --git a/internal/vaultik/snapshot.go b/internal/vaultik/snapshot.go index 0c4c6cd..7c92a76 100644 --- a/internal/vaultik/snapshot.go +++ b/internal/vaultik/snapshot.go @@ -95,7 +95,10 @@ func (v *Vaultik) CreateSnapshot(opts *SnapshotCreateOptions) error { log.Info("Pruning enabled - deleting old snapshots and unreferenced blobs") v.printlnStdout("\nPruning old snapshots (keeping latest)...") - if err := v.PurgeSnapshots(true, "", true); err != nil { + if err := v.PurgeSnapshotsWithOptions(&SnapshotPurgeOptions{ + KeepLatest: true, + Force: true, + }); err != nil { return fmt.Errorf("prune: purging old snapshots: %w", err) } @@ -528,18 +531,7 @@ type SnapshotPurgeOptions struct { Name string // Filter purge to a specific snapshot name } -// PurgeSnapshots removes old snapshots based on criteria. -// When keepLatest is true, retention is applied per snapshot name — the latest -// snapshot for each distinct name is kept. -func (v *Vaultik) PurgeSnapshots(keepLatest bool, olderThan string, force bool) error { - return v.PurgeSnapshotsWithOptions(&SnapshotPurgeOptions{ - KeepLatest: keepLatest, - OlderThan: olderThan, - Force: force, - }) -} - -// PurgeSnapshotsWithOptions removes old snapshots based on criteria with full options. +// PurgeSnapshotsWithOptions removes old snapshots based on criteria. // When KeepLatest is true, retention is applied per snapshot name — the latest // snapshot for each distinct name is kept. If Name is non-empty, only snapshots // matching that name are considered for purge.