field NotFound err in kopia, handle in cli (#1027)

## Description

Replace the `manifest.NotFound` error production
in kopia wrapper with a local version of the error. This allows the cli to catch the corso error and
write a clearer response to the end user.

## Type of change

- [x] 🌻 Feature

## Issue(s)

* #976 

## Test Plan

- [x] 💪 Manual
- [x] 💚 E2E
This commit is contained in:
Keepers 2022-10-04 12:27:23 -06:00 committed by GitHub
parent d0560500d2
commit 67215c9bf1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 34 additions and 19 deletions

View File

@ -11,6 +11,7 @@ import (
"github.com/alcionai/corso/src/cli/options" "github.com/alcionai/corso/src/cli/options"
. "github.com/alcionai/corso/src/cli/print" . "github.com/alcionai/corso/src/cli/print"
"github.com/alcionai/corso/src/cli/utils" "github.com/alcionai/corso/src/cli/utils"
"github.com/alcionai/corso/src/internal/kopia"
"github.com/alcionai/corso/src/internal/model" "github.com/alcionai/corso/src/internal/model"
"github.com/alcionai/corso/src/pkg/backup" "github.com/alcionai/corso/src/pkg/backup"
"github.com/alcionai/corso/src/pkg/backup/details" "github.com/alcionai/corso/src/pkg/backup/details"
@ -422,6 +423,10 @@ func runDetailsExchangeCmd(
) (*details.Details, error) { ) (*details.Details, error) {
d, _, err := r.BackupDetails(ctx, backupID) d, _, err := r.BackupDetails(ctx, backupID)
if err != nil { if err != nil {
if errors.Is(err, kopia.ErrNotFound) {
return nil, errors.Errorf("no backup exists with the id %s", backupID)
}
return nil, errors.Wrap(err, "Failed to get backup details in the repository") return nil, errors.Wrap(err, "Failed to get backup details in the repository")
} }

View File

@ -11,6 +11,7 @@ import (
"github.com/alcionai/corso/src/cli/options" "github.com/alcionai/corso/src/cli/options"
. "github.com/alcionai/corso/src/cli/print" . "github.com/alcionai/corso/src/cli/print"
"github.com/alcionai/corso/src/cli/utils" "github.com/alcionai/corso/src/cli/utils"
"github.com/alcionai/corso/src/internal/kopia"
"github.com/alcionai/corso/src/internal/model" "github.com/alcionai/corso/src/internal/model"
"github.com/alcionai/corso/src/pkg/backup" "github.com/alcionai/corso/src/pkg/backup"
"github.com/alcionai/corso/src/pkg/backup/details" "github.com/alcionai/corso/src/pkg/backup/details"
@ -295,6 +296,10 @@ func runDetailsOneDriveCmd(
) (*details.Details, error) { ) (*details.Details, error) {
d, _, err := r.BackupDetails(ctx, backupID) d, _, err := r.BackupDetails(ctx, backupID)
if err != nil { if err != nil {
if errors.Is(err, kopia.ErrNotFound) {
return nil, errors.Errorf("no backup exists with the id %s", backupID)
}
return nil, errors.Wrap(err, "Failed to get backup details in the repository") return nil, errors.Wrap(err, "Failed to get backup details in the repository")
} }

View File

@ -14,6 +14,7 @@ import (
const stableIDKey = "stableID" const stableIDKey = "stableID"
var ( var (
ErrNotFound = errors.New("not found")
errNoModelStoreID = errors.New("model has no ModelStoreID") errNoModelStoreID = errors.New("model has no ModelStoreID")
errNoStableID = errors.New("model has no StableID") errNoStableID = errors.New("model has no StableID")
errBadTagKey = errors.New("tag key overlaps with required key") errBadTagKey = errors.New("tag key overlaps with required key")
@ -219,8 +220,7 @@ func (ms *ModelStore) GetIDsForType(
} }
// getModelStoreID gets the ModelStoreID of the model with the given // getModelStoreID gets the ModelStoreID of the model with the given
// StableID. Returns github.com/kopia/kopia/repo/manifest.ErrNotFound if no // StableID. Returns an error if the given StableID is empty or more than
// model was found. Returns an error if the given StableID is empty or more than
// one model has the same StableID. // one model has the same StableID.
func (ms *ModelStore) getModelStoreID( func (ms *ModelStore) getModelStoreID(
ctx context.Context, ctx context.Context,
@ -243,7 +243,7 @@ func (ms *ModelStore) getModelStoreID(
} }
if len(metadata) == 0 { if len(metadata) == 0 {
return "", errors.Wrap(manifest.ErrNotFound, "getting ModelStoreID") return "", errors.Wrap(ErrNotFound, "getting ModelStoreID")
} }
if len(metadata) != 1 { if len(metadata) != 1 {
@ -257,10 +257,9 @@ func (ms *ModelStore) getModelStoreID(
return metadata[0].ID, nil return metadata[0].ID, nil
} }
// Get deserializes the model with the given StableID into data. Returns // Get deserializes the model with the given StableID into data.
// github.com/kopia/kopia/repo/manifest.ErrNotFound if no model was found. // Returns an error if the persisted model has a different type
// Returns and error if the persisted model has a different type than expected // than expected or if multiple models have the same StableID.
// or if multiple models have the same StableID.
func (ms *ModelStore) Get( func (ms *ModelStore) Get(
ctx context.Context, ctx context.Context,
s model.Schema, s model.Schema,
@ -276,12 +275,11 @@ func (ms *ModelStore) Get(
return err return err
} }
return ms.GetWithModelStoreID(ctx, s, modelID, data) return transmuteErr(ms.GetWithModelStoreID(ctx, s, modelID, data))
} }
// GetWithModelStoreID deserializes the model with the given ModelStoreID into // GetWithModelStoreID deserializes the model with the given ModelStoreID into
// data. Returns github.com/kopia/kopia/repo/manifest.ErrNotFound if no model // data. Returns and error if the persisted model has a different type than
// was found. Returns and error if the persisted model has a different type than
// expected. // expected.
func (ms *ModelStore) GetWithModelStoreID( func (ms *ModelStore) GetWithModelStoreID(
ctx context.Context, ctx context.Context,
@ -298,10 +296,8 @@ func (ms *ModelStore) GetWithModelStoreID(
} }
metadata, err := ms.c.GetManifest(ctx, id, data) metadata, err := ms.c.GetManifest(ctx, id, data)
// TODO(ashmrtnz): Should probably return some recognizable, non-kopia error
// if not found. That way kopia doesn't need to be imported to higher layers.
if err != nil { if err != nil {
return errors.Wrap(err, "getting model data") return errors.Wrap(transmuteErr(err), "getting model data")
} }
if metadata.Labels[manifest.TypeLabelKey] != s.String() { if metadata.Labels[manifest.TypeLabelKey] != s.String() {
@ -423,7 +419,7 @@ func (ms *ModelStore) Delete(ctx context.Context, s model.Schema, id model.Stabl
latest, err := ms.getModelStoreID(ctx, s, id) latest, err := ms.getModelStoreID(ctx, s, id)
if err != nil { if err != nil {
if errors.Is(err, manifest.ErrNotFound) { if errors.Is(err, ErrNotFound) {
return nil return nil
} }
@ -452,3 +448,12 @@ func (ms *ModelStore) DeleteWithModelStoreID(ctx context.Context, id manifest.ID
return errors.Wrap(err, "deleting model") return errors.Wrap(err, "deleting model")
} }
func transmuteErr(err error) error {
switch {
case errors.Is(err, manifest.ErrNotFound):
return ErrNotFound
default:
return err
}
}

View File

@ -335,9 +335,9 @@ func (suite *ModelStoreIntegrationSuite) TestPutGet_WithTags() {
func (suite *ModelStoreIntegrationSuite) TestGet_NotFoundErrors() { func (suite *ModelStoreIntegrationSuite) TestGet_NotFoundErrors() {
t := suite.T() t := suite.T()
assert.ErrorIs(t, suite.m.Get(suite.ctx, model.BackupOpSchema, "baz", nil), manifest.ErrNotFound) assert.ErrorIs(t, suite.m.Get(suite.ctx, model.BackupOpSchema, "baz", nil), ErrNotFound)
assert.ErrorIs( assert.ErrorIs(
t, suite.m.GetWithModelStoreID(suite.ctx, model.BackupOpSchema, "baz", nil), manifest.ErrNotFound) t, suite.m.GetWithModelStoreID(suite.ctx, model.BackupOpSchema, "baz", nil), ErrNotFound)
} }
func (suite *ModelStoreIntegrationSuite) TestPutGetOfType() { func (suite *ModelStoreIntegrationSuite) TestPutGetOfType() {
@ -580,7 +580,7 @@ func (suite *ModelStoreIntegrationSuite) TestPutUpdate() {
} }
err = m.GetWithModelStoreID(ctx, theModelType, oldModelID, nil) err = m.GetWithModelStoreID(ctx, theModelType, oldModelID, nil)
assert.ErrorIs(t, err, manifest.ErrNotFound) assert.ErrorIs(t, err, ErrNotFound)
}) })
} }
} }
@ -640,7 +640,7 @@ func (suite *ModelStoreIntegrationSuite) TestPutDelete() {
returned := &fooModel{} returned := &fooModel{}
err := suite.m.GetWithModelStoreID(suite.ctx, theModelType, foo.ModelStoreID, returned) err := suite.m.GetWithModelStoreID(suite.ctx, theModelType, foo.ModelStoreID, returned)
assert.ErrorIs(t, err, manifest.ErrNotFound) assert.ErrorIs(t, err, ErrNotFound)
} }
func (suite *ModelStoreIntegrationSuite) TestPutDelete_BadIDsNoop() { func (suite *ModelStoreIntegrationSuite) TestPutDelete_BadIDsNoop() {
@ -725,7 +725,7 @@ func (suite *ModelStoreRegressionSuite) TestFailDuringWriteSessionHasNoVisibleEf
assert.ErrorIs(t, err, assert.AnError) assert.ErrorIs(t, err, assert.AnError)
err = m.GetWithModelStoreID(ctx, theModelType, newID, nil) err = m.GetWithModelStoreID(ctx, theModelType, newID, nil)
assert.ErrorIs(t, err, manifest.ErrNotFound) assert.ErrorIs(t, err, ErrNotFound)
returned := &fooModel{} returned := &fooModel{}
require.NoError( require.NoError(