[#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 package errors
import ( import (
"errors"
"fmt" "fmt"
"net/http" "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 ( type (
@ -1765,7 +1767,7 @@ var errorCodes = errorCodeMap{
// IsS3Error checks if the provided error is a specific s3 error. // IsS3Error checks if the provided error is a specific s3 error.
func IsS3Error(err error, code ErrorCode) bool { func IsS3Error(err error, code ErrorCode) bool {
err = frosterrors.UnwrapErr(err) err = frostErr.UnwrapErr(err)
e, ok := err.(Error) e, ok := err.(Error)
return ok && e.ErrCode == code return ok && e.ErrCode == code
} }
@ -1802,6 +1804,26 @@ func GetAPIErrorWithError(code ErrorCode, err error) Error {
return errorCodes.toAPIErrWithErr(code, err) 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. // ObjectError -- error that is linked to a specific object.
type ObjectError struct { type ObjectError struct {
Err error Err error

View file

@ -13,7 +13,6 @@ import (
s3errors "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" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware" "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" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
"go.opentelemetry.io/otel/trace" "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) { func (h *handler) logAndSendError(w http.ResponseWriter, logText string, reqInfo *middleware.ReqInfo, err error, additional ...zap.Field) {
err = handleDeleteMarker(w, err) 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)) additional = append(additional, zap.NamedError("write_response_error", wrErr))
} else { } else {
additional = append(additional, zap.Int("status", code)) 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) 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) { func (h *handler) ResolveBucket(ctx context.Context, bucket string) (*data.BucketInfo, error) {
return h.obj.GetBucketInfo(ctx, bucket) return h.obj.GetBucketInfo(ctx, bucket)
} }

View file

@ -1,12 +1,12 @@
package handler package handler
import ( import (
"errors" stdErrors "errors"
"fmt" "fmt"
"testing" "testing"
s3errors "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" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/errors"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -18,27 +18,27 @@ func TestTransformS3Errors(t *testing.T) {
}{ }{
{ {
name: "simple std error to internal error", name: "simple std error to internal error",
err: errors.New("some error"), err: stdErrors.New("some error"),
expected: s3errors.ErrInternalError, expected: s3errors.ErrInternalError,
}, },
{ {
name: "layer access denied error to s3 access denied error", name: "layer access denied error to s3 access denied error",
err: layer.ErrAccessDenied, err: errors.ErrAccessDenied,
expected: s3errors.ErrAccessDenied, expected: s3errors.ErrAccessDenied,
}, },
{ {
name: "wrapped layer access denied error to s3 access denied error", 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, expected: s3errors.ErrAccessDenied,
}, },
{ {
name: "layer node access denied error to s3 access denied error", name: "layer node access denied error to s3 access denied error",
err: layer.ErrNodeAccessDenied, err: errors.ErrNodeAccessDenied,
expected: s3errors.ErrAccessDenied, expected: s3errors.ErrAccessDenied,
}, },
{ {
name: "layer gateway timeout error to s3 gateway timeout error", name: "layer gateway timeout error to s3 gateway timeout error",
err: layer.ErrGatewayTimeout, err: errors.ErrGatewayTimeout,
expected: s3errors.ErrGatewayTimeout, expected: s3errors.ErrGatewayTimeout,
}, },
{ {
@ -53,7 +53,7 @@ func TestTransformS3Errors(t *testing.T) {
}, },
} { } {
t.Run(tc.name, func(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) s3err, ok := err.(s3errors.Error)
require.True(t, ok, "error must be s3 error") require.True(t, ok, "error must be s3 error")
require.Equalf(t, tc.expected, s3err.ErrCode, require.Equalf(t, tc.expected, s3err.ErrCode,

View file

@ -7,6 +7,7 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
s3errors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" 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) { 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) tags, lockInfo, err = n.treeService.GetObjectTaggingAndLock(ctx, objVersion.BktInfo, nodeVersion)
if err != nil { 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{}, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error())
} }
return nil, data.LockInfo{}, err return nil, data.LockInfo{}, err

View file

@ -3,12 +3,13 @@ package layer
import ( import (
"bytes" "bytes"
"context" "context"
errorsStd "errors" stdErrors "errors"
"fmt" "fmt"
"io" "io"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" "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" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/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 { if cors.CORSRules == nil {
return errors.GetAPIError(errors.ErrMalformedXML) return apiErrors.GetAPIError(apiErrors.ErrMalformedXML)
} }
if err := checkCORS(cors); err != nil { 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)) 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 { if err != nil && !objToDeleteNotFound {
return err 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 { func (n *Layer) DeleteBucketCORS(ctx context.Context, bktInfo *data.BucketInfo) error {
objs, err := n.treeService.DeleteBucketCORS(ctx, bktInfo) objs, err := n.treeService.DeleteBucketCORS(ctx, bktInfo)
objNotFound := errorsStd.Is(err, ErrNoNodeToRemove) objNotFound := stdErrors.Is(err, errors.ErrNoNodeToRemove)
if err != nil && !objNotFound { if err != nil && !objNotFound {
return err return err
} }
@ -124,12 +125,12 @@ func checkCORS(cors *data.CORSConfiguration) error {
for _, r := range cors.CORSRules { for _, r := range cors.CORSRules {
for _, m := range r.AllowedMethods { for _, m := range r.AllowedMethods {
if _, ok := supportedMethods[m]; !ok { 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 { for _, h := range r.ExposeHeaders {
if h == wildcard { 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 ( import (
"context" "context"
"crypto/ecdsa" "crypto/ecdsa"
"errors"
"io" "io"
"time" "time"
@ -221,14 +220,6 @@ type PrmObjectPatch struct {
ObjectSize uint64 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. // FrostFS represents virtual connection to FrostFS network.
type FrostFS interface { type FrostFS interface {
// CreateContainer creates and saves parameterized container in FrostFS. // 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" v2container "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
objectv2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" 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-s3-gw/api/middleware"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" "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 { if obj, ok := t.objects[sAddr]; ok {
owner := getBearerOwner(ctx) owner := getBearerOwner(ctx)
if !t.checkAccess(cnrID, owner) { if !t.checkAccess(cnrID, owner) {
return nil, ErrAccessDenied return nil, errors.ErrAccessDenied
} }
return obj, nil return obj, nil
@ -345,7 +346,7 @@ func (t *TestFrostFS) DeleteObject(ctx context.Context, prm PrmObjectDelete) err
if _, ok := t.objects[addr.EncodeToString()]; ok { if _, ok := t.objects[addr.EncodeToString()]; ok {
owner := getBearerOwner(ctx) owner := getBearerOwner(ctx)
if !t.checkAccess(prm.Container, owner) { if !t.checkAccess(prm.Container, owner) {
return ErrAccessDenied return errors.ErrAccessDenied
} }
delete(t.objects, addr.EncodeToString()) 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"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" "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" 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/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/api/middleware"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" "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) containerID, err := n.ResolveBucket(ctx, zone, name)
if err != nil { if err != nil {
if strings.Contains(err.Error(), "not found") { 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 return nil, err
} }
@ -397,9 +397,9 @@ func (n *Layer) GetObject(ctx context.Context, p *GetObjectParams) (*ObjectPaylo
if err != nil { if err != nil {
if client.IsErrObjectNotFound(err) { if client.IsErrObjectNotFound(err) {
if p.Versioned { 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 { } 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 { func isNotFoundError(err error) bool {
return errors.IsS3Error(err, errors.ErrNoSuchKey) || return s3errors.IsS3Error(err, s3errors.ErrNoSuchKey) ||
errors.IsS3Error(err, errors.ErrNoSuchVersion) s3errors.IsS3Error(err, s3errors.ErrNoSuchVersion)
} }
func (n *Layer) getNodeVersionsToDelete(ctx context.Context, bkt *data.BucketInfo, obj *VersionedObject) ([]*data.NodeVersion, error) { func (n *Layer) getNodeVersionsToDelete(ctx context.Context, bkt *data.BucketInfo, obj *VersionedObject) ([]*data.NodeVersion, error) {
var versionsToDelete []*data.NodeVersion var versionsToDelete []*data.NodeVersion
versions, err := n.treeService.GetVersions(ctx, bkt, obj.Name) versions, err := n.treeService.GetVersions(ctx, bkt, obj.Name)
if err != nil { 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, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error())
} }
return nil, err 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) { func (n *Layer) CreateBucket(ctx context.Context, p *CreateBucketParams) (*data.BucketInfo, error) {
bktInfo, err := n.GetBucketInfo(ctx, p.Name) bktInfo, err := n.GetBucketInfo(ctx, p.Name)
if err != nil { if err != nil {
if errors.IsS3Error(err, errors.ErrNoSuchBucket) { if s3errors.IsS3Error(err, s3errors.ErrNoSuchBucket) {
return n.createContainer(ctx, p) return n.createContainer(ctx, p)
} }
return nil, err return nil, err
} }
if p.SessionContainerCreation != nil && session.IssuedBy(*p.SessionContainerCreation, bktInfo.Owner) { 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) { 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 return err
} }
if len(res) != 0 { if len(res) != 0 {
return errors.GetAPIError(errors.ErrBucketNotEmpty) return s3errors.GetAPIError(s3errors.ErrBucketNotEmpty)
} }
} }

View file

@ -5,12 +5,13 @@ import (
"context" "context"
"encoding/base64" "encoding/base64"
"encoding/xml" "encoding/xml"
"errors" stderrors "errors"
"fmt" "fmt"
"io" "io"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
apiErr "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" 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" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
"go.uber.org/zap" "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)) 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 { if err != nil && !objsToDeleteNotFound {
return err return err
} }
@ -98,7 +99,7 @@ func (n *Layer) GetBucketLifecycleConfiguration(ctx context.Context, bktInfo *da
} }
addr, err := n.treeService.GetBucketLifecycleConfiguration(ctx, bktInfo) addr, err := n.treeService.GetBucketLifecycleConfiguration(ctx, bktInfo)
objNotFound := errors.Is(err, ErrNodeNotFound) objNotFound := stderrors.Is(err, errors.ErrNodeNotFound)
if err != nil && !objNotFound { if err != nil && !objNotFound {
return nil, err 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 { func (n *Layer) DeleteBucketLifecycleConfiguration(ctx context.Context, bktInfo *data.BucketInfo) error {
objs, err := n.treeService.DeleteBucketLifecycleConfiguration(ctx, bktInfo) objs, err := n.treeService.DeleteBucketLifecycleConfiguration(ctx, bktInfo)
objsNotFound := errors.Is(err, ErrNoNodeToRemove) objsNotFound := stderrors.Is(err, errors.ErrNoNodeToRemove)
if err != nil && !objsNotFound { if err != nil && !objsNotFound {
return err return err
} }

View file

@ -7,7 +7,7 @@ import (
"encoding/base64" "encoding/base64"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"errors" stdErrors "errors"
"fmt" "fmt"
"io" "io"
"sort" "sort"
@ -19,6 +19,7 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
s3errors "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/encryption"
"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/internal/logs"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "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) { 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) multipartInfo, err := n.treeService.GetMultipartUpload(ctx, p.Info.Bkt, p.Info.Key, p.Info.UploadID)
if err != nil { 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 "", fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchUpload), err.Error())
} }
return "", err 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) 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 { if err != nil && !oldPartIDNotFound {
return nil, err 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) { 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) multipartInfo, err := n.treeService.GetMultipartUpload(ctx, p.Info.Bkt, p.Info.Key, p.Info.UploadID)
if err != nil { 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, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchUpload), err.Error())
} }
return nil, err 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) { 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) multipartInfo, err := n.treeService.GetMultipartUpload(ctx, p.Bkt, p.Key, p.UploadID)
if err != nil { 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, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchUpload), err.Error())
} }
return nil, nil, err return nil, nil, err

View file

@ -8,7 +8,7 @@ import (
"encoding/base64" "encoding/base64"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"errors" stdErrors "errors"
"fmt" "fmt"
"io" "io"
"mime" "mime"
@ -21,6 +21,7 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
apiErrors "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" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/pkg/detector" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/pkg/detector"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "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) node, err := n.treeService.GetLatestVersion(ctx, bkt, objectName)
if err != nil { 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, fmt.Errorf("%w: %s", apiErrors.GetAPIError(apiErrors.ErrNoSuchKey), err.Error())
} }
return nil, err return nil, err
@ -418,7 +419,7 @@ func (n *Layer) headVersion(ctx context.Context, bkt *data.BucketInfo, p *HeadOb
if p.VersionID == data.UnversionedObjectVersionID { if p.VersionID == data.UnversionedObjectVersionID {
foundVersion, err = n.treeService.GetUnversioned(ctx, bkt, p.Object) foundVersion, err = n.treeService.GetUnversioned(ctx, bkt, p.Object)
if err != nil { 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, fmt.Errorf("%w: %s", apiErrors.GetAPIError(apiErrors.ErrNoSuchVersion), err.Error())
} }
return nil, err return nil, err

View file

@ -3,7 +3,7 @@ package layer
import ( import (
"context" "context"
"encoding/xml" "encoding/xml"
errorsStd "errors" stdErrors "errors"
"fmt" "fmt"
"math" "math"
"strconv" "strconv"
@ -11,7 +11,8 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "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/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" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/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) 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 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) 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 return nil, err
} }
if lockInfo == nil { 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) addr, err := n.treeService.GetBucketCORS(ctx, bkt)
objNotFound := errorsStd.Is(err, ErrNodeNotFound) objNotFound := stdErrors.Is(err, errors.ErrNodeNotFound)
if err != nil && !objNotFound { if err != nil && !objNotFound {
return nil, err return nil, err
} }
if objNotFound { 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 var prmAuth PrmAuth
@ -209,7 +210,7 @@ func (n *Layer) GetBucketSettings(ctx context.Context, bktInfo *data.BucketInfo)
settings, err := n.treeService.GetSettingsNode(ctx, bktInfo) settings, err := n.treeService.GetSettingsNode(ctx, bktInfo)
if err != nil { if err != nil {
if !errorsStd.Is(err, ErrNodeNotFound) { if !stdErrors.Is(err, errors.ErrNodeNotFound) {
return nil, err return nil, err
} }
settings = &data.BucketSettings{Versioning: data.VersioningUnversioned} settings = &data.BucketSettings{Versioning: data.VersioningUnversioned}

View file

@ -2,11 +2,12 @@ package layer
import ( import (
"context" "context"
"errors" stdErrors "errors"
"fmt" "fmt"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
s3errors "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/errors"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/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) tags, err := n.treeService.GetObjectTagging(ctx, p.ObjectVersion.BktInfo, nodeVersion)
if err != nil { 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, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error())
} }
return "", nil, err 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) err = n.treeService.PutObjectTagging(ctx, p.ObjectVersion.BktInfo, nodeVersion, p.TagSet)
if err != nil { 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 fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error())
} }
return err return err
@ -81,7 +82,7 @@ func (n *Layer) DeleteObjectTagging(ctx context.Context, p *data.ObjectVersion)
err = n.treeService.DeleteObjectTagging(ctx, p.BktInfo, version) err = n.treeService.DeleteObjectTagging(ctx, p.BktInfo, version)
if err != nil { 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 fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error())
} }
return err return err
@ -102,7 +103,7 @@ func (n *Layer) GetBucketTagging(ctx context.Context, bktInfo *data.BucketInfo)
} }
tags, err := n.treeService.GetBucketTagging(ctx, bktInfo) 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 return nil, err
} }
@ -161,7 +162,7 @@ func (n *Layer) getNodeVersion(ctx context.Context, objVersion *data.ObjectVersi
if err == nil && version.IsDeleteMarker && !objVersion.NoErrorOnDeleteMarker { if err == nil && version.IsDeleteMarker && !objVersion.NoErrorOnDeleteMarker {
return nil, fmt.Errorf("%w: found version is delete marker", s3errors.GetAPIError(s3errors.ErrNoSuchKey)) 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()) return nil, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error())
} }

View file

@ -9,6 +9,7 @@ import (
"time" "time"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" "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" 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) { func (t *TreeServiceMock) GetSettingsNode(_ context.Context, bktInfo *data.BucketInfo) (*data.BucketSettings, error) {
settings, ok := t.settings[bktInfo.CID.EncodeToString()] settings, ok := t.settings[bktInfo.CID.EncodeToString()]
if !ok { if !ok {
return nil, ErrNodeNotFound return nil, errors.ErrNodeNotFound
} }
return settings, nil return settings, nil
@ -140,7 +141,7 @@ func (t *TreeServiceMock) PutBucketCORS(_ context.Context, bktInfo *data.BucketI
t.system[bktInfo.CID.EncodeToString()] = systemMap t.system[bktInfo.CID.EncodeToString()] = systemMap
return nil, ErrNoNodeToRemove return nil, errors.ErrNoNodeToRemove
} }
func (t *TreeServiceMock) DeleteBucketCORS(context.Context, *data.BucketInfo) ([]oid.Address, error) { 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) { func (t *TreeServiceMock) GetVersions(_ context.Context, bktInfo *data.BucketInfo, objectName string) ([]*data.NodeVersion, error) {
cnrVersionsMap, ok := t.versions[bktInfo.CID.EncodeToString()] cnrVersionsMap, ok := t.versions[bktInfo.CID.EncodeToString()]
if !ok { if !ok {
return nil, ErrNodeNotFound return nil, errors.ErrNodeNotFound
} }
versions, ok := cnrVersionsMap[objectName] versions, ok := cnrVersionsMap[objectName]
if !ok { if !ok {
return nil, ErrNodeNotFound return nil, errors.ErrNodeNotFound
} }
return versions, nil 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) { func (t *TreeServiceMock) GetLatestVersion(_ context.Context, bktInfo *data.BucketInfo, objectName string) (*data.NodeVersion, error) {
cnrVersionsMap, ok := t.versions[bktInfo.CID.EncodeToString()] cnrVersionsMap, ok := t.versions[bktInfo.CID.EncodeToString()]
if !ok { if !ok {
return nil, ErrNodeNotFound return nil, errors.ErrNodeNotFound
} }
versions, ok := cnrVersionsMap[objectName] versions, ok := cnrVersionsMap[objectName]
if !ok { if !ok {
return nil, ErrNodeNotFound return nil, errors.ErrNodeNotFound
} }
sort.Slice(versions, func(i, j int) bool { 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 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) { func (t *TreeServiceMock) InitVersionsByPrefixStream(_ context.Context, bktInfo *data.BucketInfo, prefix string, latestOnly bool) (data.VersionsStream, error) {
cnrVersionsMap, ok := t.versions[bktInfo.CID.EncodeToString()] cnrVersionsMap, ok := t.versions[bktInfo.CID.EncodeToString()]
if !ok { if !ok {
return nil, ErrNodeNotFound return nil, errors.ErrNodeNotFound
} }
var result []*data.NodeVersion 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) { func (t *TreeServiceMock) GetUnversioned(_ context.Context, bktInfo *data.BucketInfo, objectName string) (*data.NodeVersion, error) {
cnrVersionsMap, ok := t.versions[bktInfo.CID.EncodeToString()] cnrVersionsMap, ok := t.versions[bktInfo.CID.EncodeToString()]
if !ok { if !ok {
return nil, ErrNodeNotFound return nil, errors.ErrNodeNotFound
} }
versions, ok := cnrVersionsMap[objectName] versions, ok := cnrVersionsMap[objectName]
if !ok { if !ok {
return nil, ErrNodeNotFound return nil, errors.ErrNodeNotFound
} }
for _, version := range versions { 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) { 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 { func (t *TreeServiceMock) RemoveVersion(_ context.Context, bktInfo *data.BucketInfo, nodeID uint64) error {
cnrVersionsMap, ok := t.versions[bktInfo.CID.EncodeToString()] cnrVersionsMap, ok := t.versions[bktInfo.CID.EncodeToString()]
if !ok { if !ok {
return ErrNodeNotFound return errors.ErrNodeNotFound
} }
for key, versions := range cnrVersionsMap { 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) { 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) { func (t *TreeServiceMock) GetMultipartUpload(_ context.Context, bktInfo *data.BucketInfo, objectName, uploadID string) (*data.MultipartInfo, error) {
cnrMultipartsMap, ok := t.multiparts[bktInfo.CID.EncodeToString()] cnrMultipartsMap, ok := t.multiparts[bktInfo.CID.EncodeToString()]
if !ok { if !ok {
return nil, ErrNodeNotFound return nil, errors.ErrNodeNotFound
} }
multiparts := cnrMultipartsMap[objectName] 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) { 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 { if foundMultipart == nil {
return nil, ErrNodeNotFound return nil, errors.ErrNodeNotFound
} }
partsMap := t.parts[foundMultipart.UploadID] partsMap := t.parts[foundMultipart.UploadID]
@ -411,18 +412,18 @@ func (t *TreeServiceMock) PutBucketLifecycleConfiguration(_ context.Context, bkt
t.system[bktInfo.CID.EncodeToString()] = systemMap 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) { func (t *TreeServiceMock) GetBucketLifecycleConfiguration(_ context.Context, bktInfo *data.BucketInfo) (oid.Address, error) {
systemMap, ok := t.system[bktInfo.CID.EncodeToString()] systemMap, ok := t.system[bktInfo.CID.EncodeToString()]
if !ok { if !ok {
return oid.Address{}, ErrNodeNotFound return oid.Address{}, errors.ErrNodeNotFound
} }
node, ok := systemMap["lifecycle"] node, ok := systemMap["lifecycle"]
if !ok { if !ok {
return oid.Address{}, ErrNodeNotFound return oid.Address{}, errors.ErrNodeNotFound
} }
return newAddress(bktInfo.CID, node.OID), nil 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) { func (t *TreeServiceMock) DeleteBucketLifecycleConfiguration(_ context.Context, bktInfo *data.BucketInfo) ([]oid.Address, error) {
systemMap, ok := t.system[bktInfo.CID.EncodeToString()] systemMap, ok := t.system[bktInfo.CID.EncodeToString()]
if !ok { if !ok {
return nil, ErrNoNodeToRemove return nil, errors.ErrNoNodeToRemove
} }
node, ok := systemMap["lifecycle"] node, ok := systemMap["lifecycle"]
if !ok { if !ok {
return nil, ErrNoNodeToRemove return nil, errors.ErrNoNodeToRemove
} }
delete(systemMap, "lifecycle") delete(systemMap, "lifecycle")
@ -461,7 +462,7 @@ LOOP:
} }
if uploadID == "" { if uploadID == "" {
return ErrNodeNotFound return errors.ErrNodeNotFound
} }
delete(t.parts, uploadID) delete(t.parts, uploadID)

View file

@ -2,7 +2,6 @@ package layer
import ( import (
"context" "context"
"errors"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" 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 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) 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 ( import (
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"os"
"strconv" "strconv"
"strings"
"time" "time"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
@ -13,9 +11,6 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "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 { func userHeaders(attrs []object.Attribute) map[string]string {
result := make(map[string]string, len(attrs)) result := make(map[string]string, len(attrs))
@ -111,9 +106,3 @@ func filepathFromObject(o *object.Object) string {
objID, _ := o.ID() objID, _ := o.ID()
return objID.EncodeToString() 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" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
apiErr "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" 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/frostfs-s3-gw/internal/logs"
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
@ -85,7 +84,7 @@ func PolicyCheck(cfg PolicyConfig) Func {
ctx := r.Context() ctx := r.Context()
if err := policyCheck(r, cfg); err != nil { if err := policyCheck(r, cfg); err != nil {
reqLogOrDefault(ctx, cfg.Log).Error(logs.PolicyValidationFailed, zap.Error(err)) 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 { if _, wrErr := WriteErrorResponse(w, GetReqInfo(ctx), err); wrErr != nil {
reqLogOrDefault(ctx, cfg.Log).Error(logs.FailedToWriteResponse, zap.Error(wrErr)) reqLogOrDefault(ctx, cfg.Log).Error(logs.FailedToWriteResponse, zap.Error(wrErr))
} }

View file

@ -62,7 +62,7 @@ const (
hdrSSE = "X-Amz-Server-Side-Encryption" hdrSSE = "X-Amz-Server-Side-Encryption"
// hdrSSECustomerKey is the HTTP header key referencing the // hdrSSECustomerKey is the HTTP header key referencing the
// SSE-C client-provided key.. // SSE-C client-provided key.
hdrSSECustomerKey = hdrSSE + "-Customer-Key" hdrSSECustomerKey = hdrSSE + "-Customer-Key"
// hdrSSECopyKey is the HTTP header key referencing the SSE-C // hdrSSECopyKey is the HTTP header key referencing the SSE-C
@ -74,7 +74,7 @@ var (
xmlHeader = []byte(xml.Header) 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 // http://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
var s3ErrorResponseMap = map[string]string{ var s3ErrorResponseMap = map[string]string{
"AccessDenied": "Access Denied.", "AccessDenied": "Access Denied.",

View file

@ -11,6 +11,7 @@ import (
objectv2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" objectv2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer" "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" 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/client"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" "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 { 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) { 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) return fmt.Errorf("%s: %w", msg, err)

View file

@ -7,7 +7,7 @@ import (
"testing" "testing"
"time" "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" errorsFrost "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/errors"
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -23,10 +23,10 @@ func TestErrorChecking(t *testing.T) {
var wrappedError error var wrappedError error
if fetchedReason, ok := errorsFrost.IsErrObjectAccessDenied(err); ok { 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) require.Contains(t, wrappedError.Error(), reason)
} }

View file

@ -12,7 +12,7 @@ import (
"time" "time"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" "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/api/middleware"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
@ -75,13 +75,13 @@ const (
var ( var (
// ErrNodeNotFound is returned from ServiceClient in case of not found error. // 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 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 is returned from ServiceClient service in case of timeout error.
ErrGatewayTimeout = layer.ErrGatewayTimeout ErrGatewayTimeout = layerErr.ErrGatewayTimeout
errNodeDoesntContainFileName = fmt.Errorf("node doesn't contain FileName") 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 { func (c *Tree) PutSettingsNode(ctx context.Context, bktInfo *data.BucketInfo, settings *data.BucketSettings) error {
multiNode, err := c.getSystemNode(ctx, bktInfo, settingsFileName) multiNode, err := c.getSystemNode(ctx, bktInfo, settingsFileName)
isErrNotFound := errors.Is(err, layer.ErrNodeNotFound) isErrNotFound := errors.Is(err, layerErr.ErrNodeNotFound)
if err != nil && !isErrNotFound { if err != nil && !isErrNotFound {
return fmt.Errorf("couldn't get node: %w", err) 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) { func (c *Tree) PutBucketCORS(ctx context.Context, bktInfo *data.BucketInfo, addr oid.Address) ([]oid.Address, error) {
multiNode, err := c.getSystemNode(ctx, bktInfo, corsFilename) multiNode, err := c.getSystemNode(ctx, bktInfo, corsFilename)
isErrNotFound := errors.Is(err, layer.ErrNodeNotFound) isErrNotFound := errors.Is(err, layerErr.ErrNodeNotFound)
if err != nil && !isErrNotFound { if err != nil && !isErrNotFound {
return nil, fmt.Errorf("couldn't get node: %w", err) 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 { if _, err = c.service.AddNode(ctx, bktInfo, systemTree, 0, meta); err != nil {
return nil, err return nil, err
} }
return nil, layer.ErrNoNodeToRemove return nil, layerErr.ErrNoNodeToRemove
} }
latest := multiNode.Latest() 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) { func (c *Tree) DeleteBucketCORS(ctx context.Context, bktInfo *data.BucketInfo) ([]oid.Address, error) {
multiNode, err := c.getSystemNode(ctx, bktInfo, corsFilename) multiNode, err := c.getSystemNode(ctx, bktInfo, corsFilename)
isErrNotFound := errors.Is(err, layer.ErrNodeNotFound) isErrNotFound := errors.Is(err, layerErr.ErrNodeNotFound)
if err != nil && !isErrNotFound { if err != nil && !isErrNotFound {
return nil, err return nil, err
} }
if isErrNotFound { if isErrNotFound {
return nil, layer.ErrNoNodeToRemove return nil, layerErr.ErrNoNodeToRemove
} }
objToDelete := c.cleanOldNodes(ctx, multiNode.nodes, bktInfo) 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 { func (c *Tree) PutBucketTagging(ctx context.Context, bktInfo *data.BucketInfo, tagSet map[string]string) error {
multiNode, err := c.getSystemNode(ctx, bktInfo, bucketTaggingFilename) multiNode, err := c.getSystemNode(ctx, bktInfo, bucketTaggingFilename)
isErrNotFound := errors.Is(err, layer.ErrNodeNotFound) isErrNotFound := errors.Is(err, layerErr.ErrNodeNotFound)
if err != nil && !isErrNotFound { if err != nil && !isErrNotFound {
return fmt.Errorf("couldn't get node: %w", err) return fmt.Errorf("couldn't get node: %w", err)
} }
@ -852,7 +852,7 @@ func getLatestVersionNode(nodes []NodeResponse) (NodeResponse, error) {
} }
if targetIndexNode == -1 { if targetIndexNode == -1 {
return nil, layer.ErrNodeNotFound return nil, layerErr.ErrNodeNotFound
} }
return nodes[targetIndexNode], nil return nodes[targetIndexNode], nil
@ -977,7 +977,7 @@ func (s *VersionsByPrefixStreamImpl) getNodeFromMainStream() (NodeResponse, erro
for { for {
node, err := s.mainStream.Next() node, err := s.mainStream.Next()
if err != nil { if err != nil {
if errors.Is(err, ErrNodeNotFound) { if errors.Is(err, layerErr.ErrNodeNotFound) {
return nil, io.EOF return nil, io.EOF
} }
return nil, fmt.Errorf("main stream next: %w", err) 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) { 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) rootID, tailPrefix, err := c.determinePrefixNode(ctx, bktInfo, treeID, prefix)
if err != nil { if err != nil {
if errors.Is(err, layer.ErrNodeNotFound) { if errors.Is(err, layerErr.ErrNodeNotFound) {
return nil, "", nil, io.EOF return nil, "", nil, io.EOF
} }
return nil, "", nil, err 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) subTree, err := c.service.GetSubTreeStream(ctx, bktInfo, treeID, rootID, 2)
if err != nil { if err != nil {
if errors.Is(err, layer.ErrNodeNotFound) { if errors.Is(err, layerErr.ErrNodeNotFound) {
return nil, "", nil, io.EOF return nil, "", nil, io.EOF
} }
return nil, "", nil, err return nil, "", nil, err
@ -1158,7 +1158,7 @@ func (c *Tree) getPrefixNodeID(ctx context.Context, bktInfo *data.BucketInfo, tr
} }
if len(intermediateNodes) == 0 { if len(intermediateNodes) == 0 {
return nil, layer.ErrNodeNotFound return nil, layerErr.ErrNodeNotFound
} }
return intermediateNodes, nil 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) { 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) rootID, tailPrefix, err := c.determinePrefixNode(ctx, bktInfo, treeID, prefix)
if err != nil { if err != nil {
if errors.Is(err, layer.ErrNodeNotFound) { if errors.Is(err, layerErr.ErrNodeNotFound) {
return nil, "", nil return nil, "", nil
} }
return nil, "", err 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) subTree, err := c.service.GetSubTree(ctx, bktInfo, treeID, rootID, 2, false)
if err != nil { if err != nil {
if errors.Is(err, layer.ErrNodeNotFound) { if errors.Is(err, layerErr.ErrNodeNotFound) {
return nil, "", nil return nil, "", nil
} }
return nil, "", err return nil, "", err
@ -1281,7 +1281,7 @@ func (c *Tree) getUnversioned(ctx context.Context, bktInfo *data.BucketInfo, tre
} }
if len(nodes) == 0 { if len(nodes) == 0 {
return nil, layer.ErrNodeNotFound return nil, layerErr.ErrNodeNotFound
} }
if len(nodes) > 1 { 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) { 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, err
} }
return nil, layer.ErrNoNodeToRemove return nil, layerErr.ErrNoNodeToRemove
} }
func (c *Tree) GetParts(ctx context.Context, bktInfo *data.BucketInfo, multipartNodeID uint64) ([]*data.PartInfoExtended, error) { 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) { func (c *Tree) PutBucketLifecycleConfiguration(ctx context.Context, bktInfo *data.BucketInfo, addr oid.Address) ([]oid.Address, error) {
multiNode, err := c.getSystemNode(ctx, bktInfo, bucketLifecycleFilename) multiNode, err := c.getSystemNode(ctx, bktInfo, bucketLifecycleFilename)
isErrNotFound := errors.Is(err, layer.ErrNodeNotFound) isErrNotFound := errors.Is(err, layerErr.ErrNodeNotFound)
if err != nil && !isErrNotFound { if err != nil && !isErrNotFound {
return nil, fmt.Errorf("couldn't get node: %w", err) 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 { if _, err = c.service.AddNode(ctx, bktInfo, systemTree, 0, meta); err != nil {
return nil, err return nil, err
} }
return nil, layer.ErrNoNodeToRemove return nil, layerErr.ErrNoNodeToRemove
} }
latest := multiNode.Latest() 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) { func (c *Tree) DeleteBucketLifecycleConfiguration(ctx context.Context, bktInfo *data.BucketInfo) ([]oid.Address, error) {
multiNode, err := c.getSystemNode(ctx, bktInfo, bucketLifecycleFilename) multiNode, err := c.getSystemNode(ctx, bktInfo, bucketLifecycleFilename)
isErrNotFound := errors.Is(err, layer.ErrNodeNotFound) isErrNotFound := errors.Is(err, layerErr.ErrNodeNotFound)
if err != nil && !isErrNotFound { if err != nil && !isErrNotFound {
return nil, err return nil, err
} }
if isErrNotFound { if isErrNotFound {
return nil, layer.ErrNoNodeToRemove return nil, layerErr.ErrNoNodeToRemove
} }
objToDelete := c.cleanOldNodes(ctx, multiNode.nodes, bktInfo) 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) 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 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) nodes, err := c.service.GetNodes(ctx, p)
if err != nil { if err != nil {
if errors.Is(err, layer.ErrNodeNotFound) { if errors.Is(err, layerErr.ErrNodeNotFound) {
return nil, nil return nil, nil
} }
return nil, err return nil, err
@ -1827,7 +1827,7 @@ func (c *Tree) getSystemNode(ctx context.Context, bktInfo *data.BucketInfo, name
nodes = filterMultipartNodes(nodes) nodes = filterMultipartNodes(nodes)
if len(nodes) == 0 { if len(nodes) == 0 {
return nil, layer.ErrNodeNotFound return nil, layerErr.ErrNodeNotFound
} }
if len(nodes) != 1 { if len(nodes) != 1 {
c.reqLogger(ctx).Warn(logs.FoundSeveralSystemNodes, zap.String("name", name)) c.reqLogger(ctx).Warn(logs.FoundSeveralSystemNodes, zap.String("name", name))

View file

@ -2,13 +2,14 @@ package tree
import ( import (
"context" "context"
"errors" stdErr "errors"
"fmt" "fmt"
"io" "io"
"sort" "sort"
"time" "time"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/errors"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
) )
@ -242,16 +243,16 @@ func (c *ServiceClientMemory) GetSubTree(_ context.Context, bktInfo *data.Bucket
tr, ok := cnr.trees[treeID] tr, ok := cnr.trees[treeID]
if !ok { if !ok {
return nil, ErrNodeNotFound return nil, errors.ErrNodeNotFound
} }
if len(rootID) != 1 { if len(rootID) != 1 {
return nil, errors.New("invalid rootID") return nil, stdErr.New("invalid rootID")
} }
node := tr.treeData.getNode(rootID[0]) node := tr.treeData.getNode(rootID[0])
if node == nil { if node == nil {
return nil, ErrNodeNotFound return nil, errors.ErrNodeNotFound
} }
if sort { 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) { func (c *ServiceClientMemory) GetSubTreeStream(_ context.Context, bktInfo *data.BucketInfo, treeID string, rootID []uint64, depth uint32) (SubTreeStream, error) {
cnr, ok := c.containers[bktInfo.CID.EncodeToString()] cnr, ok := c.containers[bktInfo.CID.EncodeToString()]
if !ok { if !ok {
return &SubTreeStreamMemoryImpl{err: ErrNodeNotFound}, nil return &SubTreeStreamMemoryImpl{err: errors.ErrNodeNotFound}, nil
} }
tr, ok := cnr.trees[treeID] tr, ok := cnr.trees[treeID]
if !ok { if !ok {
return nil, ErrNodeNotFound return nil, errors.ErrNodeNotFound
} }
if len(rootID) != 1 { if len(rootID) != 1 {
return nil, errors.New("invalid rootID") return nil, stdErr.New("invalid rootID")
} }
node := tr.treeData.getNode(rootID[0]) node := tr.treeData.getNode(rootID[0])
if node == nil { if node == nil {
return nil, ErrNodeNotFound return nil, errors.ErrNodeNotFound
} }
sortNode(tr.treeData) sortNode(tr.treeData)
@ -353,7 +354,7 @@ func (c *ServiceClientMemory) AddNodeBase(_ context.Context, bktInfo *data.Bucke
parentNode := tr.treeData.getNode(parent) parentNode := tr.treeData.getNode(parent)
if parentNode == nil { if parentNode == nil {
return 0, ErrNodeNotFound return 0, errors.ErrNodeNotFound
} }
newID := tr.idCounter 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 { 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()] cnr, ok := c.containers[bktInfo.CID.EncodeToString()]
if !ok { if !ok {
return ErrNodeNotFound return errors.ErrNodeNotFound
} }
tr, ok := cnr.trees[treeID] tr, ok := cnr.trees[treeID]
if !ok { if !ok {
return ErrNodeNotFound return errors.ErrNodeNotFound
} }
node := tr.treeData.getNode(nodeID) node := tr.treeData.getNode(nodeID)
if node == nil { if node == nil {
return ErrNodeNotFound return errors.ErrNodeNotFound
} }
newParent := tr.treeData.getNode(parentID) newParent := tr.treeData.getNode(parentID)
if newParent == nil { if newParent == nil {
return ErrNodeNotFound return errors.ErrNodeNotFound
} }
node.data.meta = metaToNodeMeta(meta) 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 { func (c *ServiceClientMemory) RemoveNode(_ context.Context, bktInfo *data.BucketInfo, treeID string, nodeID uint64) error {
cnr, ok := c.containers[bktInfo.CID.EncodeToString()] cnr, ok := c.containers[bktInfo.CID.EncodeToString()]
if !ok { if !ok {
return ErrNodeNotFound return errors.ErrNodeNotFound
} }
tr, ok := cnr.trees[treeID] tr, ok := cnr.trees[treeID]
if !ok { if !ok {
return ErrNodeNotFound return errors.ErrNodeNotFound
} }
node := tr.treeData.getNode(nodeID) node := tr.treeData.getNode(nodeID)
if node == nil { if node == nil {
return ErrNodeNotFound return errors.ErrNodeNotFound
} }
node.parent.removeChild(nodeID) node.parent.removeChild(nodeID)