[#488] Add transformation to S3 error in policy check
Some checks failed
/ Builds (pull_request) Successful in 2m29s
/ Lint (pull_request) Successful in 4m42s
/ DCO (pull_request) Successful in 6m10s
/ Vulncheck (pull_request) Successful in 6m40s
/ Tests (pull_request) Failing after 11m57s

Moved layer public errors to api/layer/errors to avoid circular dependencies
Made transformToS3Error public and move to `api/errors` package

Signed-off-by: Nikita Zinkevich <n.zinkevich@yadro.com>
This commit is contained in:
Nikita Zinkevich 2024-09-11 12:04:49 +03:00
parent d0e4d55772
commit 41dc579744
23 changed files with 179 additions and 182 deletions

View file

@ -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

View file

@ -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)
}

View file

@ -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,

View file

@ -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

View file

@ -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)
}
}
}

View file

@ -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")
)

View file

@ -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.

View file

@ -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())

View file

@ -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)
}
}

View file

@ -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
}

View file

@ -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

View file

@ -8,7 +8,7 @@ import (
"encoding/base64"
"encoding/hex"
"encoding/json"
"errors"
stdErrors "errors"
"fmt"
"io"
"mime"
@ -21,6 +21,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-s3-gw/pkg/detector"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
@ -382,7 +383,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
@ -418,7 +419,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

View file

@ -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}

View file

@ -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())
}

View file

@ -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)

View file

@ -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")
)

View file

@ -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]
}

View file

@ -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))
}

View file

@ -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.",

View file

@ -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)

View file

@ -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)
}

View file

@ -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))

View file

@ -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)