From d531b13866d5fe28d71f9efb762aee0cde292b9d Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Fri, 30 Jun 2023 12:03:55 +0300 Subject: [PATCH] [#143] Add more context to some s3 errors Signed-off-by: Denis Kirillov --- api/errors/errors.go | 3 +++ api/handler/acl.go | 2 +- api/handler/acl_test.go | 29 +++++++++++++++++++------ api/handler/delete_test.go | 30 ++++++++++++-------------- api/handler/put_test.go | 16 ++++++++++++-- api/layer/compound.go | 9 ++++---- api/layer/container.go | 6 ++---- api/layer/cors.go | 2 +- api/layer/layer.go | 2 +- api/layer/multipart_upload.go | 40 +++++++++++++++++------------------ api/layer/object.go | 10 ++++----- api/layer/system_object.go | 2 +- api/layer/tagging.go | 27 ++++++++++++----------- 13 files changed, 105 insertions(+), 73 deletions(-) diff --git a/api/errors/errors.go b/api/errors/errors.go index 1ce4d0d0..47822e12 100644 --- a/api/errors/errors.go +++ b/api/errors/errors.go @@ -3,6 +3,8 @@ package errors import ( "fmt" "net/http" + + frosterrors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/errors" ) type ( @@ -1700,6 +1702,7 @@ var errorCodes = errorCodeMap{ // IsS3Error checks if the provided error is a specific s3 error. func IsS3Error(err error, code ErrorCode) bool { + err = frosterrors.UnwrapErr(err) e, ok := err.(Error) return ok && e.ErrCode == code } diff --git a/api/handler/acl.go b/api/handler/acl.go index 5e6c2e94..65c3b6e3 100644 --- a/api/handler/acl.go +++ b/api/handler/acl.go @@ -507,7 +507,7 @@ func checkOwner(info *data.BucketInfo, owner string) error { // may need to convert owner to appropriate format if info.Owner.String() != owner { - return errors.GetAPIError(errors.ErrAccessDenied) + return fmt.Errorf("%w: mismatch owner", errors.GetAPIError(errors.ErrAccessDenied)) } return nil diff --git a/api/handler/acl_test.go b/api/handler/acl_test.go index f3c877c5..b91960d8 100644 --- a/api/handler/acl_test.go +++ b/api/handler/acl_test.go @@ -11,10 +11,12 @@ import ( "fmt" "io" "net/http" + "net/http/httptest" "testing" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" + s3errors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" @@ -1480,9 +1482,14 @@ func createAccessBox(t *testing.T) (*accessbox.Box, *keys.PrivateKey) { tok := new(session.Container) tok.ForVerb(session.VerbContainerSetEACL) + err = tok.Sign(key.PrivateKey) + require.NoError(t, err) tok2 := new(session.Container) tok2.ForVerb(session.VerbContainerPut) + err = tok2.Sign(key.PrivateKey) + require.NoError(t, err) + box := &accessbox.Box{ Gate: &accessbox.GateData{ SessionTokens: []*session.Container{tok, tok2}, @@ -1493,18 +1500,28 @@ func createAccessBox(t *testing.T) (*accessbox.Box, *keys.PrivateKey) { return box, key } -func createBucket(t *testing.T, tc *handlerContext, bktName string, box *accessbox.Box) *data.BucketInfo { - w, r := prepareTestRequest(tc, bktName, "", nil) - ctx := context.WithValue(r.Context(), api.BoxData, box) - r = r.WithContext(ctx) - tc.Handler().CreateBucketHandler(w, r) +func createBucket(t *testing.T, hc *handlerContext, bktName string, box *accessbox.Box) *data.BucketInfo { + w := createBucketBase(hc, bktName, box) assertStatus(t, w, http.StatusOK) - bktInfo, err := tc.Layer().GetBucketInfo(tc.Context(), bktName) + bktInfo, err := hc.Layer().GetBucketInfo(hc.Context(), bktName) require.NoError(t, err) return bktInfo } +func createBucketAssertS3Error(hc *handlerContext, bktName string, box *accessbox.Box, code s3errors.ErrorCode) { + w := createBucketBase(hc, bktName, box) + assertS3Error(hc.t, w, s3errors.GetAPIError(code)) +} + +func createBucketBase(hc *handlerContext, bktName string, box *accessbox.Box) *httptest.ResponseRecorder { + w, r := prepareTestRequest(hc, bktName, "", nil) + ctx := context.WithValue(r.Context(), api.BoxData, box) + r = r.WithContext(ctx) + hc.Handler().CreateBucketHandler(w, r) + return w +} + func putBucketACL(t *testing.T, tc *handlerContext, bktName string, box *accessbox.Box, header map[string]string) { w, r := prepareTestRequest(tc, bktName, "", nil) for key, val := range header { diff --git a/api/handler/delete_test.go b/api/handler/delete_test.go index 7c5160c9..947ef3f6 100644 --- a/api/handler/delete_test.go +++ b/api/handler/delete_test.go @@ -3,6 +3,7 @@ package handler import ( "bytes" "net/http" + "net/http/httptest" "net/url" "testing" @@ -431,31 +432,28 @@ func deleteBucket(t *testing.T, tc *handlerContext, bktName string, code int) { assertStatus(t, w, code) } -func checkNotFound(t *testing.T, tc *handlerContext, bktName, objName, version string) { - query := make(url.Values) - query.Add(api.QueryVersionID, version) - - w, r := prepareTestFullRequest(tc, bktName, objName, query, nil) - tc.Handler().HeadObjectHandler(w, r) +func checkNotFound(t *testing.T, hc *handlerContext, bktName, objName, version string) { + w := headObjectBase(hc, bktName, objName, version) assertStatus(t, w, http.StatusNotFound) } func headObjectAssertS3Error(hc *handlerContext, bktName, objName, version string, code apiErrors.ErrorCode) { + w := headObjectBase(hc, bktName, objName, version) + assertS3Error(hc.t, w, apiErrors.GetAPIError(code)) +} + +func checkFound(t *testing.T, hc *handlerContext, bktName, objName, version string) { + w := headObjectBase(hc, bktName, objName, version) + assertStatus(t, w, http.StatusOK) +} + +func headObjectBase(hc *handlerContext, bktName, objName, version string) *httptest.ResponseRecorder { query := make(url.Values) query.Add(api.QueryVersionID, version) w, r := prepareTestFullRequest(hc, bktName, objName, query, nil) hc.Handler().HeadObjectHandler(w, r) - assertS3Error(hc.t, w, apiErrors.GetAPIError(code)) -} - -func checkFound(t *testing.T, tc *handlerContext, bktName, objName, version string) { - query := make(url.Values) - query.Add(api.QueryVersionID, version) - - w, r := prepareTestFullRequest(tc, bktName, objName, query, nil) - tc.Handler().HeadObjectHandler(w, r) - assertStatus(t, w, http.StatusOK) + return w } func listVersions(t *testing.T, tc *handlerContext, bktName string) *ListObjectsVersionsResponse { diff --git a/api/handler/put_test.go b/api/handler/put_test.go index 044a0fa9..d65c365e 100644 --- a/api/handler/put_test.go +++ b/api/handler/put_test.go @@ -16,7 +16,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth" v4 "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth/signer/v4" - "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/creds/accessbox" "github.com/aws/aws-sdk-go/aws/credentials" @@ -166,7 +166,7 @@ func TestPutObjectWithStreamBodyError(t *testing.T) { r.Header.Set(api.AmzContentSha256, api.StreamingContentSHA256) r.Header.Set(api.ContentEncoding, api.AwsChunked) tc.Handler().PutObjectHandler(w, r) - assertS3Error(t, w, errors.GetAPIError(errors.ErrMissingContentLength)) + assertS3Error(t, w, s3errors.GetAPIError(s3errors.ErrMissingContentLength)) checkNotFound(t, tc, bktName, objName, emptyVersion) } @@ -239,3 +239,15 @@ func TestPutObjectWithStreamBodyAWSExample(t *testing.T) { require.Equal(t, chunk[i], data[i]) } } + +func TestCreateBucket(t *testing.T) { + hc := prepareHandlerContext(t) + bktName := "bkt-name" + + box, _ := createAccessBox(t) + createBucket(t, hc, bktName, box) + createBucketAssertS3Error(hc, bktName, box, s3errors.ErrBucketAlreadyOwnedByYou) + + box2, _ := createAccessBox(t) + createBucketAssertS3Error(hc, bktName, box2, s3errors.ErrBucketAlreadyExists) +} diff --git a/api/layer/compound.go b/api/layer/compound.go index 4ac4a6f0..8f322029 100644 --- a/api/layer/compound.go +++ b/api/layer/compound.go @@ -2,10 +2,11 @@ package layer import ( "context" - errorsStd "errors" + "errors" + "fmt" "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" ) func (n *layer) GetObjectTaggingAndLock(ctx context.Context, objVersion *ObjectVersion, nodeVersion *data.NodeVersion) (map[string]string, *data.LockInfo, error) { @@ -28,8 +29,8 @@ func (n *layer) GetObjectTaggingAndLock(ctx context.Context, objVersion *ObjectV tags, lockInfo, err = n.treeService.GetObjectTaggingAndLock(ctx, objVersion.BktInfo, nodeVersion) if err != nil { - if errorsStd.Is(err, ErrNodeNotFound) { - return nil, nil, errors.GetAPIError(errors.ErrNoSuchKey) + if errors.Is(err, ErrNodeNotFound) { + return nil, nil, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error()) } return nil, nil, err } diff --git a/api/layer/container.go b/api/layer/container.go index e4c5b136..b7657238 100644 --- a/api/layer/container.go +++ b/api/layer/container.go @@ -8,7 +8,7 @@ import ( v2container "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" - "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" + s3errors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -43,10 +43,8 @@ func (n *layer) containerInfo(ctx context.Context, idCnr cid.ID) (*data.BucketIn ) res, err = n.frostFS.Container(ctx, idCnr) if err != nil { - log.Error("could not fetch container", zap.Error(err)) - if client.IsErrContainerNotFound(err) { - return nil, errors.GetAPIError(errors.ErrNoSuchBucket) + return nil, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchBucket), err.Error()) } return nil, fmt.Errorf("get frostfs container: %w", err) } diff --git a/api/layer/cors.go b/api/layer/cors.go index 25b02b05..2d6b6e46 100644 --- a/api/layer/cors.go +++ b/api/layer/cors.go @@ -73,7 +73,7 @@ func (n *layer) GetBucketCORS(ctx context.Context, bktInfo *data.BucketInfo) (*d cors, err := n.getCORS(ctx, bktInfo) if err != nil { if errorsStd.Is(err, ErrNodeNotFound) { - return nil, errors.GetAPIError(errors.ErrNoSuchCORSConfiguration) + return nil, fmt.Errorf("%w: %s", errors.GetAPIError(errors.ErrNoSuchCORSConfiguration), err.Error()) } return nil, err } diff --git a/api/layer/layer.go b/api/layer/layer.go index 693df0f0..7c28d4c1 100644 --- a/api/layer/layer.go +++ b/api/layer/layer.go @@ -361,7 +361,7 @@ func (n *layer) GetBucketInfo(ctx context.Context, name string) (*data.BucketInf containerID, err := n.ResolveBucket(ctx, name) if err != nil { if strings.Contains(err.Error(), "not found") { - return nil, errors.GetAPIError(errors.ErrNoSuchBucket) + return nil, fmt.Errorf("%w: %s", errors.GetAPIError(errors.ErrNoSuchBucket), err.Error()) } return nil, err } diff --git a/api/layer/multipart_upload.go b/api/layer/multipart_upload.go index 3807c820..b453269b 100644 --- a/api/layer/multipart_upload.go +++ b/api/layer/multipart_upload.go @@ -3,7 +3,7 @@ package layer import ( "context" "encoding/hex" - stderrors "errors" + "errors" "fmt" "io" "sort" @@ -12,7 +12,7 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" - "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" + s3errors "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer/encryption" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" @@ -174,14 +174,14 @@ func (n *layer) CreateMultipartUpload(ctx context.Context, p *CreateMultipartPar func (n *layer) UploadPart(ctx context.Context, p *UploadPartParams) (string, error) { multipartInfo, err := n.treeService.GetMultipartUpload(ctx, p.Info.Bkt, p.Info.Key, p.Info.UploadID) if err != nil { - if stderrors.Is(err, ErrNodeNotFound) { - return "", errors.GetAPIError(errors.ErrNoSuchUpload) + if errors.Is(err, ErrNodeNotFound) { + return "", fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchUpload), err.Error()) } return "", err } if p.Size > uploadMaxSize { - return "", errors.GetAPIError(errors.ErrEntityTooLarge) + return "", fmt.Errorf("%w: %d/%d", s3errors.GetAPIError(s3errors.ErrEntityTooLarge), p.Size, uploadMaxSize) } objInfo, err := n.uploadPart(ctx, multipartInfo, p) @@ -196,7 +196,7 @@ func (n *layer) uploadPart(ctx context.Context, multipartInfo *data.MultipartInf encInfo := FormEncryptionInfo(multipartInfo.Meta) if err := p.Info.Encryption.MatchObjectEncryption(encInfo); err != nil { n.reqLogger(ctx).Warn("mismatched obj encryptionInfo", zap.Error(err)) - return nil, errors.GetAPIError(errors.ErrInvalidEncryptionParameters) + return nil, s3errors.GetAPIError(s3errors.ErrInvalidEncryptionParameters) } bktInfo := p.Info.Bkt @@ -246,7 +246,7 @@ func (n *layer) uploadPart(ctx context.Context, multipartInfo *data.MultipartInf } oldPartID, err := n.treeService.AddPart(ctx, bktInfo, multipartInfo.ID, partInfo) - oldPartIDNotFound := stderrors.Is(err, ErrNoNodeToRemove) + oldPartIDNotFound := errors.Is(err, ErrNoNodeToRemove) if err != nil && !oldPartIDNotFound { return nil, err } @@ -275,8 +275,8 @@ func (n *layer) uploadPart(ctx context.Context, multipartInfo *data.MultipartInf func (n *layer) UploadPartCopy(ctx context.Context, p *UploadCopyParams) (*data.ObjectInfo, error) { multipartInfo, err := n.treeService.GetMultipartUpload(ctx, p.Info.Bkt, p.Info.Key, p.Info.UploadID) if err != nil { - if stderrors.Is(err, ErrNodeNotFound) { - return nil, errors.GetAPIError(errors.ErrNoSuchUpload) + if errors.Is(err, ErrNodeNotFound) { + return nil, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchUpload), err.Error()) } return nil, err } @@ -285,11 +285,11 @@ func (n *layer) UploadPartCopy(ctx context.Context, p *UploadCopyParams) (*data. if p.Range != nil { size = p.Range.End - p.Range.Start + 1 if p.Range.End > p.SrcObjInfo.Size { - return nil, errors.GetAPIError(errors.ErrInvalidCopyPartRangeSource) + return nil, fmt.Errorf("%w: %d-%d/%d", s3errors.GetAPIError(s3errors.ErrInvalidCopyPartRangeSource), p.Range.Start, p.Range.End, p.SrcObjInfo.Size) } } if size > uploadMaxSize { - return nil, errors.GetAPIError(errors.ErrEntityTooLarge) + return nil, fmt.Errorf("%w: %d/%d", s3errors.GetAPIError(s3errors.ErrEntityTooLarge), size, uploadMaxSize) } pr, pw := io.Pipe() @@ -333,7 +333,7 @@ type multiObjectReader struct { func (x *multiObjectReader) Read(p []byte) (n int, err error) { if x.curReader != nil { n, err = x.curReader.Read(p) - if !stderrors.Is(err, io.EOF) { + if !errors.Is(err, io.EOF) { return n, err } } @@ -359,7 +359,7 @@ func (x *multiObjectReader) Read(p []byte) (n int, err error) { func (n *layer) CompleteMultipartUpload(ctx context.Context, p *CompleteMultipartParams) (*UploadData, *data.ExtendedObjectInfo, error) { for i := 1; i < len(p.Parts); i++ { if p.Parts[i].PartNumber <= p.Parts[i-1].PartNumber { - return nil, nil, errors.GetAPIError(errors.ErrInvalidPartOrder) + return nil, nil, s3errors.GetAPIError(s3errors.ErrInvalidPartOrder) } } @@ -370,7 +370,7 @@ func (n *layer) CompleteMultipartUpload(ctx context.Context, p *CompleteMultipar encInfo := FormEncryptionInfo(multipartInfo.Meta) if len(partsInfo) < len(p.Parts) { - return nil, nil, errors.GetAPIError(errors.ErrInvalidPart) + return nil, nil, fmt.Errorf("%w: found %d parts, need %d", s3errors.GetAPIError(s3errors.ErrInvalidPart), len(partsInfo), len(p.Parts)) } var multipartObjetSize uint64 @@ -381,11 +381,11 @@ func (n *layer) CompleteMultipartUpload(ctx context.Context, p *CompleteMultipar for i, part := range p.Parts { partInfo := partsInfo[part.PartNumber] if partInfo == nil || part.ETag != partInfo.ETag { - return nil, nil, errors.GetAPIError(errors.ErrInvalidPart) + return nil, nil, fmt.Errorf("%w: unknown part %d or etag mismatched", s3errors.GetAPIError(s3errors.ErrInvalidPart), part.PartNumber) } // for the last part we have no minimum size limit if i != len(p.Parts)-1 && partInfo.Size < uploadMinSize { - return nil, nil, errors.GetAPIError(errors.ErrEntityTooSmall) + return nil, nil, fmt.Errorf("%w: %d/%d", s3errors.GetAPIError(s3errors.ErrEntityTooSmall), partInfo.Size, uploadMinSize) } parts = append(parts, partInfo) multipartObjetSize += partInfo.Size // even if encryption is enabled size is actual (decrypted) @@ -455,7 +455,7 @@ func (n *layer) CompleteMultipartUpload(ctx context.Context, p *CompleteMultipar zap.String("uploadKey", p.Info.Key), zap.Error(err)) - return nil, nil, errors.GetAPIError(errors.ErrInternalError) + return nil, nil, s3errors.GetAPIError(s3errors.ErrInternalError) } var addr oid.Address @@ -559,7 +559,7 @@ func (n *layer) ListParts(ctx context.Context, p *ListPartsParams) (*ListPartsIn encInfo := FormEncryptionInfo(multipartInfo.Meta) if err = p.Info.Encryption.MatchObjectEncryption(encInfo); err != nil { n.reqLogger(ctx).Warn("mismatched obj encryptionInfo", zap.Error(err)) - return nil, errors.GetAPIError(errors.ErrInvalidEncryptionParameters) + return nil, s3errors.GetAPIError(s3errors.ErrInvalidEncryptionParameters) } res.Owner = multipartInfo.Owner @@ -602,8 +602,8 @@ func (n *layer) ListParts(ctx context.Context, p *ListPartsParams) (*ListPartsIn func (n *layer) getUploadParts(ctx context.Context, p *UploadInfoParams) (*data.MultipartInfo, map[int]*data.PartInfo, error) { multipartInfo, err := n.treeService.GetMultipartUpload(ctx, p.Bkt, p.Key, p.UploadID) if err != nil { - if stderrors.Is(err, ErrNodeNotFound) { - return nil, nil, errors.GetAPIError(errors.ErrNoSuchUpload) + if errors.Is(err, ErrNodeNotFound) { + return nil, nil, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchUpload), err.Error()) } return nil, nil, err } diff --git a/api/layer/object.go b/api/layer/object.go index 95f7b9d8..04730063 100644 --- a/api/layer/object.go +++ b/api/layer/object.go @@ -308,13 +308,13 @@ func (n *layer) headLastVersionIfNotDeleted(ctx context.Context, bkt *data.Bucke node, err := n.treeService.GetLatestVersion(ctx, bkt, objectName) if err != nil { if errors.Is(err, ErrNodeNotFound) { - return nil, apiErrors.GetAPIError(apiErrors.ErrNoSuchKey) + return nil, fmt.Errorf("%w: %s", apiErrors.GetAPIError(apiErrors.ErrNoSuchKey), err.Error()) } return nil, err } if node.IsDeleteMarker() { - return nil, apiErrors.GetAPIError(apiErrors.ErrNoSuchKey) + return nil, fmt.Errorf("%w: found version is delete marker", apiErrors.GetAPIError(apiErrors.ErrNoSuchKey)) } meta, err := n.objectHead(ctx, bkt, node.OID) @@ -343,7 +343,7 @@ func (n *layer) headVersion(ctx context.Context, bkt *data.BucketInfo, p *HeadOb foundVersion, err = n.treeService.GetUnversioned(ctx, bkt, p.Object) if err != nil { if errors.Is(err, ErrNodeNotFound) { - return nil, apiErrors.GetAPIError(apiErrors.ErrNoSuchVersion) + return nil, fmt.Errorf("%w: %s", apiErrors.GetAPIError(apiErrors.ErrNoSuchVersion), err.Error()) } return nil, err } @@ -360,7 +360,7 @@ func (n *layer) headVersion(ctx context.Context, bkt *data.BucketInfo, p *HeadOb } } if foundVersion == nil { - return nil, apiErrors.GetAPIError(apiErrors.ErrNoSuchVersion) + return nil, fmt.Errorf("%w: there isn't tree node with requested version id", apiErrors.GetAPIError(apiErrors.ErrNoSuchVersion)) } } @@ -372,7 +372,7 @@ func (n *layer) headVersion(ctx context.Context, bkt *data.BucketInfo, p *HeadOb meta, err := n.objectHead(ctx, bkt, foundVersion.OID) if err != nil { if client.IsErrObjectNotFound(err) { - return nil, apiErrors.GetAPIError(apiErrors.ErrNoSuchVersion) + return nil, fmt.Errorf("%w: %s", apiErrors.GetAPIError(apiErrors.ErrNoSuchVersion), err.Error()) } return nil, err } diff --git a/api/layer/system_object.go b/api/layer/system_object.go index 0563341d..b5500d8c 100644 --- a/api/layer/system_object.go +++ b/api/layer/system_object.go @@ -167,7 +167,7 @@ func (n *layer) getCORS(ctx context.Context, bkt *data.BucketInfo) (*data.CORSCo } if objIDNotFound { - return nil, errors.GetAPIError(errors.ErrNoSuchCORSConfiguration) + return nil, fmt.Errorf("%w: %s", errors.GetAPIError(errors.ErrNoSuchCORSConfiguration), err.Error()) } obj, err := n.objectGet(ctx, bkt, objID) diff --git a/api/layer/tagging.go b/api/layer/tagging.go index a1144d3b..ff399f69 100644 --- a/api/layer/tagging.go +++ b/api/layer/tagging.go @@ -2,10 +2,11 @@ package layer import ( "context" - errorsStd "errors" + "errors" + "fmt" "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" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" @@ -52,8 +53,8 @@ func (n *layer) GetObjectTagging(ctx context.Context, p *GetObjectTaggingParams) tags, err := n.treeService.GetObjectTagging(ctx, p.ObjectVersion.BktInfo, nodeVersion) if err != nil { - if errorsStd.Is(err, ErrNodeNotFound) { - return "", nil, errors.GetAPIError(errors.ErrNoSuchKey) + if errors.Is(err, ErrNodeNotFound) { + return "", nil, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error()) } return "", nil, err } @@ -75,8 +76,8 @@ func (n *layer) PutObjectTagging(ctx context.Context, p *PutObjectTaggingParams) err = n.treeService.PutObjectTagging(ctx, p.ObjectVersion.BktInfo, nodeVersion, p.TagSet) if err != nil { - if errorsStd.Is(err, ErrNodeNotFound) { - return nil, errors.GetAPIError(errors.ErrNoSuchKey) + if errors.Is(err, ErrNodeNotFound) { + return nil, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error()) } return nil, err } @@ -94,8 +95,8 @@ func (n *layer) DeleteObjectTagging(ctx context.Context, p *ObjectVersion) (*dat err = n.treeService.DeleteObjectTagging(ctx, p.BktInfo, version) if err != nil { - if errorsStd.Is(err, ErrNodeNotFound) { - return nil, errors.GetAPIError(errors.ErrNoSuchKey) + if errors.Is(err, ErrNodeNotFound) { + return nil, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error()) } return nil, err } @@ -115,7 +116,7 @@ func (n *layer) GetBucketTagging(ctx context.Context, bktInfo *data.BucketInfo) } tags, err := n.treeService.GetBucketTagging(ctx, bktInfo) - if err != nil && !errorsStd.Is(err, ErrNodeNotFound) { + if err != nil && !errors.Is(err, ErrNodeNotFound) { return nil, err } @@ -168,12 +169,14 @@ func (n *layer) getNodeVersion(ctx context.Context, objVersion *ObjectVersion) ( } } if version == nil { - err = errors.GetAPIError(errors.ErrNoSuchVersion) + err = fmt.Errorf("%w: there isn't tree node with requested version id", s3errors.GetAPIError(s3errors.ErrNoSuchVersion)) } } - if err == nil && version.IsDeleteMarker() && !objVersion.NoErrorOnDeleteMarker || errorsStd.Is(err, ErrNodeNotFound) { - return nil, errors.GetAPIError(errors.ErrNoSuchKey) + if err == nil && version.IsDeleteMarker() && !objVersion.NoErrorOnDeleteMarker { + return nil, fmt.Errorf("%w: found version is delete marker", s3errors.GetAPIError(s3errors.ErrNoSuchKey)) + } else if errors.Is(err, ErrNodeNotFound) { + return nil, fmt.Errorf("%w: %s", s3errors.GetAPIError(s3errors.ErrNoSuchKey), err.Error()) } if err == nil && version != nil && !version.IsDeleteMarker() {