diff --git a/api/errors/errors.go b/api/errors/errors.go index 6f839b8..8b5380e 100644 --- a/api/errors/errors.go +++ b/api/errors/errors.go @@ -1,10 +1,12 @@ package errors import ( + "errors" "fmt" "net/http" - frosterrors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/errors" + layerErr "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/errors" + frostErr "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/errors" ) type ( @@ -1765,7 +1767,7 @@ var errorCodes = errorCodeMap{ // IsS3Error checks if the provided error is a specific s3 error. func IsS3Error(err error, code ErrorCode) bool { - err = frosterrors.UnwrapErr(err) + err = frostErr.UnwrapErr(err) e, ok := err.(Error) return ok && e.ErrCode == code } @@ -1802,6 +1804,26 @@ func GetAPIErrorWithError(code ErrorCode, err error) Error { return errorCodes.toAPIErrWithErr(code, err) } +// TransformToS3Error converts FrostFS error to the corresponding S3 error type. +func TransformToS3Error(err error) error { + err = frostErr.UnwrapErr(err) // this wouldn't work with errors.Join + var s3err Error + if errors.As(err, &s3err) { + return err + } + + if errors.Is(err, layerErr.ErrAccessDenied) || + errors.Is(err, layerErr.ErrNodeAccessDenied) { + return GetAPIError(ErrAccessDenied) + } + + if errors.Is(err, layerErr.ErrGatewayTimeout) { + return GetAPIError(ErrGatewayTimeout) + } + + return GetAPIError(ErrInternalError) +} + // ObjectError -- error that is linked to a specific object. type ObjectError struct { Err error diff --git a/api/handler/util.go b/api/handler/util.go index dde5274..8fe1f75 100644 --- a/api/handler/util.go +++ b/api/handler/util.go @@ -13,7 +13,6 @@ import ( s3errors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware" - frosterrors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/errors" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "go.opentelemetry.io/otel/trace" @@ -30,7 +29,7 @@ func (h *handler) reqLogger(ctx context.Context) *zap.Logger { func (h *handler) logAndSendError(w http.ResponseWriter, logText string, reqInfo *middleware.ReqInfo, err error, additional ...zap.Field) { err = handleDeleteMarker(w, err) - if code, wrErr := middleware.WriteErrorResponse(w, reqInfo, transformToS3Error(err)); wrErr != nil { + if code, wrErr := middleware.WriteErrorResponse(w, reqInfo, s3errors.TransformToS3Error(err)); wrErr != nil { additional = append(additional, zap.NamedError("write_response_error", wrErr)) } else { additional = append(additional, zap.Int("status", code)) @@ -60,24 +59,6 @@ func handleDeleteMarker(w http.ResponseWriter, err error) error { return fmt.Errorf("%w: %s", s3errors.GetAPIError(target.ErrorCode), err) } -func transformToS3Error(err error) error { - err = frosterrors.UnwrapErr(err) // this wouldn't work with errors.Join - if _, ok := err.(s3errors.Error); ok { - return err - } - - if errors.Is(err, layer.ErrAccessDenied) || - errors.Is(err, layer.ErrNodeAccessDenied) { - return s3errors.GetAPIError(s3errors.ErrAccessDenied) - } - - if errors.Is(err, layer.ErrGatewayTimeout) { - return s3errors.GetAPIError(s3errors.ErrGatewayTimeout) - } - - return s3errors.GetAPIError(s3errors.ErrInternalError) -} - func (h *handler) ResolveBucket(ctx context.Context, bucket string) (*data.BucketInfo, error) { return h.obj.GetBucketInfo(ctx, bucket) } diff --git a/api/handler/util_test.go b/api/handler/util_test.go index 587f92c..6c769ca 100644 --- a/api/handler/util_test.go +++ b/api/handler/util_test.go @@ -1,12 +1,12 @@ package handler import ( - "errors" + stdErrors "errors" "fmt" "testing" s3errors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" - "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer" + "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/errors" "github.com/stretchr/testify/require" ) @@ -18,27 +18,27 @@ func TestTransformS3Errors(t *testing.T) { }{ { name: "simple std error to internal error", - err: errors.New("some error"), + err: stdErrors.New("some error"), expected: s3errors.ErrInternalError, }, { name: "layer access denied error to s3 access denied error", - err: layer.ErrAccessDenied, + err: errors.ErrAccessDenied, expected: s3errors.ErrAccessDenied, }, { name: "wrapped layer access denied error to s3 access denied error", - err: fmt.Errorf("wrap: %w", layer.ErrAccessDenied), + err: fmt.Errorf("wrap: %w", errors.ErrAccessDenied), expected: s3errors.ErrAccessDenied, }, { name: "layer node access denied error to s3 access denied error", - err: layer.ErrNodeAccessDenied, + err: errors.ErrNodeAccessDenied, expected: s3errors.ErrAccessDenied, }, { name: "layer gateway timeout error to s3 gateway timeout error", - err: layer.ErrGatewayTimeout, + err: errors.ErrGatewayTimeout, expected: s3errors.ErrGatewayTimeout, }, { @@ -53,7 +53,7 @@ func TestTransformS3Errors(t *testing.T) { }, } { t.Run(tc.name, func(t *testing.T) { - err := transformToS3Error(tc.err) + err := s3errors.TransformToS3Error(tc.err) s3err, ok := err.(s3errors.Error) require.True(t, ok, "error must be s3 error") require.Equalf(t, tc.expected, s3err.ErrCode, diff --git a/api/layer/compound.go b/api/layer/compound.go index 7ff3e37..bf0e24d 100644 --- a/api/layer/compound.go +++ b/api/layer/compound.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" s3errors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" + layerErr "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/errors" ) func (n *Layer) GetObjectTaggingAndLock(ctx context.Context, objVersion *data.ObjectVersion, nodeVersion *data.NodeVersion) (map[string]string, data.LockInfo, error) { @@ -29,7 +30,7 @@ func (n *Layer) GetObjectTaggingAndLock(ctx context.Context, objVersion *data.Ob tags, lockInfo, err = n.treeService.GetObjectTaggingAndLock(ctx, objVersion.BktInfo, nodeVersion) if err != nil { - if errors.Is(err, ErrNodeNotFound) { + if errors.Is(err, layerErr.ErrNodeNotFound) { return nil, data.LockInfo{}, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error()) } return nil, data.LockInfo{}, err diff --git a/api/layer/cors.go b/api/layer/cors.go index 43c0491..953b25d 100644 --- a/api/layer/cors.go +++ b/api/layer/cors.go @@ -3,12 +3,13 @@ package layer import ( "bytes" "context" - errorsStd "errors" + stdErrors "errors" "fmt" "io" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" - "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" + apiErrors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" + "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/errors" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -31,7 +32,7 @@ func (n *Layer) PutBucketCORS(ctx context.Context, p *PutCORSParams) error { } if cors.CORSRules == nil { - return errors.GetAPIError(errors.ErrMalformedXML) + return apiErrors.GetAPIError(apiErrors.ErrMalformedXML) } if err := checkCORS(cors); err != nil { @@ -61,7 +62,7 @@ func (n *Layer) PutBucketCORS(ctx context.Context, p *PutCORSParams) error { } objsToDelete, err := n.treeService.PutBucketCORS(ctx, p.BktInfo, newAddress(corsBkt.CID, createdObj.ID)) - objToDeleteNotFound := errorsStd.Is(err, ErrNoNodeToRemove) + objToDeleteNotFound := stdErrors.Is(err, errors.ErrNoNodeToRemove) if err != nil && !objToDeleteNotFound { return err } @@ -104,7 +105,7 @@ func (n *Layer) GetBucketCORS(ctx context.Context, bktInfo *data.BucketInfo) (*d func (n *Layer) DeleteBucketCORS(ctx context.Context, bktInfo *data.BucketInfo) error { objs, err := n.treeService.DeleteBucketCORS(ctx, bktInfo) - objNotFound := errorsStd.Is(err, ErrNoNodeToRemove) + objNotFound := stdErrors.Is(err, errors.ErrNoNodeToRemove) if err != nil && !objNotFound { return err } @@ -124,12 +125,12 @@ func checkCORS(cors *data.CORSConfiguration) error { for _, r := range cors.CORSRules { for _, m := range r.AllowedMethods { if _, ok := supportedMethods[m]; !ok { - return errors.GetAPIErrorWithError(errors.ErrCORSUnsupportedMethod, fmt.Errorf("unsupported method is %s", m)) + return apiErrors.GetAPIErrorWithError(apiErrors.ErrCORSUnsupportedMethod, fmt.Errorf("unsupported method is %s", m)) } } for _, h := range r.ExposeHeaders { if h == wildcard { - return errors.GetAPIError(errors.ErrCORSWildcardExposeHeaders) + return apiErrors.GetAPIError(apiErrors.ErrCORSWildcardExposeHeaders) } } } diff --git a/api/layer/errors/errors.go b/api/layer/errors/errors.go new file mode 100644 index 0000000..fffdee7 --- /dev/null +++ b/api/layer/errors/errors.go @@ -0,0 +1,16 @@ +package errors + +import "errors" + +var ( + // ErrAccessDenied is returned from FrostFS in case of access violation. + ErrAccessDenied = errors.New("access denied") + // ErrGatewayTimeout is returned from FrostFS in case of timeout, deadline exceeded etc. + ErrGatewayTimeout = errors.New("gateway timeout") + // ErrNodeNotFound is returned from Tree service in case of not found error. + ErrNodeNotFound = errors.New("not found") + // ErrNodeAccessDenied is returned from Tree service in case of access denied error. + ErrNodeAccessDenied = errors.New("access denied") + // ErrNoNodeToRemove is returned from Tree service in case of the lack of node with OID to remove. + ErrNoNodeToRemove = errors.New("no node to remove") +) diff --git a/api/layer/frostfs.go b/api/layer/frostfs.go index 3f01f2f..37aa5c5 100644 --- a/api/layer/frostfs.go +++ b/api/layer/frostfs.go @@ -3,7 +3,6 @@ package layer import ( "context" "crypto/ecdsa" - "errors" "io" "time" @@ -221,14 +220,6 @@ type PrmObjectPatch struct { ObjectSize uint64 } -var ( - // ErrAccessDenied is returned from FrostFS in case of access violation. - ErrAccessDenied = errors.New("access denied") - - // ErrGatewayTimeout is returned from FrostFS in case of timeout, deadline exceeded etc. - ErrGatewayTimeout = errors.New("gateway timeout") -) - // FrostFS represents virtual connection to FrostFS network. type FrostFS interface { // CreateContainer creates and saves parameterized container in FrostFS. diff --git a/api/layer/frostfs_mock.go b/api/layer/frostfs_mock.go index b416dcc..7d3297b 100644 --- a/api/layer/frostfs_mock.go +++ b/api/layer/frostfs_mock.go @@ -12,6 +12,7 @@ import ( v2container "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" objectv2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/errors" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" @@ -220,7 +221,7 @@ func (t *TestFrostFS) retrieveObject(ctx context.Context, cnrID cid.ID, objID oi if obj, ok := t.objects[sAddr]; ok { owner := getBearerOwner(ctx) if !t.checkAccess(cnrID, owner) { - return nil, ErrAccessDenied + return nil, errors.ErrAccessDenied } return obj, nil @@ -345,7 +346,7 @@ func (t *TestFrostFS) DeleteObject(ctx context.Context, prm PrmObjectDelete) err if _, ok := t.objects[addr.EncodeToString()]; ok { owner := getBearerOwner(ctx) if !t.checkAccess(prm.Container, owner) { - return ErrAccessDenied + return errors.ErrAccessDenied } delete(t.objects, addr.EncodeToString()) diff --git a/api/layer/layer.go b/api/layer/layer.go index 57f804d..c87fe1a 100644 --- a/api/layer/layer.go +++ b/api/layer/layer.go @@ -17,9 +17,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" - "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" s3errors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/encryption" + "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/errors" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" @@ -331,7 +331,7 @@ func (n *Layer) GetBucketInfo(ctx context.Context, name string) (*data.BucketInf containerID, err := n.ResolveBucket(ctx, zone, name) if err != nil { if strings.Contains(err.Error(), "not found") { - return nil, fmt.Errorf("%w: %s", errors.GetAPIError(errors.ErrNoSuchBucket), err.Error()) + return nil, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchBucket), err.Error()) } return nil, err } @@ -397,9 +397,9 @@ func (n *Layer) GetObject(ctx context.Context, p *GetObjectParams) (*ObjectPaylo if err != nil { if client.IsErrObjectNotFound(err) { if p.Versioned { - err = fmt.Errorf("%w: %s", errors.GetAPIError(errors.ErrNoSuchVersion), err.Error()) + err = fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchVersion), err.Error()) } else { - err = fmt.Errorf("%w: %s", errors.GetAPIError(errors.ErrNoSuchKey), err.Error()) + err = fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error()) } } @@ -655,15 +655,15 @@ func (n *Layer) handleNotFoundError(bkt *data.BucketInfo, obj *VersionedObject) } func isNotFoundError(err error) bool { - return errors.IsS3Error(err, errors.ErrNoSuchKey) || - errors.IsS3Error(err, errors.ErrNoSuchVersion) + return s3errors.IsS3Error(err, s3errors.ErrNoSuchKey) || + s3errors.IsS3Error(err, s3errors.ErrNoSuchVersion) } func (n *Layer) getNodeVersionsToDelete(ctx context.Context, bkt *data.BucketInfo, obj *VersionedObject) ([]*data.NodeVersion, error) { var versionsToDelete []*data.NodeVersion versions, err := n.treeService.GetVersions(ctx, bkt, obj.Name) if err != nil { - if stderrors.Is(err, ErrNodeNotFound) { + if stderrors.Is(err, errors.ErrNodeNotFound) { return nil, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error()) } return nil, err @@ -785,17 +785,17 @@ func (n *Layer) DeleteObjects(ctx context.Context, p *DeleteObjectParams) []*Ver func (n *Layer) CreateBucket(ctx context.Context, p *CreateBucketParams) (*data.BucketInfo, error) { bktInfo, err := n.GetBucketInfo(ctx, p.Name) if err != nil { - if errors.IsS3Error(err, errors.ErrNoSuchBucket) { + if s3errors.IsS3Error(err, s3errors.ErrNoSuchBucket) { return n.createContainer(ctx, p) } return nil, err } if p.SessionContainerCreation != nil && session.IssuedBy(*p.SessionContainerCreation, bktInfo.Owner) { - return nil, errors.GetAPIError(errors.ErrBucketAlreadyOwnedByYou) + return nil, s3errors.GetAPIError(s3errors.ErrBucketAlreadyOwnedByYou) } - return nil, errors.GetAPIError(errors.ErrBucketAlreadyExists) + return nil, s3errors.GetAPIError(s3errors.ErrBucketAlreadyExists) } func (n *Layer) ResolveBucket(ctx context.Context, zone, name string) (cid.ID, error) { @@ -822,7 +822,7 @@ func (n *Layer) DeleteBucket(ctx context.Context, p *DeleteBucketParams) error { return err } if len(res) != 0 { - return errors.GetAPIError(errors.ErrBucketNotEmpty) + return s3errors.GetAPIError(s3errors.ErrBucketNotEmpty) } } diff --git a/api/layer/lifecycle.go b/api/layer/lifecycle.go index ad052aa..0610d04 100644 --- a/api/layer/lifecycle.go +++ b/api/layer/lifecycle.go @@ -5,12 +5,13 @@ import ( "context" "encoding/base64" "encoding/xml" - "errors" + stderrors "errors" "fmt" "io" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" apiErr "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" + "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/errors" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" @@ -59,7 +60,7 @@ func (n *Layer) PutBucketLifecycleConfiguration(ctx context.Context, p *PutBucke } objsToDelete, err := n.treeService.PutBucketLifecycleConfiguration(ctx, p.BktInfo, newAddress(lifecycleBkt.CID, createdObj.ID)) - objsToDeleteNotFound := errors.Is(err, ErrNoNodeToRemove) + objsToDeleteNotFound := stderrors.Is(err, errors.ErrNoNodeToRemove) if err != nil && !objsToDeleteNotFound { return err } @@ -98,7 +99,7 @@ func (n *Layer) GetBucketLifecycleConfiguration(ctx context.Context, bktInfo *da } addr, err := n.treeService.GetBucketLifecycleConfiguration(ctx, bktInfo) - objNotFound := errors.Is(err, ErrNodeNotFound) + objNotFound := stderrors.Is(err, errors.ErrNodeNotFound) if err != nil && !objNotFound { return nil, err } @@ -132,7 +133,7 @@ func (n *Layer) GetBucketLifecycleConfiguration(ctx context.Context, bktInfo *da func (n *Layer) DeleteBucketLifecycleConfiguration(ctx context.Context, bktInfo *data.BucketInfo) error { objs, err := n.treeService.DeleteBucketLifecycleConfiguration(ctx, bktInfo) - objsNotFound := errors.Is(err, ErrNoNodeToRemove) + objsNotFound := stderrors.Is(err, errors.ErrNoNodeToRemove) if err != nil && !objsNotFound { return err } diff --git a/api/layer/multipart_upload.go b/api/layer/multipart_upload.go index c99173d..20d8cc1 100644 --- a/api/layer/multipart_upload.go +++ b/api/layer/multipart_upload.go @@ -7,7 +7,7 @@ import ( "encoding/base64" "encoding/hex" "encoding/json" - "errors" + stdErrors "errors" "fmt" "io" "sort" @@ -19,6 +19,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" s3errors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/encryption" + "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/errors" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" @@ -187,7 +188,7 @@ func (n *Layer) CreateMultipartUpload(ctx context.Context, p *CreateMultipartPar func (n *Layer) UploadPart(ctx context.Context, p *UploadPartParams) (string, error) { multipartInfo, err := n.treeService.GetMultipartUpload(ctx, p.Info.Bkt, p.Info.Key, p.Info.UploadID) if err != nil { - if errors.Is(err, ErrNodeNotFound) { + if stdErrors.Is(err, errors.ErrNodeNotFound) { return "", fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchUpload), err.Error()) } return "", err @@ -291,7 +292,7 @@ func (n *Layer) uploadPart(ctx context.Context, multipartInfo *data.MultipartInf } oldPartIDs, err := n.treeService.AddPart(ctx, bktInfo, multipartInfo.ID, partInfo) - oldPartIDNotFound := errors.Is(err, ErrNoNodeToRemove) + oldPartIDNotFound := stdErrors.Is(err, errors.ErrNoNodeToRemove) if err != nil && !oldPartIDNotFound { return nil, err } @@ -323,7 +324,7 @@ func (n *Layer) uploadPart(ctx context.Context, multipartInfo *data.MultipartInf func (n *Layer) UploadPartCopy(ctx context.Context, p *UploadCopyParams) (*data.ObjectInfo, error) { multipartInfo, err := n.treeService.GetMultipartUpload(ctx, p.Info.Bkt, p.Info.Key, p.Info.UploadID) if err != nil { - if errors.Is(err, ErrNodeNotFound) { + if stdErrors.Is(err, errors.ErrNodeNotFound) { return nil, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchUpload), err.Error()) } return nil, err @@ -646,7 +647,7 @@ func (p PartsInfo) Extract(part int, etag string, md5Enabled bool) *data.PartInf func (n *Layer) getUploadParts(ctx context.Context, p *UploadInfoParams) (*data.MultipartInfo, PartsInfo, error) { multipartInfo, err := n.treeService.GetMultipartUpload(ctx, p.Bkt, p.Key, p.UploadID) if err != nil { - if errors.Is(err, ErrNodeNotFound) { + if stdErrors.Is(err, errors.ErrNodeNotFound) { return nil, nil, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchUpload), err.Error()) } return nil, nil, err diff --git a/api/layer/object.go b/api/layer/object.go index 8c4549d..a4ab324 100644 --- a/api/layer/object.go +++ b/api/layer/object.go @@ -8,7 +8,7 @@ import ( "encoding/base64" "encoding/hex" "encoding/json" - "errors" + stdErrors "errors" "fmt" "io" "mime" @@ -20,6 +20,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" apiErrors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" + "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/errors" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -380,7 +381,7 @@ func (n *Layer) headLastVersionIfNotDeleted(ctx context.Context, bkt *data.Bucke node, err := n.treeService.GetLatestVersion(ctx, bkt, objectName) if err != nil { - if errors.Is(err, ErrNodeNotFound) { + if stdErrors.Is(err, errors.ErrNodeNotFound) { return nil, fmt.Errorf("%w: %s", apiErrors.GetAPIError(apiErrors.ErrNoSuchKey), err.Error()) } return nil, err @@ -416,7 +417,7 @@ func (n *Layer) headVersion(ctx context.Context, bkt *data.BucketInfo, p *HeadOb if p.VersionID == data.UnversionedObjectVersionID { foundVersion, err = n.treeService.GetUnversioned(ctx, bkt, p.Object) if err != nil { - if errors.Is(err, ErrNodeNotFound) { + if stdErrors.Is(err, errors.ErrNodeNotFound) { return nil, fmt.Errorf("%w: %s", apiErrors.GetAPIError(apiErrors.ErrNoSuchVersion), err.Error()) } return nil, err diff --git a/api/layer/system_object.go b/api/layer/system_object.go index 81f0b3f..46da7c0 100644 --- a/api/layer/system_object.go +++ b/api/layer/system_object.go @@ -3,7 +3,7 @@ package layer import ( "context" "encoding/xml" - errorsStd "errors" + stdErrors "errors" "fmt" "math" "strconv" @@ -11,7 +11,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" - "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" + apiErrors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" + "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/errors" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) @@ -40,7 +41,7 @@ func (n *Layer) PutLockInfo(ctx context.Context, p *PutLockInfoParams) (err erro } lockInfo, err := n.treeService.GetLock(ctx, p.ObjVersion.BktInfo, versionNode.ID) - if err != nil && !errorsStd.Is(err, ErrNodeNotFound) { + if err != nil && !stdErrors.Is(err, errors.ErrNodeNotFound) { return err } @@ -146,7 +147,7 @@ func (n *Layer) GetLockInfo(ctx context.Context, objVersion *data.ObjectVersion) } lockInfo, err := n.treeService.GetLock(ctx, objVersion.BktInfo, versionNode.ID) - if err != nil && !errorsStd.Is(err, ErrNodeNotFound) { + if err != nil && !stdErrors.Is(err, errors.ErrNodeNotFound) { return nil, err } if lockInfo == nil { @@ -165,13 +166,13 @@ func (n *Layer) getCORS(ctx context.Context, bkt *data.BucketInfo) (*data.CORSCo } addr, err := n.treeService.GetBucketCORS(ctx, bkt) - objNotFound := errorsStd.Is(err, ErrNodeNotFound) + objNotFound := stdErrors.Is(err, errors.ErrNodeNotFound) if err != nil && !objNotFound { return nil, err } if objNotFound { - return nil, fmt.Errorf("%w: %s", errors.GetAPIError(errors.ErrNoSuchCORSConfiguration), err.Error()) + return nil, fmt.Errorf("%w: %s", apiErrors.GetAPIError(apiErrors.ErrNoSuchCORSConfiguration), err.Error()) } var prmAuth PrmAuth @@ -209,7 +210,7 @@ func (n *Layer) GetBucketSettings(ctx context.Context, bktInfo *data.BucketInfo) settings, err := n.treeService.GetSettingsNode(ctx, bktInfo) if err != nil { - if !errorsStd.Is(err, ErrNodeNotFound) { + if !stdErrors.Is(err, errors.ErrNodeNotFound) { return nil, err } settings = &data.BucketSettings{Versioning: data.VersioningUnversioned} diff --git a/api/layer/tagging.go b/api/layer/tagging.go index 293b6f6..9b6d19a 100644 --- a/api/layer/tagging.go +++ b/api/layer/tagging.go @@ -2,11 +2,12 @@ package layer import ( "context" - "errors" + stdErrors "errors" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" s3errors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" + "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/errors" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -39,7 +40,7 @@ func (n *Layer) GetObjectTagging(ctx context.Context, p *data.GetObjectTaggingPa tags, err := n.treeService.GetObjectTagging(ctx, p.ObjectVersion.BktInfo, nodeVersion) if err != nil { - if errors.Is(err, ErrNodeNotFound) { + if stdErrors.Is(err, errors.ErrNodeNotFound) { return "", nil, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error()) } return "", nil, err @@ -62,7 +63,7 @@ func (n *Layer) PutObjectTagging(ctx context.Context, p *data.PutObjectTaggingPa err = n.treeService.PutObjectTagging(ctx, p.ObjectVersion.BktInfo, nodeVersion, p.TagSet) if err != nil { - if errors.Is(err, ErrNodeNotFound) { + if stdErrors.Is(err, errors.ErrNodeNotFound) { return fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error()) } return err @@ -81,7 +82,7 @@ func (n *Layer) DeleteObjectTagging(ctx context.Context, p *data.ObjectVersion) err = n.treeService.DeleteObjectTagging(ctx, p.BktInfo, version) if err != nil { - if errors.Is(err, ErrNodeNotFound) { + if stdErrors.Is(err, errors.ErrNodeNotFound) { return fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error()) } return err @@ -102,7 +103,7 @@ func (n *Layer) GetBucketTagging(ctx context.Context, bktInfo *data.BucketInfo) } tags, err := n.treeService.GetBucketTagging(ctx, bktInfo) - if err != nil && !errors.Is(err, ErrNodeNotFound) { + if err != nil && !stdErrors.Is(err, errors.ErrNodeNotFound) { return nil, err } @@ -161,7 +162,7 @@ func (n *Layer) getNodeVersion(ctx context.Context, objVersion *data.ObjectVersi if err == nil && version.IsDeleteMarker && !objVersion.NoErrorOnDeleteMarker { return nil, fmt.Errorf("%w: found version is delete marker", s3errors.GetAPIError(s3errors.ErrNoSuchKey)) - } else if errors.Is(err, ErrNodeNotFound) { + } else if stdErrors.Is(err, errors.ErrNodeNotFound) { return nil, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error()) } diff --git a/api/layer/tree_mock.go b/api/layer/tree_mock.go index 8a85ffb..738b243 100644 --- a/api/layer/tree_mock.go +++ b/api/layer/tree_mock.go @@ -9,6 +9,7 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" + "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/errors" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) @@ -105,7 +106,7 @@ func (t *TreeServiceMock) PutSettingsNode(_ context.Context, bktInfo *data.Bucke func (t *TreeServiceMock) GetSettingsNode(_ context.Context, bktInfo *data.BucketInfo) (*data.BucketSettings, error) { settings, ok := t.settings[bktInfo.CID.EncodeToString()] if !ok { - return nil, ErrNodeNotFound + return nil, errors.ErrNodeNotFound } return settings, nil @@ -140,7 +141,7 @@ func (t *TreeServiceMock) PutBucketCORS(_ context.Context, bktInfo *data.BucketI t.system[bktInfo.CID.EncodeToString()] = systemMap - return nil, ErrNoNodeToRemove + return nil, errors.ErrNoNodeToRemove } func (t *TreeServiceMock) DeleteBucketCORS(context.Context, *data.BucketInfo) ([]oid.Address, error) { @@ -150,12 +151,12 @@ func (t *TreeServiceMock) DeleteBucketCORS(context.Context, *data.BucketInfo) ([ func (t *TreeServiceMock) GetVersions(_ context.Context, bktInfo *data.BucketInfo, objectName string) ([]*data.NodeVersion, error) { cnrVersionsMap, ok := t.versions[bktInfo.CID.EncodeToString()] if !ok { - return nil, ErrNodeNotFound + return nil, errors.ErrNodeNotFound } versions, ok := cnrVersionsMap[objectName] if !ok { - return nil, ErrNodeNotFound + return nil, errors.ErrNodeNotFound } return versions, nil @@ -164,12 +165,12 @@ func (t *TreeServiceMock) GetVersions(_ context.Context, bktInfo *data.BucketInf func (t *TreeServiceMock) GetLatestVersion(_ context.Context, bktInfo *data.BucketInfo, objectName string) (*data.NodeVersion, error) { cnrVersionsMap, ok := t.versions[bktInfo.CID.EncodeToString()] if !ok { - return nil, ErrNodeNotFound + return nil, errors.ErrNodeNotFound } versions, ok := cnrVersionsMap[objectName] if !ok { - return nil, ErrNodeNotFound + return nil, errors.ErrNodeNotFound } sort.Slice(versions, func(i, j int) bool { @@ -180,13 +181,13 @@ func (t *TreeServiceMock) GetLatestVersion(_ context.Context, bktInfo *data.Buck return versions[len(versions)-1], nil } - return nil, ErrNodeNotFound + return nil, errors.ErrNodeNotFound } func (t *TreeServiceMock) InitVersionsByPrefixStream(_ context.Context, bktInfo *data.BucketInfo, prefix string, latestOnly bool) (data.VersionsStream, error) { cnrVersionsMap, ok := t.versions[bktInfo.CID.EncodeToString()] if !ok { - return nil, ErrNodeNotFound + return nil, errors.ErrNodeNotFound } var result []*data.NodeVersion @@ -218,12 +219,12 @@ func (t *TreeServiceMock) InitVersionsByPrefixStream(_ context.Context, bktInfo func (t *TreeServiceMock) GetUnversioned(_ context.Context, bktInfo *data.BucketInfo, objectName string) (*data.NodeVersion, error) { cnrVersionsMap, ok := t.versions[bktInfo.CID.EncodeToString()] if !ok { - return nil, ErrNodeNotFound + return nil, errors.ErrNodeNotFound } versions, ok := cnrVersionsMap[objectName] if !ok { - return nil, ErrNodeNotFound + return nil, errors.ErrNodeNotFound } for _, version := range versions { @@ -232,7 +233,7 @@ func (t *TreeServiceMock) GetUnversioned(_ context.Context, bktInfo *data.Bucket } } - return nil, ErrNodeNotFound + return nil, errors.ErrNodeNotFound } func (t *TreeServiceMock) AddVersion(_ context.Context, bktInfo *data.BucketInfo, newVersion *data.NodeVersion) (uint64, error) { @@ -278,7 +279,7 @@ func (t *TreeServiceMock) AddVersion(_ context.Context, bktInfo *data.BucketInfo func (t *TreeServiceMock) RemoveVersion(_ context.Context, bktInfo *data.BucketInfo, nodeID uint64) error { cnrVersionsMap, ok := t.versions[bktInfo.CID.EncodeToString()] if !ok { - return ErrNodeNotFound + return errors.ErrNodeNotFound } for key, versions := range cnrVersionsMap { @@ -290,7 +291,7 @@ func (t *TreeServiceMock) RemoveVersion(_ context.Context, bktInfo *data.BucketI } } - return ErrNodeNotFound + return errors.ErrNodeNotFound } func (t *TreeServiceMock) GetAllVersionsByPrefix(_ context.Context, bktInfo *data.BucketInfo, prefix string) ([]*data.NodeVersion, error) { @@ -334,7 +335,7 @@ func (t *TreeServiceMock) GetMultipartUploadsByPrefix(context.Context, *data.Buc func (t *TreeServiceMock) GetMultipartUpload(_ context.Context, bktInfo *data.BucketInfo, objectName, uploadID string) (*data.MultipartInfo, error) { cnrMultipartsMap, ok := t.multiparts[bktInfo.CID.EncodeToString()] if !ok { - return nil, ErrNodeNotFound + return nil, errors.ErrNodeNotFound } multiparts := cnrMultipartsMap[objectName] @@ -344,7 +345,7 @@ func (t *TreeServiceMock) GetMultipartUpload(_ context.Context, bktInfo *data.Bu } } - return nil, ErrNodeNotFound + return nil, errors.ErrNodeNotFound } func (t *TreeServiceMock) AddPart(ctx context.Context, bktInfo *data.BucketInfo, multipartNodeID uint64, info *data.PartInfo) (oldObjIDsToDelete []oid.ID, err error) { @@ -387,7 +388,7 @@ LOOP: } if foundMultipart == nil { - return nil, ErrNodeNotFound + return nil, errors.ErrNodeNotFound } partsMap := t.parts[foundMultipart.UploadID] @@ -411,18 +412,18 @@ func (t *TreeServiceMock) PutBucketLifecycleConfiguration(_ context.Context, bkt t.system[bktInfo.CID.EncodeToString()] = systemMap - return nil, ErrNoNodeToRemove + return nil, errors.ErrNoNodeToRemove } func (t *TreeServiceMock) GetBucketLifecycleConfiguration(_ context.Context, bktInfo *data.BucketInfo) (oid.Address, error) { systemMap, ok := t.system[bktInfo.CID.EncodeToString()] if !ok { - return oid.Address{}, ErrNodeNotFound + return oid.Address{}, errors.ErrNodeNotFound } node, ok := systemMap["lifecycle"] if !ok { - return oid.Address{}, ErrNodeNotFound + return oid.Address{}, errors.ErrNodeNotFound } return newAddress(bktInfo.CID, node.OID), nil @@ -431,12 +432,12 @@ func (t *TreeServiceMock) GetBucketLifecycleConfiguration(_ context.Context, bkt func (t *TreeServiceMock) DeleteBucketLifecycleConfiguration(_ context.Context, bktInfo *data.BucketInfo) ([]oid.Address, error) { systemMap, ok := t.system[bktInfo.CID.EncodeToString()] if !ok { - return nil, ErrNoNodeToRemove + return nil, errors.ErrNoNodeToRemove } node, ok := systemMap["lifecycle"] if !ok { - return nil, ErrNoNodeToRemove + return nil, errors.ErrNoNodeToRemove } delete(systemMap, "lifecycle") @@ -461,7 +462,7 @@ LOOP: } if uploadID == "" { - return ErrNodeNotFound + return errors.ErrNodeNotFound } delete(t.parts, uploadID) diff --git a/api/layer/tree_service.go b/api/layer/tree_service.go index 5a2047a..ed8dad7 100644 --- a/api/layer/tree_service.go +++ b/api/layer/tree_service.go @@ -2,7 +2,6 @@ package layer import ( "context" - "errors" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -72,14 +71,3 @@ type TreeService interface { // GetObjectTaggingAndLock unifies GetObjectTagging and GetLock methods in single tree service invocation. GetObjectTaggingAndLock(ctx context.Context, bktInfo *data.BucketInfo, objVersion *data.NodeVersion) (map[string]string, *data.LockInfo, error) } - -var ( - // ErrNodeNotFound is returned from Tree service in case of not found error. - ErrNodeNotFound = errors.New("not found") - - // ErrNodeAccessDenied is returned from Tree service in case of access denied error. - ErrNodeAccessDenied = errors.New("access denied") - - // ErrNoNodeToRemove is returned from Tree service in case of the lack of node with OID to remove. - ErrNoNodeToRemove = errors.New("no node to remove") -) diff --git a/api/layer/util.go b/api/layer/util.go index f3ba2b0..36e81c1 100644 --- a/api/layer/util.go +++ b/api/layer/util.go @@ -3,9 +3,7 @@ package layer import ( "encoding/hex" "fmt" - "os" "strconv" - "strings" "time" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" @@ -13,9 +11,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" ) -// PathSeparator is a path components separator string. -const PathSeparator = string(os.PathSeparator) - func userHeaders(attrs []object.Attribute) map[string]string { result := make(map[string]string, len(attrs)) @@ -111,9 +106,3 @@ func filepathFromObject(o *object.Object) string { objID, _ := o.ID() return objID.EncodeToString() } - -// NameFromString splits name into a base file name and a directory path. -func NameFromString(name string) (string, string) { - ind := strings.LastIndex(name, PathSeparator) - return name[ind+1:], name[:ind+1] -} diff --git a/api/middleware/policy.go b/api/middleware/policy.go index f3bcd63..4cc8d7f 100644 --- a/api/middleware/policy.go +++ b/api/middleware/policy.go @@ -12,7 +12,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" apiErr "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" - frostfsErrors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/errors" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" @@ -85,7 +84,7 @@ func PolicyCheck(cfg PolicyConfig) Func { ctx := r.Context() if err := policyCheck(r, cfg); err != nil { reqLogOrDefault(ctx, cfg.Log).Error(logs.PolicyValidationFailed, zap.Error(err)) - err = frostfsErrors.UnwrapErr(err) + err = apiErr.TransformToS3Error(err) if _, wrErr := WriteErrorResponse(w, GetReqInfo(ctx), err); wrErr != nil { reqLogOrDefault(ctx, cfg.Log).Error(logs.FailedToWriteResponse, zap.Error(wrErr)) } diff --git a/api/middleware/response.go b/api/middleware/response.go index b94b403..94b633d 100644 --- a/api/middleware/response.go +++ b/api/middleware/response.go @@ -62,7 +62,7 @@ const ( hdrSSE = "X-Amz-Server-Side-Encryption" // hdrSSECustomerKey is the HTTP header key referencing the - // SSE-C client-provided key.. + // SSE-C client-provided key. hdrSSECustomerKey = hdrSSE + "-Customer-Key" // hdrSSECopyKey is the HTTP header key referencing the SSE-C @@ -74,7 +74,7 @@ var ( xmlHeader = []byte(xml.Header) ) -// Non exhaustive list of AWS S3 standard error responses - +// Non-exhaustive list of AWS S3 standard error responses - // http://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html var s3ErrorResponseMap = map[string]string{ "AccessDenied": "Access Denied.", diff --git a/internal/frostfs/frostfs.go b/internal/frostfs/frostfs.go index 5fd935b..85788f1 100644 --- a/internal/frostfs/frostfs.go +++ b/internal/frostfs/frostfs.go @@ -11,6 +11,7 @@ import ( objectv2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer" + layerErr "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/errors" errorsFrost "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/errors" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" @@ -467,11 +468,11 @@ func handleObjectError(msg string, err error) error { } if reason, ok := errorsFrost.IsErrObjectAccessDenied(err); ok { - return fmt.Errorf("%s: %w: %s", msg, layer.ErrAccessDenied, reason) + return fmt.Errorf("%s: %w: %s", msg, layerErr.ErrAccessDenied, reason) } if errorsFrost.IsTimeoutError(err) { - return fmt.Errorf("%s: %w: %s", msg, layer.ErrGatewayTimeout, err.Error()) + return fmt.Errorf("%s: %w: %s", msg, layerErr.ErrGatewayTimeout, err.Error()) } return fmt.Errorf("%s: %w", msg, err) diff --git a/internal/frostfs/frostfs_test.go b/internal/frostfs/frostfs_test.go index a3b9bf2..d52072e 100644 --- a/internal/frostfs/frostfs_test.go +++ b/internal/frostfs/frostfs_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer" + layerErr "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/errors" errorsFrost "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/errors" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "github.com/stretchr/testify/require" @@ -23,10 +23,10 @@ func TestErrorChecking(t *testing.T) { var wrappedError error if fetchedReason, ok := errorsFrost.IsErrObjectAccessDenied(err); ok { - wrappedError = fmt.Errorf("%w: %s", layer.ErrAccessDenied, fetchedReason) + wrappedError = fmt.Errorf("%w: %s", layerErr.ErrAccessDenied, fetchedReason) } - require.ErrorIs(t, wrappedError, layer.ErrAccessDenied) + require.ErrorIs(t, wrappedError, layerErr.ErrAccessDenied) require.Contains(t, wrappedError.Error(), reason) } diff --git a/pkg/service/tree/tree.go b/pkg/service/tree/tree.go index c89d6af..ebd3fa6 100644 --- a/pkg/service/tree/tree.go +++ b/pkg/service/tree/tree.go @@ -12,7 +12,7 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" - "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer" + layerErr "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/errors" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -75,13 +75,13 @@ const ( var ( // ErrNodeNotFound is returned from ServiceClient in case of not found error. - ErrNodeNotFound = layer.ErrNodeNotFound + ErrNodeNotFound = layerErr.ErrNodeNotFound // ErrNodeAccessDenied is returned from ServiceClient service in case of access denied error. - ErrNodeAccessDenied = layer.ErrNodeAccessDenied + ErrNodeAccessDenied = layerErr.ErrNodeAccessDenied // ErrGatewayTimeout is returned from ServiceClient service in case of timeout error. - ErrGatewayTimeout = layer.ErrGatewayTimeout + ErrGatewayTimeout = layerErr.ErrGatewayTimeout errNodeDoesntContainFileName = fmt.Errorf("node doesn't contain FileName") ) @@ -523,7 +523,7 @@ func (c *Tree) GetSettingsNode(ctx context.Context, bktInfo *data.BucketInfo) (* func (c *Tree) PutSettingsNode(ctx context.Context, bktInfo *data.BucketInfo, settings *data.BucketSettings) error { multiNode, err := c.getSystemNode(ctx, bktInfo, settingsFileName) - isErrNotFound := errors.Is(err, layer.ErrNodeNotFound) + isErrNotFound := errors.Is(err, layerErr.ErrNodeNotFound) if err != nil && !isErrNotFound { return fmt.Errorf("couldn't get node: %w", err) } @@ -561,7 +561,7 @@ func (c *Tree) GetBucketCORS(ctx context.Context, bktInfo *data.BucketInfo) (oid func (c *Tree) PutBucketCORS(ctx context.Context, bktInfo *data.BucketInfo, addr oid.Address) ([]oid.Address, error) { multiNode, err := c.getSystemNode(ctx, bktInfo, corsFilename) - isErrNotFound := errors.Is(err, layer.ErrNodeNotFound) + isErrNotFound := errors.Is(err, layerErr.ErrNodeNotFound) if err != nil && !isErrNotFound { return nil, fmt.Errorf("couldn't get node: %w", err) } @@ -575,7 +575,7 @@ func (c *Tree) PutBucketCORS(ctx context.Context, bktInfo *data.BucketInfo, addr if _, err = c.service.AddNode(ctx, bktInfo, systemTree, 0, meta); err != nil { return nil, err } - return nil, layer.ErrNoNodeToRemove + return nil, layerErr.ErrNoNodeToRemove } latest := multiNode.Latest() @@ -601,13 +601,13 @@ func (c *Tree) PutBucketCORS(ctx context.Context, bktInfo *data.BucketInfo, addr func (c *Tree) DeleteBucketCORS(ctx context.Context, bktInfo *data.BucketInfo) ([]oid.Address, error) { multiNode, err := c.getSystemNode(ctx, bktInfo, corsFilename) - isErrNotFound := errors.Is(err, layer.ErrNodeNotFound) + isErrNotFound := errors.Is(err, layerErr.ErrNodeNotFound) if err != nil && !isErrNotFound { return nil, err } if isErrNotFound { - return nil, layer.ErrNoNodeToRemove + return nil, layerErr.ErrNoNodeToRemove } objToDelete := c.cleanOldNodes(ctx, multiNode.nodes, bktInfo) @@ -730,7 +730,7 @@ func (c *Tree) GetBucketTagging(ctx context.Context, bktInfo *data.BucketInfo) ( func (c *Tree) PutBucketTagging(ctx context.Context, bktInfo *data.BucketInfo, tagSet map[string]string) error { multiNode, err := c.getSystemNode(ctx, bktInfo, bucketTaggingFilename) - isErrNotFound := errors.Is(err, layer.ErrNodeNotFound) + isErrNotFound := errors.Is(err, layerErr.ErrNodeNotFound) if err != nil && !isErrNotFound { return fmt.Errorf("couldn't get node: %w", err) } @@ -852,7 +852,7 @@ func getLatestVersionNode(nodes []NodeResponse) (NodeResponse, error) { } if targetIndexNode == -1 { - return nil, layer.ErrNodeNotFound + return nil, layerErr.ErrNodeNotFound } return nodes[targetIndexNode], nil @@ -977,7 +977,7 @@ func (s *VersionsByPrefixStreamImpl) getNodeFromMainStream() (NodeResponse, erro for { node, err := s.mainStream.Next() if err != nil { - if errors.Is(err, ErrNodeNotFound) { + if errors.Is(err, layerErr.ErrNodeNotFound) { return nil, io.EOF } return nil, fmt.Errorf("main stream next: %w", err) @@ -1104,7 +1104,7 @@ func (c *Tree) InitVersionsByPrefixStream(ctx context.Context, bktInfo *data.Buc func (c *Tree) getSubTreeByPrefixMainStream(ctx context.Context, bktInfo *data.BucketInfo, treeID, prefix string) (SubTreeStream, string, []uint64, error) { rootID, tailPrefix, err := c.determinePrefixNode(ctx, bktInfo, treeID, prefix) if err != nil { - if errors.Is(err, layer.ErrNodeNotFound) { + if errors.Is(err, layerErr.ErrNodeNotFound) { return nil, "", nil, io.EOF } return nil, "", nil, err @@ -1112,7 +1112,7 @@ func (c *Tree) getSubTreeByPrefixMainStream(ctx context.Context, bktInfo *data.B subTree, err := c.service.GetSubTreeStream(ctx, bktInfo, treeID, rootID, 2) if err != nil { - if errors.Is(err, layer.ErrNodeNotFound) { + if errors.Is(err, layerErr.ErrNodeNotFound) { return nil, "", nil, io.EOF } return nil, "", nil, err @@ -1158,7 +1158,7 @@ func (c *Tree) getPrefixNodeID(ctx context.Context, bktInfo *data.BucketInfo, tr } if len(intermediateNodes) == 0 { - return nil, layer.ErrNodeNotFound + return nil, layerErr.ErrNodeNotFound } return intermediateNodes, nil @@ -1167,7 +1167,7 @@ func (c *Tree) getPrefixNodeID(ctx context.Context, bktInfo *data.BucketInfo, tr func (c *Tree) getSubTreeByPrefix(ctx context.Context, bktInfo *data.BucketInfo, treeID, prefix string, latestOnly bool) ([]NodeResponse, string, error) { rootID, tailPrefix, err := c.determinePrefixNode(ctx, bktInfo, treeID, prefix) if err != nil { - if errors.Is(err, layer.ErrNodeNotFound) { + if errors.Is(err, layerErr.ErrNodeNotFound) { return nil, "", nil } return nil, "", err @@ -1175,7 +1175,7 @@ func (c *Tree) getSubTreeByPrefix(ctx context.Context, bktInfo *data.BucketInfo, subTree, err := c.service.GetSubTree(ctx, bktInfo, treeID, rootID, 2, false) if err != nil { - if errors.Is(err, layer.ErrNodeNotFound) { + if errors.Is(err, layerErr.ErrNodeNotFound) { return nil, "", nil } return nil, "", err @@ -1281,7 +1281,7 @@ func (c *Tree) getUnversioned(ctx context.Context, bktInfo *data.BucketInfo, tre } if len(nodes) == 0 { - return nil, layer.ErrNodeNotFound + return nil, layerErr.ErrNodeNotFound } if len(nodes) > 1 { @@ -1420,7 +1420,7 @@ func (c *Tree) GetMultipartUpload(ctx context.Context, bktInfo *data.BucketInfo, } } - return nil, layer.ErrNodeNotFound + return nil, layerErr.ErrNodeNotFound } func (c *Tree) AddPart(ctx context.Context, bktInfo *data.BucketInfo, multipartNodeID uint64, info *data.PartInfo) (oldObjIDsToDelete []oid.ID, err error) { @@ -1498,7 +1498,7 @@ func (c *Tree) AddPart(ctx context.Context, bktInfo *data.BucketInfo, multipartN return nil, err } - return nil, layer.ErrNoNodeToRemove + return nil, layerErr.ErrNoNodeToRemove } func (c *Tree) GetParts(ctx context.Context, bktInfo *data.BucketInfo, multipartNodeID uint64) ([]*data.PartInfoExtended, error) { @@ -1535,7 +1535,7 @@ func (c *Tree) GetParts(ctx context.Context, bktInfo *data.BucketInfo, multipart func (c *Tree) PutBucketLifecycleConfiguration(ctx context.Context, bktInfo *data.BucketInfo, addr oid.Address) ([]oid.Address, error) { multiNode, err := c.getSystemNode(ctx, bktInfo, bucketLifecycleFilename) - isErrNotFound := errors.Is(err, layer.ErrNodeNotFound) + isErrNotFound := errors.Is(err, layerErr.ErrNodeNotFound) if err != nil && !isErrNotFound { return nil, fmt.Errorf("couldn't get node: %w", err) } @@ -1549,7 +1549,7 @@ func (c *Tree) PutBucketLifecycleConfiguration(ctx context.Context, bktInfo *dat if _, err = c.service.AddNode(ctx, bktInfo, systemTree, 0, meta); err != nil { return nil, err } - return nil, layer.ErrNoNodeToRemove + return nil, layerErr.ErrNoNodeToRemove } latest := multiNode.Latest() @@ -1584,13 +1584,13 @@ func (c *Tree) GetBucketLifecycleConfiguration(ctx context.Context, bktInfo *dat func (c *Tree) DeleteBucketLifecycleConfiguration(ctx context.Context, bktInfo *data.BucketInfo) ([]oid.Address, error) { multiNode, err := c.getSystemNode(ctx, bktInfo, bucketLifecycleFilename) - isErrNotFound := errors.Is(err, layer.ErrNodeNotFound) + isErrNotFound := errors.Is(err, layerErr.ErrNodeNotFound) if err != nil && !isErrNotFound { return nil, err } if isErrNotFound { - return nil, layer.ErrNoNodeToRemove + return nil, layerErr.ErrNoNodeToRemove } objToDelete := c.cleanOldNodes(ctx, multiNode.nodes, bktInfo) @@ -1727,7 +1727,7 @@ func (c *Tree) addVersion(ctx context.Context, bktInfo *data.BucketInfo, treeID return node.ID, c.clearOutdatedVersionInfo(ctx, bktInfo, treeID, node.ID) } - if !errors.Is(err, layer.ErrNodeNotFound) { + if !errors.Is(err, layerErr.ErrNodeNotFound) { return 0, err } } @@ -1760,7 +1760,7 @@ func (c *Tree) getVersions(ctx context.Context, bktInfo *data.BucketInfo, treeID } nodes, err := c.service.GetNodes(ctx, p) if err != nil { - if errors.Is(err, layer.ErrNodeNotFound) { + if errors.Is(err, layerErr.ErrNodeNotFound) { return nil, nil } return nil, err @@ -1827,7 +1827,7 @@ func (c *Tree) getSystemNode(ctx context.Context, bktInfo *data.BucketInfo, name nodes = filterMultipartNodes(nodes) if len(nodes) == 0 { - return nil, layer.ErrNodeNotFound + return nil, layerErr.ErrNodeNotFound } if len(nodes) != 1 { c.reqLogger(ctx).Warn(logs.FoundSeveralSystemNodes, zap.String("name", name)) diff --git a/pkg/service/tree/tree_client_in_memory.go b/pkg/service/tree/tree_client_in_memory.go index 4c27fd7..a72ba5d 100644 --- a/pkg/service/tree/tree_client_in_memory.go +++ b/pkg/service/tree/tree_client_in_memory.go @@ -2,13 +2,14 @@ package tree import ( "context" - "errors" + stdErr "errors" "fmt" "io" "sort" "time" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" + "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/errors" "golang.org/x/exp/slices" ) @@ -242,16 +243,16 @@ func (c *ServiceClientMemory) GetSubTree(_ context.Context, bktInfo *data.Bucket tr, ok := cnr.trees[treeID] if !ok { - return nil, ErrNodeNotFound + return nil, errors.ErrNodeNotFound } if len(rootID) != 1 { - return nil, errors.New("invalid rootID") + return nil, stdErr.New("invalid rootID") } node := tr.treeData.getNode(rootID[0]) if node == nil { - return nil, ErrNodeNotFound + return nil, errors.ErrNodeNotFound } if sort { @@ -282,21 +283,21 @@ func (s *SubTreeStreamMemoryImpl) Next() (NodeResponse, error) { func (c *ServiceClientMemory) GetSubTreeStream(_ context.Context, bktInfo *data.BucketInfo, treeID string, rootID []uint64, depth uint32) (SubTreeStream, error) { cnr, ok := c.containers[bktInfo.CID.EncodeToString()] if !ok { - return &SubTreeStreamMemoryImpl{err: ErrNodeNotFound}, nil + return &SubTreeStreamMemoryImpl{err: errors.ErrNodeNotFound}, nil } tr, ok := cnr.trees[treeID] if !ok { - return nil, ErrNodeNotFound + return nil, errors.ErrNodeNotFound } if len(rootID) != 1 { - return nil, errors.New("invalid rootID") + return nil, stdErr.New("invalid rootID") } node := tr.treeData.getNode(rootID[0]) if node == nil { - return nil, ErrNodeNotFound + return nil, errors.ErrNodeNotFound } sortNode(tr.treeData) @@ -353,7 +354,7 @@ func (c *ServiceClientMemory) AddNodeBase(_ context.Context, bktInfo *data.Bucke parentNode := tr.treeData.getNode(parent) if parentNode == nil { - return 0, ErrNodeNotFound + return 0, errors.ErrNodeNotFound } newID := tr.idCounter @@ -418,22 +419,22 @@ func (c *ServiceClientMemory) AddNodeByPath(_ context.Context, bktInfo *data.Buc func (c *ServiceClientMemory) MoveNode(_ context.Context, bktInfo *data.BucketInfo, treeID string, nodeID, parentID uint64, meta map[string]string) error { cnr, ok := c.containers[bktInfo.CID.EncodeToString()] if !ok { - return ErrNodeNotFound + return errors.ErrNodeNotFound } tr, ok := cnr.trees[treeID] if !ok { - return ErrNodeNotFound + return errors.ErrNodeNotFound } node := tr.treeData.getNode(nodeID) if node == nil { - return ErrNodeNotFound + return errors.ErrNodeNotFound } newParent := tr.treeData.getNode(parentID) if newParent == nil { - return ErrNodeNotFound + return errors.ErrNodeNotFound } node.data.meta = metaToNodeMeta(meta) @@ -466,17 +467,17 @@ func sortNodes(list []*treeNodeMemory) { func (c *ServiceClientMemory) RemoveNode(_ context.Context, bktInfo *data.BucketInfo, treeID string, nodeID uint64) error { cnr, ok := c.containers[bktInfo.CID.EncodeToString()] if !ok { - return ErrNodeNotFound + return errors.ErrNodeNotFound } tr, ok := cnr.trees[treeID] if !ok { - return ErrNodeNotFound + return errors.ErrNodeNotFound } node := tr.treeData.getNode(nodeID) if node == nil { - return ErrNodeNotFound + return errors.ErrNodeNotFound } node.parent.removeChild(nodeID)