restore and verify report an unknown snapshot ID as not found (closes #426)
check / check (push) Successful in 9m36s
check / check (push) Successful in 9m36s
A snapshot ID that names no snapshot in the local index or on the destination store made restore and verify fail on a missing object at a hashed path, and verify printed a header for it first. Resolving a snapshot ID now uses the look-up `snapshot remove` already does, so all three commands give the same error, and verify prints its header only after the snapshot is found. Model: opus-5-5
This commit is contained in:
1 parent
098ed80990
commit
5682918723
5 files changed
+113
-50
No files matched your search
@@ -969,25 +969,22 @@ func (v *Vaultik) VerifySnapshotWithOptions(
|
||||
Mode: "shallow",
|
||||
}
|
||||
|
||||
v.printVerifyHeader(snapshotID, opts)
|
||||
|
||||
// Resolve the identifier to the snapshot's remote key. A human ID is
|
||||
// hashed; a remote key (or its abbreviation, as printed for a
|
||||
// remote-only snapshot) is used as-is, so a host with no local index
|
||||
// can verify a snapshot it can only see on the store. The key is kept
|
||||
// so we can also check for the snapshot's encrypted database below.
|
||||
// The key is kept so we can also check for the snapshot's encrypted
|
||||
// database below.
|
||||
remoteKey, err := v.resolveSnapshotRemoteKey(snapshotID)
|
||||
if err != nil {
|
||||
if opts.JSON {
|
||||
result.Status = verifyStatusFailed
|
||||
result.ErrorMessage = fmt.Sprintf("resolving snapshot identifier: %v", err)
|
||||
result.ErrorMessage = err.Error()
|
||||
|
||||
return v.outputVerifyJSON(result)
|
||||
}
|
||||
|
||||
return fmt.Errorf("resolving snapshot identifier: %w", err)
|
||||
return err
|
||||
}
|
||||
|
||||
v.printVerifyHeader(snapshotID, opts)
|
||||
|
||||
manifest, err := v.downloadManifestByKey(remoteKey)
|
||||
if err != nil {
|
||||
if opts.JSON {
|
||||
@@ -1480,7 +1477,7 @@ func (v *Vaultik) RemoveSnapshot(
|
||||
return result, err
|
||||
}
|
||||
|
||||
inLocalIndex, err := v.findSnapshotToRemove(snapshotID, opts)
|
||||
inLocalIndex, err := v.checkSnapshotExists(snapshotID, opts.LocalOnly)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
@@ -1543,17 +1540,20 @@ func (v *Vaultik) RemoveSnapshot(
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// findSnapshotToRemove reports whether the local index has a row for
|
||||
// snapshotID, and returns errSnapshotNotFound when there is nothing to
|
||||
// remove: no row and, unless LocalOnly is set, no metadata on the
|
||||
// destination store either. The destination store is consulted only
|
||||
// when the local index has no row, so a snapshot in the local index can
|
||||
// still be removed from it while the destination store is unreachable,
|
||||
// and only after checkDestinationMarker passes, so an unplugged volume's
|
||||
// empty mount point is not taken for a store without the snapshot.
|
||||
func (v *Vaultik) findSnapshotToRemove(
|
||||
snapshotID string, opts *RemoveOptions,
|
||||
) (bool, error) {
|
||||
// checkSnapshotExists returns errSnapshotNotFound when the local index
|
||||
// has no row for snapshotID and, unless localOnly is set, the
|
||||
// destination store has no metadata for it either. inLocalIndex reports
|
||||
// whether the local index has that row. The destination store is
|
||||
// consulted only when the local index has no row, so a snapshot in the
|
||||
// local index can still be removed from it while the destination store
|
||||
// is unreachable, and only after checkDestinationMarker passes, so an
|
||||
// unplugged volume's empty mount point is not taken for a store without
|
||||
// the snapshot.
|
||||
//
|
||||
//nolint:nonamedreturns // the result name says what the bool means
|
||||
func (v *Vaultik) checkSnapshotExists(
|
||||
snapshotID string, localOnly bool,
|
||||
) (inLocalIndex bool, err error) {
|
||||
if v.Repositories != nil {
|
||||
snap, err := v.Repositories.Snapshots.GetByID(v.ctx, snapshotID)
|
||||
if err != nil {
|
||||
@@ -1565,12 +1565,12 @@ func (v *Vaultik) findSnapshotToRemove(
|
||||
}
|
||||
}
|
||||
|
||||
if opts.LocalOnly {
|
||||
if localOnly {
|
||||
return false, fmt.Errorf("%w in the local index: %s",
|
||||
errSnapshotNotFound, snapshotID)
|
||||
}
|
||||
|
||||
err := v.checkDestinationMarker()
|
||||
err = v.checkDestinationMarker()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user