Skip to content

Commit

Permalink
private/metaclient: add new error types for object lock upload errs
Browse files Browse the repository at this point in the history
this also fixes a case where Commit calls didn't convert to known
errors and caused unmapped errors on gateway.

Updates storj/edge#498

Change-Id: I07907185c26559805c342be584b3b2c8bc776800
  • Loading branch information
halkyon committed Sep 10, 2024
1 parent 14cad7f commit 0e957ac
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 20 deletions.
11 changes: 6 additions & 5 deletions private/metaclient/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -989,15 +989,16 @@ func convertNotFoundErr(err error) error {
)

message := errs.Unwrap(err).Error()
if strings.HasPrefix(message, bucketNotFoundPrefix) {
switch {
case strings.HasPrefix(message, bucketNotFoundPrefix):
return ErrBucketNotFound.Wrap(err)
} else if strings.HasPrefix(message, objectNotFoundPrefix) {
case strings.HasPrefix(message, objectNotFoundPrefix):
return ErrObjectNotFound.Wrap(err)
} else if strings.HasPrefix(message, noRetentionPrefix) {
case strings.HasPrefix(message, noRetentionPrefix):
return ErrRetentionNotFound.Wrap(err)
default:
return Error.Wrap(err)
}

return Error.Wrap(err)
}

func convertFailedPreconditionErr(err error) error {
Expand Down
33 changes: 25 additions & 8 deletions private/object/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,18 @@ var mon = monkit.Package()
var packageError = errs.Class("object")

// ErrMethodNotAllowed is returned when method is not allowed against specified entity (e.g. object).
var ErrMethodNotAllowed = errors.New("method not allowed")
var (
ErrMethodNotAllowed = errors.New("method not allowed")

// ErrNoObjectLockConfiguration is returned when a locked object is copied to a bucket without object lock configuration.
var ErrNoObjectLockConfiguration = errors.New("destination bucket has no object lock configuration")
// ErrNoObjectLockConfiguration is returned when a locked object is copied to a bucket without object lock configuration.
ErrNoObjectLockConfiguration = errors.New("destination bucket has no object lock configuration")

// ErrBucketNoVersioningObjectLock is returned when attempting to set object lock without versioning enabled.
ErrBucketNoVersioningObjectLock = errors.New("destination bucket does not have versioning enabled required for object lock")

// ErrRetentionNotFound is returned when getting object retention for an object that has none.
ErrRetentionNotFound = errors.New("object has no retention configuration")
)

// IPSummary contains information about the object IP-s.
type IPSummary = metaclient.GetObjectIPsResponse
Expand Down Expand Up @@ -99,7 +107,7 @@ func (upload *VersionedUpload) Write(p []byte) (n int, err error) {
//
// Returns ErrUploadDone when either Abort or Commit has already been called.
func (upload *VersionedUpload) Commit() error {
return upload.upload.Commit()
return packageConvertKnownErrors(upload.upload.Commit(), "", "")
}

// SetCustomMetadata updates custom metadata to be included with the object.
Expand Down Expand Up @@ -325,10 +333,13 @@ func SetObjectRetention(ctx context.Context, project *uplink.Project, bucket, ke

err = db.SetObjectRetention(ctx, bucket, key, version, retention)
// TODO: remove when we expose those in convertKnownErrors
if metaclient.ErrProjectNoLock.Has(err) {
switch {
case metaclient.ErrProjectNoLock.Has(err):
err = privateProject.ErrProjectNoLock
} else if metaclient.ErrBucketNoLock.Has(err) {
case metaclient.ErrBucketNoLock.Has(err):
err = privateBucket.ErrBucketNoLock
case metaclient.ErrRetentionNotFound.Has(err):
err = ErrRetentionNotFound
}

return convertKnownErrors(err, bucket, key)
Expand All @@ -346,10 +357,13 @@ func GetObjectRetention(ctx context.Context, project *uplink.Project, bucket, ke

retention, err = db.GetObjectRetention(ctx, bucket, key, version)
// TODO: remove when we expose those in convertKnownErrors
if metaclient.ErrProjectNoLock.Has(err) {
switch {
case metaclient.ErrProjectNoLock.Has(err):
err = privateProject.ErrProjectNoLock
} else if metaclient.ErrBucketNoLock.Has(err) {
case metaclient.ErrBucketNoLock.Has(err):
err = privateBucket.ErrBucketNoLock
case metaclient.ErrRetentionNotFound.Has(err):
err = ErrRetentionNotFound
}

return retention, convertKnownErrors(err, bucket, key)
Expand Down Expand Up @@ -405,6 +419,9 @@ func packageConvertKnownErrors(err error, bucket, key string) error {
if strings.HasSuffix(errs.Unwrap(err).Error(), "cannot specify Object Lock settings when uploading into a bucket without Object Lock enabled") {
return ErrNoObjectLockConfiguration
}
if strings.HasSuffix(errs.Unwrap(err).Error(), "cannot specify Object Lock settings when uploading into a bucket without Versioning enabled") {
return ErrBucketNoVersioningObjectLock
}
}
return convertKnownErrors(err, bucket, key)
}
Expand Down
20 changes: 13 additions & 7 deletions testsuite/private/object/object_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,15 +195,26 @@ func TestGetAndSetObjectRetention(t *testing.T) {

invalidBucket := "invalid-bucket"

retention := metaclient.Retention{
Mode: storj.ComplianceMode,
RetainUntil: time.Now().Add(time.Hour),
}

_, err = bucket.CreateBucketWithObjectLock(ctx, project, bucket.CreateBucketWithObjectLockParams{
Name: invalidBucket,
ObjectLockEnabled: false,
})
require.NoError(t, err)

upload, err := object.UploadObject(ctx, project, invalidBucket, "random-key", &object.UploadOptions{
Retention: retention,
})
require.NoError(t, err)
require.ErrorIs(t, upload.Commit(), object.ErrNoObjectLockConfiguration)

objectKey := "test-object"

upload, err := object.UploadObject(ctx, project, invalidBucket, objectKey, nil)
upload, err = object.UploadObject(ctx, project, invalidBucket, objectKey, nil)
require.NoError(t, err)

_, err = upload.Write([]byte("test1"))
Expand All @@ -216,11 +227,6 @@ func TestGetAndSetObjectRetention(t *testing.T) {
require.ErrorIs(t, err, bucket.ErrBucketNoLock)
require.Nil(t, objRetention)

retention := metaclient.Retention{
Mode: storj.ComplianceMode,
RetainUntil: time.Now().Add(time.Hour),
}

err = object.SetObjectRetention(ctx, project, invalidBucket, objectKey, upload.Info().Version, retention)
require.ErrorIs(t, err, bucket.ErrBucketNoLock)
require.Nil(t, objRetention)
Expand Down Expand Up @@ -254,7 +260,7 @@ func TestGetAndSetObjectRetention(t *testing.T) {
require.Nil(t, objRetention)

objRetention, err = object.GetObjectRetention(ctx, project, bucketName, objectKey, upload.Info().Version)
require.True(t, metaclient.ErrRetentionNotFound.Has(err))
require.ErrorIs(t, err, object.ErrRetentionNotFound)
require.Nil(t, objRetention)

err = object.SetObjectRetention(ctx, project, wrongBucket, objectKey, upload.Info().Version, retention)
Expand Down

0 comments on commit 0e957ac

Please sign in to comment.