Compare commits
No commits in common. "v0.28.2" and "v0.28.1" have entirely different histories.
13 changed files with 31 additions and 176 deletions
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -4,15 +4,6 @@ This document outlines major changes between releases.
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
## [0.28.2] - 2024-05-27
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- `anon` user in billing metrics (#321)
|
|
||||||
- Parts are not removed when multipart object removed (#370)
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- Put request in duration metrics (#280)
|
|
||||||
|
|
||||||
## [0.28.1] - 2024-01-24
|
## [0.28.1] - 2024-01-24
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -129,5 +120,4 @@ To see CHANGELOG for older versions, refer to https://github.com/nspcc-dev/neofs
|
||||||
[0.27.0]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/b2148cc3...v0.27.0
|
[0.27.0]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/b2148cc3...v0.27.0
|
||||||
[0.28.0]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.27.0...v0.28.0
|
[0.28.0]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.27.0...v0.28.0
|
||||||
[0.28.1]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.28.0...v0.28.1
|
[0.28.1]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.28.0...v0.28.1
|
||||||
[0.28.2]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.28.1...v0.28.2
|
[Unreleased]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.28.1...master
|
||||||
[Unreleased]: https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/compare/v0.28.2...master
|
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
v0.28.2
|
v0.28.1
|
||||||
|
|
|
@ -62,52 +62,6 @@ func TestPeriodicWriter(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDeleteMultipartAllParts(t *testing.T) {
|
|
||||||
hc := prepareHandlerContext(t)
|
|
||||||
|
|
||||||
partSize := layer.UploadMinSize
|
|
||||||
objLen := 6 * partSize
|
|
||||||
|
|
||||||
bktName, bktName2, objName := "bucket", "bucket2", "object"
|
|
||||||
|
|
||||||
// unversioned bucket
|
|
||||||
createTestBucket(hc, bktName)
|
|
||||||
multipartUpload(hc, bktName, objName, nil, objLen, partSize)
|
|
||||||
deleteObject(t, hc, bktName, objName, emptyVersion)
|
|
||||||
require.Empty(t, hc.tp.Objects())
|
|
||||||
|
|
||||||
// encrypted multipart
|
|
||||||
multipartUploadEncrypted(hc, bktName, objName, nil, objLen, partSize)
|
|
||||||
deleteObject(t, hc, bktName, objName, emptyVersion)
|
|
||||||
require.Empty(t, hc.tp.Objects())
|
|
||||||
|
|
||||||
// versions bucket
|
|
||||||
createTestBucket(hc, bktName2)
|
|
||||||
putBucketVersioning(t, hc, bktName2, true)
|
|
||||||
multipartUpload(hc, bktName2, objName, nil, objLen, partSize)
|
|
||||||
_, hdr := getObject(hc, bktName2, objName)
|
|
||||||
versionID := hdr.Get("X-Amz-Version-Id")
|
|
||||||
deleteObject(t, hc, bktName2, objName, emptyVersion)
|
|
||||||
deleteObject(t, hc, bktName2, objName, versionID)
|
|
||||||
require.Empty(t, hc.tp.Objects())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMultipartTreeSize(t *testing.T) {
|
|
||||||
hc := prepareHandlerContext(t)
|
|
||||||
|
|
||||||
partSize := layer.UploadMinSize
|
|
||||||
objLen := 6 * partSize
|
|
||||||
|
|
||||||
bktName, objName := "bucket", "object"
|
|
||||||
|
|
||||||
bktInfo := createTestBucket(hc, bktName)
|
|
||||||
multipartUpload(hc, bktName, objName, nil, objLen, partSize)
|
|
||||||
|
|
||||||
nodeVersion, err := hc.tree.GetLatestVersion(hc.Context(), bktInfo, objName)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.EqualValues(t, objLen, nodeVersion.Size)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMultipartUploadInvalidPart(t *testing.T) {
|
func TestMultipartUploadInvalidPart(t *testing.T) {
|
||||||
hc := prepareHandlerContext(t)
|
hc := prepareHandlerContext(t)
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -753,40 +752,9 @@ func (n *layer) removeOldVersion(ctx context.Context, bkt *data.BucketInfo, node
|
||||||
return obj.VersionID, nil
|
return obj.VersionID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if nodeVersion.IsCombined {
|
|
||||||
return "", n.removeCombinedObject(ctx, bkt, nodeVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", n.objectDelete(ctx, bkt, nodeVersion.OID)
|
return "", n.objectDelete(ctx, bkt, nodeVersion.OID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *layer) removeCombinedObject(ctx context.Context, bkt *data.BucketInfo, nodeVersion *data.NodeVersion) error {
|
|
||||||
combinedObj, err := n.objectGet(ctx, bkt, nodeVersion.OID)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get combined object '%s': %w", nodeVersion.OID.EncodeToString(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var parts []*data.PartInfo
|
|
||||||
if err = json.Unmarshal(combinedObj.Payload(), &parts); err != nil {
|
|
||||||
return fmt.Errorf("unmarshal combined object parts: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, part := range parts {
|
|
||||||
if err = n.objectDelete(ctx, bkt, part.OID); err == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !client.IsErrObjectAlreadyRemoved(err) && !client.IsErrObjectNotFound(err) {
|
|
||||||
return fmt.Errorf("couldn't delete part '%s': %w", part.OID.EncodeToString(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
n.reqLogger(ctx).Warn(logs.CouldntDeletePart, zap.String("cid", bkt.CID.EncodeToString()),
|
|
||||||
zap.String("oid", part.OID.EncodeToString()), zap.Int("part number", part.Number), zap.Error(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
return n.objectDelete(ctx, bkt, nodeVersion.OID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteObjects from the storage.
|
// DeleteObjects from the storage.
|
||||||
func (n *layer) DeleteObjects(ctx context.Context, p *DeleteObjectParams) []*VersionedObject {
|
func (n *layer) DeleteObjects(ctx context.Context, p *DeleteObjectParams) []*VersionedObject {
|
||||||
for i, obj := range p.Objects {
|
for i, obj := range p.Objects {
|
||||||
|
|
|
@ -315,7 +315,7 @@ func (n *layer) PutObject(ctx context.Context, p *PutObjectParams) (*data.Extend
|
||||||
OID: id,
|
OID: id,
|
||||||
ETag: hex.EncodeToString(hash),
|
ETag: hex.EncodeToString(hash),
|
||||||
FilePath: p.Object,
|
FilePath: p.Object,
|
||||||
Size: p.Size,
|
Size: size,
|
||||||
},
|
},
|
||||||
IsUnversioned: !bktSettings.VersioningEnabled(),
|
IsUnversioned: !bktSettings.VersioningEnabled(),
|
||||||
IsCombined: p.Header[MultipartObjectSize] != "",
|
IsCombined: p.Header[MultipartObjectSize] != "",
|
||||||
|
@ -356,7 +356,7 @@ func (n *layer) PutObject(ctx context.Context, p *PutObjectParams) (*data.Extend
|
||||||
Owner: n.gateOwner,
|
Owner: n.gateOwner,
|
||||||
Bucket: p.BktInfo.Name,
|
Bucket: p.BktInfo.Name,
|
||||||
Name: p.Object,
|
Name: p.Object,
|
||||||
Size: size, // we don't use here p.Size to be consistent with the objectInfoFromMeta function
|
Size: size,
|
||||||
Created: prm.CreationTime,
|
Created: prm.CreationTime,
|
||||||
Headers: p.Header,
|
Headers: p.Header,
|
||||||
ContentType: p.Header[api.ContentType],
|
ContentType: p.Header[api.ContentType],
|
||||||
|
|
|
@ -6,7 +6,6 @@ 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/errors"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
||||||
"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"
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -14,8 +13,6 @@ func Auth(center auth.Center, log *zap.Logger) Func {
|
||||||
return func(h http.Handler) http.Handler {
|
return func(h http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
reqInfo := GetReqInfo(ctx)
|
|
||||||
reqInfo.User = "anon"
|
|
||||||
box, err := center.Authenticate(r)
|
box, err := center.Authenticate(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == auth.ErrNoAuthorizationHeader {
|
if err == auth.ErrNoAuthorizationHeader {
|
||||||
|
@ -34,10 +31,6 @@ func Auth(center auth.Center, log *zap.Logger) Func {
|
||||||
ctx = SetClientTime(ctx, box.ClientTime)
|
ctx = SetClientTime(ctx, box.ClientTime)
|
||||||
}
|
}
|
||||||
ctx = SetAuthHeaders(ctx, box.AuthHeaders)
|
ctx = SetAuthHeaders(ctx, box.AuthHeaders)
|
||||||
|
|
||||||
if box.AccessBox.Gate.BearerToken != nil {
|
|
||||||
reqInfo.User = bearer.ResolveIssuer(*box.AccessBox.Gate.BearerToken).String()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h.ServeHTTP(w, r.WithContext(ctx))
|
h.ServeHTTP(w, r.WithContext(ctx))
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"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/internal/logs"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/metrics"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/metrics"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -79,8 +80,9 @@ func stats(f http.HandlerFunc, resolveCID cidResolveFunc, appMetrics *metrics.Ap
|
||||||
// simply for the fact that it is not human-readable.
|
// simply for the fact that it is not human-readable.
|
||||||
durationSecs := time.Since(statsWriter.startTime).Seconds()
|
durationSecs := time.Since(statsWriter.startTime).Seconds()
|
||||||
|
|
||||||
|
user := resolveUser(r.Context())
|
||||||
cnrID := resolveCID(r.Context(), reqInfo)
|
cnrID := resolveCID(r.Context(), reqInfo)
|
||||||
appMetrics.Update(reqInfo.User, reqInfo.BucketName, cnrID, requestTypeFromAPI(reqInfo.API), in.countBytes, out.countBytes)
|
appMetrics.Update(user, reqInfo.BucketName, cnrID, requestTypeFromAPI(reqInfo.API), in.countBytes, out.countBytes)
|
||||||
|
|
||||||
code := statsWriter.statusCode
|
code := statsWriter.statusCode
|
||||||
// A successful request has a 2xx response code
|
// A successful request has a 2xx response code
|
||||||
|
@ -92,8 +94,10 @@ func stats(f http.HandlerFunc, resolveCID cidResolveFunc, appMetrics *metrics.Ap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Increment the prometheus http request response histogram with appropriate label
|
if r.Method == http.MethodGet {
|
||||||
appMetrics.Statistic().RequestDurationsUpdate(reqInfo.API, durationSecs)
|
// Increment the prometheus http request response histogram with appropriate label
|
||||||
|
appMetrics.Statistic().RequestDurationsUpdate(reqInfo.API, durationSecs)
|
||||||
|
}
|
||||||
|
|
||||||
appMetrics.Statistic().TotalInputBytesAdd(in.countBytes)
|
appMetrics.Statistic().TotalInputBytesAdd(in.countBytes)
|
||||||
appMetrics.Statistic().TotalOutputBytesAdd(out.countBytes)
|
appMetrics.Statistic().TotalOutputBytesAdd(out.countBytes)
|
||||||
|
@ -146,6 +150,14 @@ func resolveCID(log *zap.Logger, resolveBucket BucketResolveFunc) cidResolveFunc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func resolveUser(ctx context.Context) string {
|
||||||
|
user := "anon"
|
||||||
|
if bd, err := GetBoxData(ctx); err == nil && bd.Gate.BearerToken != nil {
|
||||||
|
user = bearer.ResolveIssuer(*bd.Gate.BearerToken).String()
|
||||||
|
}
|
||||||
|
return user
|
||||||
|
}
|
||||||
|
|
||||||
// WriteHeader -- writes http status code.
|
// WriteHeader -- writes http status code.
|
||||||
func (w *responseWrapper) WriteHeader(code int) {
|
func (w *responseWrapper) WriteHeader(code int) {
|
||||||
w.Do(func() {
|
w.Do(func() {
|
||||||
|
|
|
@ -36,7 +36,6 @@ type (
|
||||||
BucketName string // Bucket name
|
BucketName string // Bucket name
|
||||||
ObjectName string // Object name
|
ObjectName string // Object name
|
||||||
TraceID string // Trace ID
|
TraceID string // Trace ID
|
||||||
User string // User owner id
|
|
||||||
URL *url.URL // Request url
|
URL *url.URL // Request url
|
||||||
tags []KeyVal // Any additional info not accommodated by above fields
|
tags []KeyVal // Any additional info not accommodated by above fields
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,34 +9,14 @@ 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"
|
||||||
"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/creds/accessbox"
|
|
||||||
bearertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer/test"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
type anonCenterMock struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *anonCenterMock) Authenticate(*http.Request) (*auth.Box, error) {
|
|
||||||
return &auth.Box{
|
|
||||||
AccessBox: &accessbox.Box{
|
|
||||||
Gate: &accessbox.GateData{},
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type centerMock struct {
|
type centerMock struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *centerMock) Authenticate(*http.Request) (*auth.Box, error) {
|
func (c *centerMock) Authenticate(*http.Request) (*auth.Box, error) {
|
||||||
token := bearertest.Token()
|
return &auth.Box{}, nil
|
||||||
return &auth.Box{
|
|
||||||
AccessBox: &accessbox.Box{
|
|
||||||
Gate: &accessbox.GateData{
|
|
||||||
BearerToken: &token,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type handlerMock struct {
|
type handlerMock struct {
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/auth"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/metrics"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/metrics"
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/go-chi/chi/v5/middleware"
|
"github.com/go-chi/chi/v5/middleware"
|
||||||
|
@ -19,7 +18,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRouterUploadPart(t *testing.T) {
|
func TestRouterUploadPart(t *testing.T) {
|
||||||
chiRouter := prepareRouter(t, &anonCenterMock{})
|
chiRouter := prepareRouter(t)
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
r := httptest.NewRequest(http.MethodPut, "/dkirillov/fix-object", nil)
|
r := httptest.NewRequest(http.MethodPut, "/dkirillov/fix-object", nil)
|
||||||
|
@ -34,7 +33,7 @@ func TestRouterUploadPart(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRouterListMultipartUploads(t *testing.T) {
|
func TestRouterListMultipartUploads(t *testing.T) {
|
||||||
chiRouter := prepareRouter(t, &anonCenterMock{})
|
chiRouter := prepareRouter(t)
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
r := httptest.NewRequest(http.MethodGet, "/test-bucket", nil)
|
r := httptest.NewRequest(http.MethodGet, "/test-bucket", nil)
|
||||||
|
@ -48,7 +47,7 @@ func TestRouterListMultipartUploads(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRouterObjectWithSlashes(t *testing.T) {
|
func TestRouterObjectWithSlashes(t *testing.T) {
|
||||||
chiRouter := prepareRouter(t, &anonCenterMock{})
|
chiRouter := prepareRouter(t)
|
||||||
|
|
||||||
bktName, objName := "dkirillov", "/fix/object"
|
bktName, objName := "dkirillov", "/fix/object"
|
||||||
target := fmt.Sprintf("/%s/%s", bktName, objName)
|
target := fmt.Sprintf("/%s/%s", bktName, objName)
|
||||||
|
@ -63,7 +62,7 @@ func TestRouterObjectWithSlashes(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRouterObjectEscaping(t *testing.T) {
|
func TestRouterObjectEscaping(t *testing.T) {
|
||||||
chiRouter := prepareRouter(t, &anonCenterMock{})
|
chiRouter := prepareRouter(t)
|
||||||
|
|
||||||
bktName := "dkirillov"
|
bktName := "dkirillov"
|
||||||
|
|
||||||
|
@ -107,38 +106,19 @@ func TestRouterObjectEscaping(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOwnerIDRetrieving(t *testing.T) {
|
func prepareRouter(t *testing.T) *chi.Mux {
|
||||||
anonRouter := prepareRouter(t, &anonCenterMock{})
|
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
r := httptest.NewRequest(http.MethodGet, "/test-bucket", nil)
|
|
||||||
|
|
||||||
anonRouter.ServeHTTP(w, r)
|
|
||||||
resp := readResponse(t, w)
|
|
||||||
require.Equal(t, "anon", resp.ReqInfo.User)
|
|
||||||
|
|
||||||
chiRouter := prepareRouter(t, ¢erMock{})
|
|
||||||
|
|
||||||
w = httptest.NewRecorder()
|
|
||||||
r = httptest.NewRequest(http.MethodGet, "/test-bucket", nil)
|
|
||||||
|
|
||||||
chiRouter.ServeHTTP(w, r)
|
|
||||||
resp = readResponse(t, w)
|
|
||||||
require.NotEqual(t, "anon", resp.ReqInfo.User)
|
|
||||||
}
|
|
||||||
|
|
||||||
func prepareRouter(t *testing.T, center auth.Center) *chi.Mux {
|
|
||||||
throttleOps := middleware.ThrottleOpts{
|
throttleOps := middleware.ThrottleOpts{
|
||||||
Limit: 10,
|
Limit: 10,
|
||||||
BacklogTimeout: 30 * time.Second,
|
BacklogTimeout: 30 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMock := &handlerMock{t: t}
|
handleMock := &handlerMock{t: t}
|
||||||
|
cntrMock := ¢erMock{}
|
||||||
log := zaptest.NewLogger(t)
|
log := zaptest.NewLogger(t)
|
||||||
metric := &metrics.AppMetrics{}
|
metric := &metrics.AppMetrics{}
|
||||||
|
|
||||||
chiRouter := chi.NewRouter()
|
chiRouter := chi.NewRouter()
|
||||||
AttachChi(chiRouter, nil, throttleOps, handleMock, center, log, metric)
|
AttachChi(chiRouter, nil, throttleOps, handleMock, cntrMock, log, metric)
|
||||||
return chiRouter
|
return chiRouter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -25,7 +25,6 @@ require (
|
||||||
go.opentelemetry.io/otel/trace v1.16.0
|
go.opentelemetry.io/otel/trace v1.16.0
|
||||||
go.uber.org/zap v1.24.0
|
go.uber.org/zap v1.24.0
|
||||||
golang.org/x/crypto v0.9.0
|
golang.org/x/crypto v0.9.0
|
||||||
golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc
|
|
||||||
google.golang.org/grpc v1.55.0
|
google.golang.org/grpc v1.55.0
|
||||||
google.golang.org/protobuf v1.30.0
|
google.golang.org/protobuf v1.30.0
|
||||||
)
|
)
|
||||||
|
@ -86,6 +85,7 @@ require (
|
||||||
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
|
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
|
||||||
go.uber.org/atomic v1.10.0 // indirect
|
go.uber.org/atomic v1.10.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc // indirect
|
||||||
golang.org/x/net v0.10.0 // indirect
|
golang.org/x/net v0.10.0 // indirect
|
||||||
golang.org/x/sync v0.2.0 // indirect
|
golang.org/x/sync v0.2.0 // indirect
|
||||||
golang.org/x/sys v0.8.0 // indirect
|
golang.org/x/sys v0.8.0 // indirect
|
||||||
|
|
|
@ -565,7 +565,7 @@ func (c *Tree) GetVersions(ctx context.Context, bktInfo *data.BucketInfo, filepa
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Tree) GetLatestVersion(ctx context.Context, bktInfo *data.BucketInfo, objectName string) (*data.NodeVersion, error) {
|
func (c *Tree) GetLatestVersion(ctx context.Context, bktInfo *data.BucketInfo, objectName string) (*data.NodeVersion, error) {
|
||||||
meta := []string{oidKV, isCombinedKV, isUnversionedKV, isDeleteMarkerKV, etagKV, sizeKV, md5KV}
|
meta := []string{oidKV, isUnversionedKV, isDeleteMarkerKV, etagKV, sizeKV, md5KV}
|
||||||
path := pathFromName(objectName)
|
path := pathFromName(objectName)
|
||||||
|
|
||||||
p := &GetNodesParams{
|
p := &GetNodesParams{
|
||||||
|
@ -1191,7 +1191,7 @@ func (c *Tree) clearOutdatedVersionInfo(ctx context.Context, bktInfo *data.Bucke
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Tree) getVersions(ctx context.Context, bktInfo *data.BucketInfo, treeID, filepath string, onlyUnversioned bool) ([]*data.NodeVersion, error) {
|
func (c *Tree) getVersions(ctx context.Context, bktInfo *data.BucketInfo, treeID, filepath string, onlyUnversioned bool) ([]*data.NodeVersion, error) {
|
||||||
keysToReturn := []string{oidKV, isCombinedKV, isUnversionedKV, isDeleteMarkerKV, etagKV, sizeKV, md5KV}
|
keysToReturn := []string{oidKV, isUnversionedKV, isDeleteMarkerKV, etagKV, sizeKV, md5KV}
|
||||||
path := pathFromName(filepath)
|
path := pathFromName(filepath)
|
||||||
p := &GetNodesParams{
|
p := &GetNodesParams{
|
||||||
BktInfo: bktInfo,
|
BktInfo: bktInfo,
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
"golang.org/x/exp/slices"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type nodeMeta struct {
|
type nodeMeta struct {
|
||||||
|
@ -184,22 +183,6 @@ func NewTreeServiceClientMemory() (*ServiceClientMemory, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type nodeResponseWrapper struct {
|
|
||||||
nodeResponse
|
|
||||||
allAttr bool
|
|
||||||
attrs []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n nodeResponseWrapper) GetMeta() []Meta {
|
|
||||||
res := make([]Meta, 0, len(n.meta))
|
|
||||||
for _, value := range n.meta {
|
|
||||||
if n.allAttr || slices.Contains(n.attrs, value.key) {
|
|
||||||
res = append(res, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ServiceClientMemory) GetNodes(_ context.Context, p *GetNodesParams) ([]NodeResponse, error) {
|
func (c *ServiceClientMemory) GetNodes(_ context.Context, p *GetNodesParams) ([]NodeResponse, error) {
|
||||||
cnr, ok := c.containers[p.BktInfo.CID.EncodeToString()]
|
cnr, ok := c.containers[p.BktInfo.CID.EncodeToString()]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -222,11 +205,7 @@ func (c *ServiceClientMemory) GetNodes(_ context.Context, p *GetNodesParams) ([]
|
||||||
|
|
||||||
res2 := make([]NodeResponse, len(res))
|
res2 := make([]NodeResponse, len(res))
|
||||||
for i, n := range res {
|
for i, n := range res {
|
||||||
res2[i] = nodeResponseWrapper{
|
res2[i] = n
|
||||||
nodeResponse: n,
|
|
||||||
allAttr: p.AllAttrs,
|
|
||||||
attrs: p.Meta,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res2, nil
|
return res2, nil
|
||||||
|
|
Loading…
Add table
Reference in a new issue