[#488] Add transformation to S3 error in policy check
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:
parent
d0e4d55772
commit
41dc579744
23 changed files with 179 additions and 182 deletions
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
16
api/layer/errors/errors.go
Normal file
16
api/layer/errors/errors.go
Normal 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")
|
||||||
|
)
|
|
@ -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.
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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")
|
|
||||||
)
|
|
||||||
|
|
|
@ -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]
|
|
||||||
}
|
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.",
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue