forked from TrueCloudLab/frostfs-s3-gw
[#236] api: Create info.go for basic structs
Moved BucketInfo and ObjectInfo from layer and handler to api Signed-off-by: Angira Kekteeva <kira@nspcc.ru>
This commit is contained in:
parent
345dafb29d
commit
239742f413
17 changed files with 231 additions and 229 deletions
34
api/cache/buckets.go
vendored
34
api/cache/buckets.go
vendored
|
@ -4,27 +4,17 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/bluele/gcache"
|
"github.com/bluele/gcache"
|
||||||
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
|
"github.com/nspcc-dev/neofs-s3-gw/api"
|
||||||
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// BucketCache provides interface for lru cache for objects.
|
// BucketCache provides interface for lru cache for objects.
|
||||||
BucketCache interface {
|
BucketCache interface {
|
||||||
Get(key string) *BucketInfo
|
Get(key string) *api.BucketInfo
|
||||||
Put(bkt *BucketInfo) error
|
Put(bkt *api.BucketInfo) error
|
||||||
Delete(key string) bool
|
Delete(key string) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// BucketInfo stores basic bucket data.
|
|
||||||
BucketInfo struct {
|
|
||||||
Name string
|
|
||||||
CID *cid.ID
|
|
||||||
Owner *owner.ID
|
|
||||||
Created time.Time
|
|
||||||
BasicACL uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetBucketCache contains cache with objects and lifetime of cache entries.
|
// GetBucketCache contains cache with objects and lifetime of cache entries.
|
||||||
GetBucketCache struct {
|
GetBucketCache struct {
|
||||||
cache gcache.Cache
|
cache gcache.Cache
|
||||||
|
@ -40,13 +30,13 @@ func NewBucketCache(cacheSize int, lifetime time.Duration) *GetBucketCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get returns cached object.
|
// Get returns cached object.
|
||||||
func (o *GetBucketCache) Get(key string) *BucketInfo {
|
func (o *GetBucketCache) Get(key string) *api.BucketInfo {
|
||||||
entry, err := o.cache.Get(key)
|
entry, err := o.cache.Get(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
result, ok := entry.(*BucketInfo)
|
result, ok := entry.(*api.BucketInfo)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -55,7 +45,7 @@ func (o *GetBucketCache) Get(key string) *BucketInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put puts an object to cache.
|
// Put puts an object to cache.
|
||||||
func (o *GetBucketCache) Put(bkt *BucketInfo) error {
|
func (o *GetBucketCache) Put(bkt *api.BucketInfo) error {
|
||||||
return o.cache.SetWithExpire(bkt.Name, bkt, o.lifetime)
|
return o.cache.SetWithExpire(bkt.Name, bkt, o.lifetime)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,15 +53,3 @@ func (o *GetBucketCache) Put(bkt *BucketInfo) error {
|
||||||
func (o *GetBucketCache) Delete(key string) bool {
|
func (o *GetBucketCache) Delete(key string) bool {
|
||||||
return o.cache.Remove(key)
|
return o.cache.Remove(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
const bktVersionSettingsObject = ".s3-versioning-settings"
|
|
||||||
|
|
||||||
// SettingsObjectName is system name for bucket settings file.
|
|
||||||
func (b *BucketInfo) SettingsObjectName() string {
|
|
||||||
return bktVersionSettingsObject
|
|
||||||
}
|
|
||||||
|
|
||||||
// SystemObjectKey is key to use in SystemCache.
|
|
||||||
func (b *BucketInfo) SystemObjectKey(obj string) string {
|
|
||||||
return b.Name + obj
|
|
||||||
}
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ import (
|
||||||
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/acl"
|
"github.com/nspcc-dev/neofs-api-go/v2/acl"
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api"
|
"github.com/nspcc-dev/neofs-s3-gw/api"
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/cache"
|
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
|
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/layer"
|
"github.com/nspcc-dev/neofs-s3-gw/api/layer"
|
||||||
)
|
)
|
||||||
|
@ -300,7 +299,7 @@ func (h *handler) GetBucketPolicyHandler(w http.ResponseWriter, r *http.Request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkOwner(info *cache.BucketInfo, owner string) error {
|
func checkOwner(info *api.BucketInfo, owner string) error {
|
||||||
if owner == "" {
|
if owner == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ func path2BucketObject(path string) (bucket, prefix string) {
|
||||||
func (h *handler) CopyObjectHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) CopyObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
info *layer.ObjectInfo
|
info *api.ObjectInfo
|
||||||
metadata map[string]string
|
metadata map[string]string
|
||||||
|
|
||||||
reqInfo = api.GetReqInfo(r.Context())
|
reqInfo = api.GetReqInfo(r.Context())
|
||||||
|
@ -118,7 +118,7 @@ func (h *handler) CopyObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
h.log.Info("object is copied",
|
h.log.Info("object is copied",
|
||||||
zap.String("bucket", info.Bucket),
|
zap.String("bucket", info.Bucket),
|
||||||
zap.String("object", info.Name),
|
zap.String("object", info.Name),
|
||||||
zap.Stringer("object_id", info.ID()))
|
zap.Stringer("object_id", info.ID))
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseCopyObjectArgs(headers http.Header) (*copyObjectArgs, error) {
|
func parseCopyObjectArgs(headers http.Header) (*copyObjectArgs, error) {
|
||||||
|
|
|
@ -65,14 +65,14 @@ func fetchRangeHeader(headers http.Header, fullSize uint64) (*layer.RangeParams,
|
||||||
return &layer.RangeParams{Start: start, End: end}, nil
|
return &layer.RangeParams{Start: start, End: end}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeHeaders(h http.Header, info *layer.ObjectInfo, tagSetLength int) {
|
func writeHeaders(h http.Header, info *api.ObjectInfo, tagSetLength int) {
|
||||||
if len(info.ContentType) > 0 {
|
if len(info.ContentType) > 0 {
|
||||||
h.Set(api.ContentType, info.ContentType)
|
h.Set(api.ContentType, info.ContentType)
|
||||||
}
|
}
|
||||||
h.Set(api.LastModified, info.Created.UTC().Format(http.TimeFormat))
|
h.Set(api.LastModified, info.Created.UTC().Format(http.TimeFormat))
|
||||||
h.Set(api.ContentLength, strconv.FormatInt(info.Size, 10))
|
h.Set(api.ContentLength, strconv.FormatInt(info.Size, 10))
|
||||||
h.Set(api.ETag, info.HashSum)
|
h.Set(api.ETag, info.HashSum)
|
||||||
h.Set(api.AmzVersionID, info.ID().String())
|
h.Set(api.AmzVersionID, info.ID.String())
|
||||||
h.Set(api.AmzTaggingCount, strconv.Itoa(tagSetLength))
|
h.Set(api.AmzTaggingCount, strconv.Itoa(tagSetLength))
|
||||||
|
|
||||||
for key, val := range info.Headers {
|
for key, val := range info.Headers {
|
||||||
|
@ -83,7 +83,7 @@ func writeHeaders(h http.Header, info *layer.ObjectInfo, tagSetLength int) {
|
||||||
func (h *handler) GetObjectHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) GetObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
info *layer.ObjectInfo
|
info *api.ObjectInfo
|
||||||
params *layer.RangeParams
|
params *layer.RangeParams
|
||||||
|
|
||||||
reqInfo = api.GetReqInfo(r.Context())
|
reqInfo = api.GetReqInfo(r.Context())
|
||||||
|
@ -143,7 +143,7 @@ func (h *handler) GetObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkPreconditions(info *layer.ObjectInfo, args *conditionalArgs) error {
|
func checkPreconditions(info *api.ObjectInfo, args *conditionalArgs) error {
|
||||||
if len(args.IfMatch) > 0 && args.IfMatch != info.HashSum {
|
if len(args.IfMatch) > 0 && args.IfMatch != info.HashSum {
|
||||||
return errors.GetAPIError(errors.ErrPreconditionFailed)
|
return errors.GetAPIError(errors.ErrPreconditionFailed)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-s3-gw/api"
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
|
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/layer"
|
"github.com/nspcc-dev/neofs-s3-gw/api/layer"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -45,8 +46,8 @@ func TestFetchRangeHeader(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newInfo(etag string, created time.Time) *layer.ObjectInfo {
|
func newInfo(etag string, created time.Time) *api.ObjectInfo {
|
||||||
return &layer.ObjectInfo{
|
return &api.ObjectInfo{
|
||||||
HashSum: etag,
|
HashSum: etag,
|
||||||
Created: created,
|
Created: created,
|
||||||
}
|
}
|
||||||
|
@ -60,13 +61,13 @@ func TestPreconditions(t *testing.T) {
|
||||||
|
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
name string
|
name string
|
||||||
info *layer.ObjectInfo
|
info *api.ObjectInfo
|
||||||
args *conditionalArgs
|
args *conditionalArgs
|
||||||
expected error
|
expected error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no conditions",
|
name: "no conditions",
|
||||||
info: new(layer.ObjectInfo),
|
info: new(api.ObjectInfo),
|
||||||
args: new(conditionalArgs),
|
args: new(conditionalArgs),
|
||||||
expected: nil,
|
expected: nil,
|
||||||
},
|
},
|
||||||
|
|
|
@ -27,7 +27,7 @@ func getRangeToDetectContentType(maxSize int64) *layer.RangeParams {
|
||||||
func (h *handler) HeadObjectHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) HeadObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
info *layer.ObjectInfo
|
info *api.ObjectInfo
|
||||||
|
|
||||||
reqInfo = api.GetReqInfo(r.Context())
|
reqInfo = api.GetReqInfo(r.Context())
|
||||||
)
|
)
|
||||||
|
@ -62,7 +62,7 @@ func (h *handler) HeadObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
VersionID: reqInfo.URL.Query().Get(api.QueryVersionID),
|
VersionID: reqInfo.URL.Query().Get(api.QueryVersionID),
|
||||||
}
|
}
|
||||||
if err = h.obj.GetObject(r.Context(), getParams); err != nil {
|
if err = h.obj.GetObject(r.Context(), getParams); err != nil {
|
||||||
h.logAndSendError(w, "could not get object", reqInfo, err, zap.Stringer("oid", info.ID()))
|
h.logAndSendError(w, "could not get object", reqInfo, err, zap.Stringer("oid", info.ID))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
info.ContentType = http.DetectContentType(buffer.Bytes())
|
info.ContentType = http.DetectContentType(buffer.Bytes())
|
||||||
|
|
|
@ -183,11 +183,11 @@ func fillPrefixes(src []string, encode string) []CommonPrefix {
|
||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
func fillContentsWithOwner(src []*layer.ObjectInfo, encode string) []Object {
|
func fillContentsWithOwner(src []*api.ObjectInfo, encode string) []Object {
|
||||||
return fillContents(src, encode, true)
|
return fillContents(src, encode, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fillContents(src []*layer.ObjectInfo, encode string, fetchOwner bool) []Object {
|
func fillContents(src []*api.ObjectInfo, encode string, fetchOwner bool) []Object {
|
||||||
var dst []Object
|
var dst []Object
|
||||||
for _, obj := range src {
|
for _, obj := range src {
|
||||||
res := Object{
|
res := Object{
|
||||||
|
|
65
api/info.go
Normal file
65
api/info.go
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
|
||||||
|
)
|
||||||
|
|
||||||
|
const bktVersionSettingsObject = ".s3-versioning-settings"
|
||||||
|
|
||||||
|
type (
|
||||||
|
// BucketInfo stores basic bucket data.
|
||||||
|
BucketInfo struct {
|
||||||
|
Name string
|
||||||
|
CID *cid.ID
|
||||||
|
Owner *owner.ID
|
||||||
|
Created time.Time
|
||||||
|
BasicACL uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjectInfo holds S3 object data.
|
||||||
|
ObjectInfo struct {
|
||||||
|
ID *object.ID
|
||||||
|
CID *cid.ID
|
||||||
|
IsDir bool
|
||||||
|
|
||||||
|
Bucket string
|
||||||
|
Name string
|
||||||
|
Size int64
|
||||||
|
ContentType string
|
||||||
|
Created time.Time
|
||||||
|
CreationEpoch uint64
|
||||||
|
HashSum string
|
||||||
|
Owner *owner.ID
|
||||||
|
Headers map[string]string
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// SettingsObjectName is system name for bucket settings file.
|
||||||
|
func (b *BucketInfo) SettingsObjectName() string { return bktVersionSettingsObject }
|
||||||
|
|
||||||
|
// SystemObjectKey is key to use in SystemCache.
|
||||||
|
func (b *BucketInfo) SystemObjectKey(obj string) string {
|
||||||
|
return b.Name + obj
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version returns object version from ObjectInfo.
|
||||||
|
func (o *ObjectInfo) Version() string { return o.ID.String() }
|
||||||
|
|
||||||
|
// NiceName returns object name for cache.
|
||||||
|
func (o *ObjectInfo) NiceName() string { return o.Bucket + "/" + o.Name }
|
||||||
|
|
||||||
|
// Address returns object address.
|
||||||
|
func (o *ObjectInfo) Address() *object.Address {
|
||||||
|
address := object.NewAddress()
|
||||||
|
address.SetContainerID(o.CID)
|
||||||
|
address.SetObjectID(o.ID)
|
||||||
|
|
||||||
|
return address
|
||||||
|
}
|
||||||
|
|
||||||
|
// TagsObject returns name of system object for tags.
|
||||||
|
func (o *ObjectInfo) TagsObject() string { return ".tagset." + o.Name + "." + o.Version() }
|
|
@ -12,7 +12,6 @@ import (
|
||||||
"github.com/nspcc-dev/neofs-api-go/pkg/container"
|
"github.com/nspcc-dev/neofs-api-go/pkg/container"
|
||||||
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
|
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api"
|
"github.com/nspcc-dev/neofs-s3-gw/api"
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/cache"
|
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
|
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/pool"
|
"github.com/nspcc-dev/neofs-sdk-go/pool"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
@ -21,19 +20,19 @@ import (
|
||||||
type (
|
type (
|
||||||
// BucketACL extends BucketInfo by eacl.Table.
|
// BucketACL extends BucketInfo by eacl.Table.
|
||||||
BucketACL struct {
|
BucketACL struct {
|
||||||
Info *cache.BucketInfo
|
Info *api.BucketInfo
|
||||||
EACL *eacl.Table
|
EACL *eacl.Table
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (n *layer) containerInfo(ctx context.Context, cid *cid.ID) (*cache.BucketInfo, error) {
|
func (n *layer) containerInfo(ctx context.Context, cid *cid.ID) (*api.BucketInfo, error) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
res *container.Container
|
res *container.Container
|
||||||
rid = api.GetRequestID(ctx)
|
rid = api.GetRequestID(ctx)
|
||||||
bearerOpt = n.BearerOpt(ctx)
|
bearerOpt = n.BearerOpt(ctx)
|
||||||
|
|
||||||
info = &cache.BucketInfo{
|
info = &api.BucketInfo{
|
||||||
CID: cid,
|
CID: cid,
|
||||||
Name: cid.String(),
|
Name: cid.String(),
|
||||||
}
|
}
|
||||||
|
@ -84,7 +83,7 @@ func (n *layer) containerInfo(ctx context.Context, cid *cid.ID) (*cache.BucketIn
|
||||||
return info, nil
|
return info, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *layer) containerList(ctx context.Context) ([]*cache.BucketInfo, error) {
|
func (n *layer) containerList(ctx context.Context) ([]*api.BucketInfo, error) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
own = n.Owner(ctx)
|
own = n.Owner(ctx)
|
||||||
|
@ -100,7 +99,7 @@ func (n *layer) containerList(ctx context.Context) ([]*cache.BucketInfo, error)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
list := make([]*cache.BucketInfo, 0, len(res))
|
list := make([]*api.BucketInfo, 0, len(res))
|
||||||
for _, cid := range res {
|
for _, cid := range res {
|
||||||
info, err := n.containerInfo(ctx, cid)
|
info, err := n.containerInfo(ctx, cid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -118,7 +117,7 @@ func (n *layer) containerList(ctx context.Context) ([]*cache.BucketInfo, error)
|
||||||
|
|
||||||
func (n *layer) createContainer(ctx context.Context, p *CreateBucketParams) (*cid.ID, error) {
|
func (n *layer) createContainer(ctx context.Context, p *CreateBucketParams) (*cid.ID, error) {
|
||||||
var err error
|
var err error
|
||||||
bktInfo := &cache.BucketInfo{
|
bktInfo := &api.BucketInfo{
|
||||||
Name: p.Name,
|
Name: p.Name,
|
||||||
Owner: n.Owner(ctx),
|
Owner: n.Owner(ctx),
|
||||||
Created: time.Now(),
|
Created: time.Now(),
|
||||||
|
|
|
@ -54,7 +54,7 @@ type (
|
||||||
// GetObjectParams stores object get request parameters.
|
// GetObjectParams stores object get request parameters.
|
||||||
GetObjectParams struct {
|
GetObjectParams struct {
|
||||||
Range *RangeParams
|
Range *RangeParams
|
||||||
ObjectInfo *ObjectInfo
|
ObjectInfo *api.ObjectInfo
|
||||||
Offset int64
|
Offset int64
|
||||||
Length int64
|
Length int64
|
||||||
Writer io.Writer
|
Writer io.Writer
|
||||||
|
@ -96,7 +96,7 @@ type (
|
||||||
|
|
||||||
// CopyObjectParams stores object copy request parameters.
|
// CopyObjectParams stores object copy request parameters.
|
||||||
CopyObjectParams struct {
|
CopyObjectParams struct {
|
||||||
SrcObject *ObjectInfo
|
SrcObject *api.ObjectInfo
|
||||||
DstBucket string
|
DstBucket string
|
||||||
DstObject string
|
DstObject string
|
||||||
SrcSize int64
|
SrcSize int64
|
||||||
|
@ -138,7 +138,7 @@ type (
|
||||||
|
|
||||||
// PutTaggingParams stores tag set params.
|
// PutTaggingParams stores tag set params.
|
||||||
PutTaggingParams struct {
|
PutTaggingParams struct {
|
||||||
ObjectInfo *ObjectInfo
|
ObjectInfo *api.ObjectInfo
|
||||||
TagSet map[string]string
|
TagSet map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,33 +151,33 @@ type (
|
||||||
Client interface {
|
Client interface {
|
||||||
NeoFS
|
NeoFS
|
||||||
|
|
||||||
PutBucketVersioning(ctx context.Context, p *PutVersioningParams) (*ObjectInfo, error)
|
PutBucketVersioning(ctx context.Context, p *PutVersioningParams) (*api.ObjectInfo, error)
|
||||||
GetBucketVersioning(ctx context.Context, name string) (*BucketSettings, error)
|
GetBucketVersioning(ctx context.Context, name string) (*BucketSettings, error)
|
||||||
|
|
||||||
ListBuckets(ctx context.Context) ([]*cache.BucketInfo, error)
|
ListBuckets(ctx context.Context) ([]*api.BucketInfo, error)
|
||||||
GetBucketInfo(ctx context.Context, name string) (*cache.BucketInfo, error)
|
GetBucketInfo(ctx context.Context, name string) (*api.BucketInfo, error)
|
||||||
GetBucketACL(ctx context.Context, name string) (*BucketACL, error)
|
GetBucketACL(ctx context.Context, name string) (*BucketACL, error)
|
||||||
PutBucketACL(ctx context.Context, p *PutBucketACLParams) error
|
PutBucketACL(ctx context.Context, p *PutBucketACLParams) error
|
||||||
CreateBucket(ctx context.Context, p *CreateBucketParams) (*cid.ID, error)
|
CreateBucket(ctx context.Context, p *CreateBucketParams) (*cid.ID, error)
|
||||||
DeleteBucket(ctx context.Context, p *DeleteBucketParams) error
|
DeleteBucket(ctx context.Context, p *DeleteBucketParams) error
|
||||||
|
|
||||||
GetObject(ctx context.Context, p *GetObjectParams) error
|
GetObject(ctx context.Context, p *GetObjectParams) error
|
||||||
GetObjectInfo(ctx context.Context, p *HeadObjectParams) (*ObjectInfo, error)
|
GetObjectInfo(ctx context.Context, p *HeadObjectParams) (*api.ObjectInfo, error)
|
||||||
GetObjectTagging(ctx context.Context, p *ObjectInfo) (map[string]string, error)
|
GetObjectTagging(ctx context.Context, p *api.ObjectInfo) (map[string]string, error)
|
||||||
GetBucketTagging(ctx context.Context, bucket string) (map[string]string, error)
|
GetBucketTagging(ctx context.Context, bucket string) (map[string]string, error)
|
||||||
|
|
||||||
PutObject(ctx context.Context, p *PutObjectParams) (*ObjectInfo, error)
|
PutObject(ctx context.Context, p *PutObjectParams) (*api.ObjectInfo, error)
|
||||||
PutObjectTagging(ctx context.Context, p *PutTaggingParams) error
|
PutObjectTagging(ctx context.Context, p *PutTaggingParams) error
|
||||||
PutBucketTagging(ctx context.Context, bucket string, tagSet map[string]string) error
|
PutBucketTagging(ctx context.Context, bucket string, tagSet map[string]string) error
|
||||||
|
|
||||||
CopyObject(ctx context.Context, p *CopyObjectParams) (*ObjectInfo, error)
|
CopyObject(ctx context.Context, p *CopyObjectParams) (*api.ObjectInfo, error)
|
||||||
|
|
||||||
ListObjectsV1(ctx context.Context, p *ListObjectsParamsV1) (*ListObjectsInfoV1, error)
|
ListObjectsV1(ctx context.Context, p *ListObjectsParamsV1) (*ListObjectsInfoV1, error)
|
||||||
ListObjectsV2(ctx context.Context, p *ListObjectsParamsV2) (*ListObjectsInfoV2, error)
|
ListObjectsV2(ctx context.Context, p *ListObjectsParamsV2) (*ListObjectsInfoV2, error)
|
||||||
ListObjectVersions(ctx context.Context, p *ListObjectVersionsParams) (*ListObjectVersionsInfo, error)
|
ListObjectVersions(ctx context.Context, p *ListObjectVersionsParams) (*ListObjectVersionsInfo, error)
|
||||||
|
|
||||||
DeleteObjects(ctx context.Context, bucket string, objects []*VersionedObject) []error
|
DeleteObjects(ctx context.Context, bucket string, objects []*VersionedObject) []error
|
||||||
DeleteObjectTagging(ctx context.Context, p *ObjectInfo) error
|
DeleteObjectTagging(ctx context.Context, p *api.ObjectInfo) error
|
||||||
DeleteBucketTagging(ctx context.Context, bucket string) error
|
DeleteBucketTagging(ctx context.Context, bucket string) error
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -240,7 +240,7 @@ func (n *layer) Get(ctx context.Context, address *object.Address) (*object.Objec
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBucketInfo returns bucket info by name.
|
// GetBucketInfo returns bucket info by name.
|
||||||
func (n *layer) GetBucketInfo(ctx context.Context, name string) (*cache.BucketInfo, error) {
|
func (n *layer) GetBucketInfo(ctx context.Context, name string) (*api.BucketInfo, error) {
|
||||||
name, err := url.QueryUnescape(name)
|
name, err := url.QueryUnescape(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -298,7 +298,7 @@ func (n *layer) PutBucketACL(ctx context.Context, param *PutBucketACLParams) err
|
||||||
|
|
||||||
// ListBuckets returns all user containers. Name of the bucket is a container
|
// ListBuckets returns all user containers. Name of the bucket is a container
|
||||||
// id. Timestamp is omitted since it is not saved in neofs container.
|
// id. Timestamp is omitted since it is not saved in neofs container.
|
||||||
func (n *layer) ListBuckets(ctx context.Context) ([]*cache.BucketInfo, error) {
|
func (n *layer) ListBuckets(ctx context.Context) ([]*api.BucketInfo, error) {
|
||||||
return n.containerList(ctx)
|
return n.containerList(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,8 +308,8 @@ func (n *layer) GetObject(ctx context.Context, p *GetObjectParams) error {
|
||||||
|
|
||||||
params := &getParams{
|
params := &getParams{
|
||||||
Writer: p.Writer,
|
Writer: p.Writer,
|
||||||
cid: p.ObjectInfo.CID(),
|
cid: p.ObjectInfo.CID,
|
||||||
oid: p.ObjectInfo.ID(),
|
oid: p.ObjectInfo.ID,
|
||||||
offset: p.Offset,
|
offset: p.Offset,
|
||||||
length: p.Length,
|
length: p.Length,
|
||||||
}
|
}
|
||||||
|
@ -327,14 +327,14 @@ func (n *layer) GetObject(ctx context.Context, p *GetObjectParams) error {
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
n.objCache.Delete(p.ObjectInfo.Address())
|
n.objCache.Delete(p.ObjectInfo.Address())
|
||||||
return fmt.Errorf("couldn't get object, cid: %s : %w", p.ObjectInfo.CID(), err)
|
return fmt.Errorf("couldn't get object, cid: %s : %w", p.ObjectInfo.CID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetObjectInfo returns meta information about the object.
|
// GetObjectInfo returns meta information about the object.
|
||||||
func (n *layer) GetObjectInfo(ctx context.Context, p *HeadObjectParams) (*ObjectInfo, error) {
|
func (n *layer) GetObjectInfo(ctx context.Context, p *HeadObjectParams) (*api.ObjectInfo, error) {
|
||||||
bkt, err := n.GetBucketInfo(ctx, p.Bucket)
|
bkt, err := n.GetBucketInfo(ctx, p.Bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
n.log.Error("could not fetch bucket info", zap.Error(err))
|
n.log.Error("could not fetch bucket info", zap.Error(err))
|
||||||
|
@ -349,7 +349,7 @@ func (n *layer) GetObjectInfo(ctx context.Context, p *HeadObjectParams) (*Object
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutObject into storage.
|
// PutObject into storage.
|
||||||
func (n *layer) PutObject(ctx context.Context, p *PutObjectParams) (*ObjectInfo, error) {
|
func (n *layer) PutObject(ctx context.Context, p *PutObjectParams) (*api.ObjectInfo, error) {
|
||||||
bkt, err := n.GetBucketInfo(ctx, p.Bucket)
|
bkt, err := n.GetBucketInfo(ctx, p.Bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -359,10 +359,10 @@ func (n *layer) PutObject(ctx context.Context, p *PutObjectParams) (*ObjectInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetObjectTagging from storage.
|
// GetObjectTagging from storage.
|
||||||
func (n *layer) GetObjectTagging(ctx context.Context, oi *ObjectInfo) (map[string]string, error) {
|
func (n *layer) GetObjectTagging(ctx context.Context, oi *api.ObjectInfo) (map[string]string, error) {
|
||||||
bktInfo := &cache.BucketInfo{
|
bktInfo := &api.BucketInfo{
|
||||||
Name: oi.Bucket,
|
Name: oi.Bucket,
|
||||||
CID: oi.CID(),
|
CID: oi.CID,
|
||||||
Owner: oi.Owner,
|
Owner: oi.Owner,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,7 +389,7 @@ func (n *layer) GetBucketTagging(ctx context.Context, bucketName string) (map[st
|
||||||
return formTagSet(objInfo), nil
|
return formTagSet(objInfo), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func formTagSet(objInfo *ObjectInfo) map[string]string {
|
func formTagSet(objInfo *api.ObjectInfo) map[string]string {
|
||||||
var tagSet map[string]string
|
var tagSet map[string]string
|
||||||
if objInfo != nil {
|
if objInfo != nil {
|
||||||
tagSet = make(map[string]string, len(objInfo.Headers))
|
tagSet = make(map[string]string, len(objInfo.Headers))
|
||||||
|
@ -407,9 +407,9 @@ func formTagSet(objInfo *ObjectInfo) map[string]string {
|
||||||
|
|
||||||
// PutObjectTagging into storage.
|
// PutObjectTagging into storage.
|
||||||
func (n *layer) PutObjectTagging(ctx context.Context, p *PutTaggingParams) error {
|
func (n *layer) PutObjectTagging(ctx context.Context, p *PutTaggingParams) error {
|
||||||
bktInfo := &cache.BucketInfo{
|
bktInfo := &api.BucketInfo{
|
||||||
Name: p.ObjectInfo.Bucket,
|
Name: p.ObjectInfo.Bucket,
|
||||||
CID: p.ObjectInfo.CID(),
|
CID: p.ObjectInfo.CID,
|
||||||
Owner: p.ObjectInfo.Owner,
|
Owner: p.ObjectInfo.Owner,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,7 +435,7 @@ func (n *layer) PutBucketTagging(ctx context.Context, bucketName string, tagSet
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteObjectTagging from storage.
|
// DeleteObjectTagging from storage.
|
||||||
func (n *layer) DeleteObjectTagging(ctx context.Context, p *ObjectInfo) error {
|
func (n *layer) DeleteObjectTagging(ctx context.Context, p *api.ObjectInfo) error {
|
||||||
bktInfo, err := n.GetBucketInfo(ctx, p.Bucket)
|
bktInfo, err := n.GetBucketInfo(ctx, p.Bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -443,7 +443,7 @@ func (n *layer) DeleteObjectTagging(ctx context.Context, p *ObjectInfo) error {
|
||||||
return n.deleteSystemObject(ctx, bktInfo, p.TagsObject())
|
return n.deleteSystemObject(ctx, bktInfo, p.TagsObject())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *layer) deleteSystemObject(ctx context.Context, bktInfo *cache.BucketInfo, name string) error {
|
func (n *layer) deleteSystemObject(ctx context.Context, bktInfo *api.BucketInfo, name string) error {
|
||||||
var oid *object.ID
|
var oid *object.ID
|
||||||
if meta := n.systemCache.Get(bktInfo.SystemObjectKey(name)); meta != nil {
|
if meta := n.systemCache.Get(bktInfo.SystemObjectKey(name)); meta != nil {
|
||||||
oid = meta.ID()
|
oid = meta.ID()
|
||||||
|
@ -472,7 +472,7 @@ func (n *layer) DeleteBucketTagging(ctx context.Context, bucketName string) erro
|
||||||
return n.deleteSystemObject(ctx, bktInfo, formBucketTagObjectName(bucketName))
|
return n.deleteSystemObject(ctx, bktInfo, formBucketTagObjectName(bucketName))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *layer) putSystemObject(ctx context.Context, bktInfo *cache.BucketInfo, objName string, metadata map[string]string, prefix string) (*object.Object, error) {
|
func (n *layer) putSystemObject(ctx context.Context, bktInfo *api.BucketInfo, objName string, metadata map[string]string, prefix string) (*object.Object, error) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
oldOID *object.ID
|
oldOID *object.ID
|
||||||
|
@ -539,7 +539,7 @@ func (n *layer) putSystemObject(ctx context.Context, bktInfo *cache.BucketInfo,
|
||||||
return meta, nil
|
return meta, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *layer) getSystemObject(ctx context.Context, bkt *cache.BucketInfo, objName string) (*ObjectInfo, error) {
|
func (n *layer) getSystemObject(ctx context.Context, bkt *api.BucketInfo, objName string) (*api.ObjectInfo, error) {
|
||||||
if meta := n.systemCache.Get(bkt.SystemObjectKey(objName)); meta != nil {
|
if meta := n.systemCache.Get(bkt.SystemObjectKey(objName)); meta != nil {
|
||||||
return objInfoFromMeta(bkt, meta), nil
|
return objInfoFromMeta(bkt, meta), nil
|
||||||
}
|
}
|
||||||
|
@ -561,7 +561,7 @@ func (n *layer) getSystemObject(ctx context.Context, bkt *cache.BucketInfo, objN
|
||||||
}
|
}
|
||||||
|
|
||||||
// CopyObject from one bucket into another bucket.
|
// CopyObject from one bucket into another bucket.
|
||||||
func (n *layer) CopyObject(ctx context.Context, p *CopyObjectParams) (*ObjectInfo, error) {
|
func (n *layer) CopyObject(ctx context.Context, p *CopyObjectParams) (*api.ObjectInfo, error) {
|
||||||
pr, pw := io.Pipe()
|
pr, pw := io.Pipe()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -585,7 +585,7 @@ func (n *layer) CopyObject(ctx context.Context, p *CopyObjectParams) (*ObjectInf
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteObject removes all objects with passed nice name.
|
// DeleteObject removes all objects with passed nice name.
|
||||||
func (n *layer) deleteObject(ctx context.Context, bkt *cache.BucketInfo, obj *VersionedObject) error {
|
func (n *layer) deleteObject(ctx context.Context, bkt *api.BucketInfo, obj *VersionedObject) error {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
ids []*object.ID
|
ids []*object.ID
|
||||||
|
@ -627,7 +627,7 @@ func (n *layer) deleteObject(ctx context.Context, bkt *cache.BucketInfo, obj *Ve
|
||||||
if err = n.objectDelete(ctx, bkt.CID, id); err != nil {
|
if err = n.objectDelete(ctx, bkt.CID, id); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = n.DeleteObjectTagging(ctx, &ObjectInfo{id: id, Bucket: bkt.Name, Name: obj.Name}); err != nil {
|
if err = n.DeleteObjectTagging(ctx, &api.ObjectInfo{ID: id, Bucket: bkt.Name, Name: obj.Name}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@ import (
|
||||||
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
||||||
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
|
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api"
|
"github.com/nspcc-dev/neofs-s3-gw/api"
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/cache"
|
|
||||||
apiErrors "github.com/nspcc-dev/neofs-s3-gw/api/errors"
|
apiErrors "github.com/nspcc-dev/neofs-s3-gw/api/errors"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
@ -61,7 +60,7 @@ type (
|
||||||
}
|
}
|
||||||
|
|
||||||
allObjectParams struct {
|
allObjectParams struct {
|
||||||
Bucket *cache.BucketInfo
|
Bucket *api.BucketInfo
|
||||||
Delimiter string
|
Delimiter string
|
||||||
Prefix string
|
Prefix string
|
||||||
}
|
}
|
||||||
|
@ -128,7 +127,7 @@ func (n *layer) objectRange(ctx context.Context, p *getParams) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// objectPut into NeoFS, took payload from io.Reader.
|
// objectPut into NeoFS, took payload from io.Reader.
|
||||||
func (n *layer) objectPut(ctx context.Context, bkt *cache.BucketInfo, p *PutObjectParams) (*ObjectInfo, error) {
|
func (n *layer) objectPut(ctx context.Context, bkt *api.BucketInfo, p *PutObjectParams) (*api.ObjectInfo, error) {
|
||||||
own := n.Owner(ctx)
|
own := n.Owner(ctx)
|
||||||
obj, err := url.QueryUnescape(p.Object)
|
obj, err := url.QueryUnescape(p.Object)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -190,9 +189,9 @@ func (n *layer) objectPut(ctx context.Context, bkt *cache.BucketInfo, p *PutObje
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ObjectInfo{
|
return &api.ObjectInfo{
|
||||||
id: oid,
|
ID: oid,
|
||||||
bucketID: bkt.CID,
|
CID: bkt.CID,
|
||||||
|
|
||||||
Owner: own,
|
Owner: own,
|
||||||
Bucket: p.Bucket,
|
Bucket: p.Bucket,
|
||||||
|
@ -264,14 +263,14 @@ func updateCRDT2PSetHeaders(p *PutObjectParams, versions *objectVersions, versio
|
||||||
|
|
||||||
if lastVersion := versions.getLast(); lastVersion != nil {
|
if lastVersion := versions.getLast(); lastVersion != nil {
|
||||||
p.Header[versionsDelAttr] = versionsDeletedStr + lastVersion.Version()
|
p.Header[versionsDelAttr] = versionsDeletedStr + lastVersion.Version()
|
||||||
idsToDeleteArr = append(idsToDeleteArr, lastVersion.ID())
|
idsToDeleteArr = append(idsToDeleteArr, lastVersion.ID)
|
||||||
} else if len(versionsDeletedStr) != 0 {
|
} else if len(versionsDeletedStr) != 0 {
|
||||||
p.Header[versionsDelAttr] = versionsDeletedStr
|
p.Header[versionsDelAttr] = versionsDeletedStr
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, version := range versions.objects {
|
for _, version := range versions.objects {
|
||||||
if contains(versions.delList, version.Version()) {
|
if contains(versions.delList, version.Version()) {
|
||||||
idsToDeleteArr = append(idsToDeleteArr, version.ID())
|
idsToDeleteArr = append(idsToDeleteArr, version.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -279,7 +278,7 @@ func updateCRDT2PSetHeaders(p *PutObjectParams, versions *objectVersions, versio
|
||||||
return idsToDeleteArr
|
return idsToDeleteArr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *layer) headLastVersionIfNotDeleted(ctx context.Context, bkt *cache.BucketInfo, objectName string) (*ObjectInfo, error) {
|
func (n *layer) headLastVersionIfNotDeleted(ctx context.Context, bkt *api.BucketInfo, objectName string) (*api.ObjectInfo, error) {
|
||||||
if address := n.namesCache.Get(bkt.Name + "/" + objectName); address != nil {
|
if address := n.namesCache.Get(bkt.Name + "/" + objectName); address != nil {
|
||||||
if headInfo := n.objCache.Get(address); headInfo != nil {
|
if headInfo := n.objCache.Get(address); headInfo != nil {
|
||||||
return objInfoFromMeta(bkt, headInfo), nil
|
return objInfoFromMeta(bkt, headInfo), nil
|
||||||
|
@ -305,7 +304,7 @@ func (n *layer) headLastVersionIfNotDeleted(ctx context.Context, bkt *cache.Buck
|
||||||
return lastVersion, nil
|
return lastVersion, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *layer) headVersions(ctx context.Context, bkt *cache.BucketInfo, objectName string) (*objectVersions, error) {
|
func (n *layer) headVersions(ctx context.Context, bkt *api.BucketInfo, objectName string) (*objectVersions, error) {
|
||||||
ids, err := n.objectSearch(ctx, &findParams{cid: bkt.CID, val: objectName})
|
ids, err := n.objectSearch(ctx, &findParams{cid: bkt.CID, val: objectName})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -343,7 +342,7 @@ func (n *layer) headVersions(ctx context.Context, bkt *cache.BucketInfo, objectN
|
||||||
return versions, nil
|
return versions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *layer) headVersion(ctx context.Context, bkt *cache.BucketInfo, versionID string) (*ObjectInfo, error) {
|
func (n *layer) headVersion(ctx context.Context, bkt *api.BucketInfo, versionID string) (*api.ObjectInfo, error) {
|
||||||
oid := object.NewID()
|
oid := object.NewID()
|
||||||
if err := oid.Parse(versionID); err != nil {
|
if err := oid.Parse(versionID); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -365,9 +364,9 @@ func (n *layer) headVersion(ctx context.Context, bkt *cache.BucketInfo, versionI
|
||||||
if err = n.objCache.Put(*meta); err != nil {
|
if err = n.objCache.Put(*meta); err != nil {
|
||||||
n.log.Warn("couldn't put obj to object cache",
|
n.log.Warn("couldn't put obj to object cache",
|
||||||
zap.String("bucket name", objInfo.Bucket),
|
zap.String("bucket name", objInfo.Bucket),
|
||||||
zap.Stringer("bucket cid", objInfo.CID()),
|
zap.Stringer("bucket cid", objInfo.CID),
|
||||||
zap.String("object name", objInfo.Name),
|
zap.String("object name", objInfo.Name),
|
||||||
zap.Stringer("object id", objInfo.ID()),
|
zap.Stringer("object id", objInfo.ID),
|
||||||
zap.Error(err))
|
zap.Error(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,7 +387,7 @@ func (n *layer) ListObjectsV1(ctx context.Context, p *ListObjectsParamsV1) (*Lis
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
result ListObjectsInfoV1
|
result ListObjectsInfoV1
|
||||||
allObjects []*ObjectInfo
|
allObjects []*api.ObjectInfo
|
||||||
)
|
)
|
||||||
|
|
||||||
if p.MaxKeys == 0 {
|
if p.MaxKeys == 0 {
|
||||||
|
@ -423,7 +422,7 @@ func (n *layer) ListObjectsV2(ctx context.Context, p *ListObjectsParamsV2) (*Lis
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
result ListObjectsInfoV2
|
result ListObjectsInfoV2
|
||||||
allObjects []*ObjectInfo
|
allObjects []*api.ObjectInfo
|
||||||
)
|
)
|
||||||
|
|
||||||
if p.MaxKeys == 0 {
|
if p.MaxKeys == 0 {
|
||||||
|
@ -449,7 +448,7 @@ func (n *layer) ListObjectsV2(ctx context.Context, p *ListObjectsParamsV2) (*Lis
|
||||||
if len(allObjects) > p.MaxKeys {
|
if len(allObjects) > p.MaxKeys {
|
||||||
result.IsTruncated = true
|
result.IsTruncated = true
|
||||||
allObjects = allObjects[:p.MaxKeys]
|
allObjects = allObjects[:p.MaxKeys]
|
||||||
result.NextContinuationToken = allObjects[len(allObjects)-1].id.String()
|
result.NextContinuationToken = allObjects[len(allObjects)-1].ID.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Prefixes, result.Objects = triageObjects(allObjects)
|
result.Prefixes, result.Objects = triageObjects(allObjects)
|
||||||
|
@ -457,13 +456,13 @@ func (n *layer) ListObjectsV2(ctx context.Context, p *ListObjectsParamsV2) (*Lis
|
||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *layer) listSortedObjectsFromNeoFS(ctx context.Context, p allObjectParams) ([]*ObjectInfo, error) {
|
func (n *layer) listSortedObjectsFromNeoFS(ctx context.Context, p allObjectParams) ([]*api.ObjectInfo, error) {
|
||||||
versions, err := n.getAllObjectsVersions(ctx, p.Bucket, p.Prefix, p.Delimiter)
|
versions, err := n.getAllObjectsVersions(ctx, p.Bucket, p.Prefix, p.Delimiter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
objects := make([]*ObjectInfo, 0, len(versions))
|
objects := make([]*api.ObjectInfo, 0, len(versions))
|
||||||
for _, v := range versions {
|
for _, v := range versions {
|
||||||
lastVersion := v.getLast()
|
lastVersion := v.getLast()
|
||||||
if lastVersion != nil {
|
if lastVersion != nil {
|
||||||
|
@ -478,7 +477,7 @@ func (n *layer) listSortedObjectsFromNeoFS(ctx context.Context, p allObjectParam
|
||||||
return objects, nil
|
return objects, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *layer) getAllObjectsVersions(ctx context.Context, bkt *cache.BucketInfo, prefix, delimiter string) (map[string]*objectVersions, error) {
|
func (n *layer) getAllObjectsVersions(ctx context.Context, bkt *api.BucketInfo, prefix, delimiter string) (map[string]*objectVersions, error) {
|
||||||
ids, err := n.objectSearch(ctx, &findParams{cid: bkt.CID})
|
ids, err := n.objectSearch(ctx, &findParams{cid: bkt.CID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -526,12 +525,12 @@ func splitVersions(header string) []string {
|
||||||
return strings.Split(header, ",")
|
return strings.Split(header, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
func isSystem(obj *ObjectInfo) bool {
|
func isSystem(obj *api.ObjectInfo) bool {
|
||||||
return len(obj.Headers[objectSystemAttributeName]) > 0 ||
|
return len(obj.Headers[objectSystemAttributeName]) > 0 ||
|
||||||
len(obj.Headers[attrVersionsIgnore]) > 0
|
len(obj.Headers[attrVersionsIgnore]) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func trimAfterObjectName(startAfter string, objects []*ObjectInfo) []*ObjectInfo {
|
func trimAfterObjectName(startAfter string, objects []*api.ObjectInfo) []*api.ObjectInfo {
|
||||||
if len(objects) != 0 && objects[len(objects)-1].Name <= startAfter {
|
if len(objects) != 0 && objects[len(objects)-1].Name <= startAfter {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -544,12 +543,12 @@ func trimAfterObjectName(startAfter string, objects []*ObjectInfo) []*ObjectInfo
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func trimAfterObjectID(id string, objects []*ObjectInfo) []*ObjectInfo {
|
func trimAfterObjectID(id string, objects []*api.ObjectInfo) []*api.ObjectInfo {
|
||||||
if len(objects) != 0 && objects[len(objects)-1].id.String() == id {
|
if len(objects) != 0 && objects[len(objects)-1].ID.String() == id {
|
||||||
return []*ObjectInfo{}
|
return []*api.ObjectInfo{}
|
||||||
}
|
}
|
||||||
for i, obj := range objects {
|
for i, obj := range objects {
|
||||||
if obj.ID().String() == id {
|
if obj.ID.String() == id {
|
||||||
return objects[i+1:]
|
return objects[i+1:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -557,9 +556,9 @@ func trimAfterObjectID(id string, objects []*ObjectInfo) []*ObjectInfo {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func triageObjects(allObjects []*ObjectInfo) (prefixes []string, objects []*ObjectInfo) {
|
func triageObjects(allObjects []*api.ObjectInfo) (prefixes []string, objects []*api.ObjectInfo) {
|
||||||
for _, ov := range allObjects {
|
for _, ov := range allObjects {
|
||||||
if ov.isDir {
|
if ov.IsDir {
|
||||||
prefixes = append(prefixes, ov.Name)
|
prefixes = append(prefixes, ov.Name)
|
||||||
} else {
|
} else {
|
||||||
objects = append(objects, ov)
|
objects = append(objects, ov)
|
||||||
|
@ -569,12 +568,12 @@ func triageObjects(allObjects []*ObjectInfo) (prefixes []string, objects []*Obje
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *layer) listAllObjects(ctx context.Context, p ListObjectsParamsCommon) ([]*ObjectInfo, error) {
|
func (n *layer) listAllObjects(ctx context.Context, p ListObjectsParamsCommon) ([]*api.ObjectInfo, error) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
bkt *cache.BucketInfo
|
bkt *api.BucketInfo
|
||||||
cacheKey cacheOptions
|
cacheKey cacheOptions
|
||||||
allObjects []*ObjectInfo
|
allObjects []*api.ObjectInfo
|
||||||
)
|
)
|
||||||
|
|
||||||
if bkt, err = n.GetBucketInfo(ctx, p.Bucket); err != nil {
|
if bkt, err = n.GetBucketInfo(ctx, p.Bucket); err != nil {
|
||||||
|
@ -598,13 +597,13 @@ func (n *layer) listAllObjects(ctx context.Context, p ListObjectsParamsCommon) (
|
||||||
}
|
}
|
||||||
|
|
||||||
// putting to cache a copy of allObjects because allObjects can be modified further
|
// putting to cache a copy of allObjects because allObjects can be modified further
|
||||||
n.listsCache.Put(cacheKey, append([]*ObjectInfo(nil), allObjects...))
|
n.listsCache.Put(cacheKey, append([]*api.ObjectInfo(nil), allObjects...))
|
||||||
}
|
}
|
||||||
|
|
||||||
return allObjects, nil
|
return allObjects, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *layer) isVersioningEnabled(ctx context.Context, bktInfo *cache.BucketInfo) bool {
|
func (n *layer) isVersioningEnabled(ctx context.Context, bktInfo *api.BucketInfo) bool {
|
||||||
settings, err := n.getBucketSettings(ctx, bktInfo)
|
settings, err := n.getBucketSettings(ctx, bktInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
n.log.Warn("couldn't get versioning settings object", zap.Error(err))
|
n.log.Warn("couldn't get versioning settings object", zap.Error(err))
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
|
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
|
||||||
|
"github.com/nspcc-dev/neofs-s3-gw/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -21,8 +22,8 @@ import (
|
||||||
// ObjectsListCache provides interface for cache of ListObjectsV2 in a layer struct.
|
// ObjectsListCache provides interface for cache of ListObjectsV2 in a layer struct.
|
||||||
type (
|
type (
|
||||||
ObjectsListCache interface {
|
ObjectsListCache interface {
|
||||||
Get(key cacheOptions) []*ObjectInfo
|
Get(key cacheOptions) []*api.ObjectInfo
|
||||||
Put(key cacheOptions, objects []*ObjectInfo)
|
Put(key cacheOptions, objects []*api.ObjectInfo)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ type (
|
||||||
mtx sync.RWMutex
|
mtx sync.RWMutex
|
||||||
}
|
}
|
||||||
cacheEntry struct {
|
cacheEntry struct {
|
||||||
list []*ObjectInfo
|
list []*api.ObjectInfo
|
||||||
}
|
}
|
||||||
cacheOptions struct {
|
cacheOptions struct {
|
||||||
method string
|
method string
|
||||||
|
@ -58,7 +59,7 @@ func newListObjectsCache(lifetime time.Duration) *listObjectsCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *listObjectsCache) Get(key cacheOptions) []*ObjectInfo {
|
func (l *listObjectsCache) Get(key cacheOptions) []*api.ObjectInfo {
|
||||||
l.mtx.RLock()
|
l.mtx.RLock()
|
||||||
defer l.mtx.RUnlock()
|
defer l.mtx.RUnlock()
|
||||||
if val, ok := l.caches[key]; ok {
|
if val, ok := l.caches[key]; ok {
|
||||||
|
@ -67,7 +68,7 @@ func (l *listObjectsCache) Get(key cacheOptions) []*ObjectInfo {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *listObjectsCache) Put(key cacheOptions, objects []*ObjectInfo) {
|
func (l *listObjectsCache) Put(key cacheOptions, objects []*api.ObjectInfo) {
|
||||||
if len(objects) == 0 {
|
if len(objects) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
||||||
|
"github.com/nspcc-dev/neofs-s3-gw/api"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,11 +30,11 @@ func randSHA256Checksum(t *testing.T) (cs [sha256.Size]byte) {
|
||||||
|
|
||||||
func TestTrimAfterObjectName(t *testing.T) {
|
func TestTrimAfterObjectName(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
objects []*ObjectInfo
|
objects []*api.ObjectInfo
|
||||||
names = []string{"b", "c", "d"}
|
names = []string{"b", "c", "d"}
|
||||||
)
|
)
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
objects = append(objects, &ObjectInfo{Name: name})
|
objects = append(objects, &api.ObjectInfo{Name: name})
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("startafter before all objects", func(t *testing.T) {
|
t.Run("startafter before all objects", func(t *testing.T) {
|
||||||
|
@ -62,7 +63,7 @@ func TestTrimAfterObjectName(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("empty objects", func(t *testing.T) {
|
t.Run("empty objects", func(t *testing.T) {
|
||||||
actual := trimAfterObjectName(names[0], []*ObjectInfo{})
|
actual := trimAfterObjectName(names[0], []*api.ObjectInfo{})
|
||||||
require.Nil(t, actual)
|
require.Nil(t, actual)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -79,14 +80,14 @@ func TestTrimAfterObjectName(t *testing.T) {
|
||||||
|
|
||||||
func TestTrimAfterObjectID(t *testing.T) {
|
func TestTrimAfterObjectID(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
objects []*ObjectInfo
|
objects []*api.ObjectInfo
|
||||||
ids []*object.ID
|
ids []*object.ID
|
||||||
numberOfIDS = 3
|
numberOfIDS = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
for i := 0; i < numberOfIDS; i++ {
|
for i := 0; i < numberOfIDS; i++ {
|
||||||
id := randID(t)
|
id := randID(t)
|
||||||
objects = append(objects, &ObjectInfo{id: id})
|
objects = append(objects, &api.ObjectInfo{ID: id})
|
||||||
ids = append(ids, id)
|
ids = append(ids, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,13 +120,13 @@ func TestTrimAfterObjectID(t *testing.T) {
|
||||||
func TestObjectsListCache(t *testing.T) {
|
func TestObjectsListCache(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
cacheSize = 10
|
cacheSize = 10
|
||||||
objects []*ObjectInfo
|
objects []*api.ObjectInfo
|
||||||
userKey = "key"
|
userKey = "key"
|
||||||
)
|
)
|
||||||
|
|
||||||
for i := 0; i < cacheSize; i++ {
|
for i := 0; i < cacheSize; i++ {
|
||||||
id := randID(t)
|
id := randID(t)
|
||||||
objects = append(objects, &ObjectInfo{id: id, Name: id.String()})
|
objects = append(objects, &api.ObjectInfo{ID: id, Name: id.String()})
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Slice(objects, func(i, j int) bool {
|
sort.Slice(objects, func(i, j int) bool {
|
||||||
|
|
|
@ -8,36 +8,16 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
|
|
||||||
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
||||||
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
|
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api"
|
"github.com/nspcc-dev/neofs-s3-gw/api"
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/cache"
|
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/creds/accessbox"
|
"github.com/nspcc-dev/neofs-s3-gw/creds/accessbox"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// ObjectInfo holds S3 object data.
|
|
||||||
ObjectInfo struct {
|
|
||||||
id *object.ID
|
|
||||||
bucketID *cid.ID
|
|
||||||
isDir bool
|
|
||||||
|
|
||||||
Bucket string
|
|
||||||
Name string
|
|
||||||
Size int64
|
|
||||||
ContentType string
|
|
||||||
Created time.Time
|
|
||||||
CreationEpoch uint64
|
|
||||||
HashSum string
|
|
||||||
Owner *owner.ID
|
|
||||||
Headers map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListObjectsInfo contains common fields of data for ListObjectsV1 and ListObjectsV2.
|
// ListObjectsInfo contains common fields of data for ListObjectsV1 and ListObjectsV2.
|
||||||
ListObjectsInfo struct {
|
ListObjectsInfo struct {
|
||||||
Prefixes []string
|
Prefixes []string
|
||||||
Objects []*ObjectInfo
|
Objects []*api.ObjectInfo
|
||||||
IsTruncated bool
|
IsTruncated bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +35,7 @@ type (
|
||||||
|
|
||||||
// ObjectVersionInfo stores info about objects versions.
|
// ObjectVersionInfo stores info about objects versions.
|
||||||
ObjectVersionInfo struct {
|
ObjectVersionInfo struct {
|
||||||
Object *ObjectInfo
|
Object *api.ObjectInfo
|
||||||
IsLatest bool
|
IsLatest bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,11 +65,11 @@ func userHeaders(attrs []*object.Attribute) map[string]string {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func objInfoFromMeta(bkt *cache.BucketInfo, meta *object.Object) *ObjectInfo {
|
func objInfoFromMeta(bkt *api.BucketInfo, meta *object.Object) *api.ObjectInfo {
|
||||||
return objectInfoFromMeta(bkt, meta, "", "")
|
return objectInfoFromMeta(bkt, meta, "", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func objectInfoFromMeta(bkt *cache.BucketInfo, meta *object.Object, prefix, delimiter string) *ObjectInfo {
|
func objectInfoFromMeta(bkt *api.BucketInfo, meta *object.Object, prefix, delimiter string) *api.ObjectInfo {
|
||||||
var (
|
var (
|
||||||
isDir bool
|
isDir bool
|
||||||
size int64
|
size int64
|
||||||
|
@ -130,10 +110,10 @@ func objectInfoFromMeta(bkt *cache.BucketInfo, meta *object.Object, prefix, deli
|
||||||
size = int64(meta.PayloadSize())
|
size = int64(meta.PayloadSize())
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ObjectInfo{
|
return &api.ObjectInfo{
|
||||||
id: meta.ID(),
|
ID: meta.ID(),
|
||||||
bucketID: bkt.CID,
|
CID: bkt.CID,
|
||||||
isDir: isDir,
|
IsDir: isDir,
|
||||||
|
|
||||||
Bucket: bkt.Name,
|
Bucket: bkt.Name,
|
||||||
Name: filename,
|
Name: filename,
|
||||||
|
@ -163,27 +143,6 @@ func NameFromString(name string) (string, string) {
|
||||||
return name[ind+1:], name[:ind+1]
|
return name[ind+1:], name[:ind+1]
|
||||||
}
|
}
|
||||||
|
|
||||||
// ID returns object ID from ObjectInfo.
|
|
||||||
func (o *ObjectInfo) ID() *object.ID { return o.id }
|
|
||||||
|
|
||||||
// Version returns object version from ObjectInfo.
|
|
||||||
func (o *ObjectInfo) Version() string { return o.id.String() }
|
|
||||||
|
|
||||||
// NiceName returns object name for cache.
|
|
||||||
func (o *ObjectInfo) NiceName() string { return o.Bucket + "/" + o.Name }
|
|
||||||
|
|
||||||
// Address returns object address.
|
|
||||||
func (o *ObjectInfo) Address() *object.Address { return newAddress(o.bucketID, o.id) }
|
|
||||||
|
|
||||||
// TagsObject returns name of system object for tags.
|
|
||||||
func (o *ObjectInfo) TagsObject() string { return ".tagset." + o.Name + "." + o.Version() }
|
|
||||||
|
|
||||||
// CID returns bucket ID from ObjectInfo.
|
|
||||||
func (o *ObjectInfo) CID() *cid.ID { return o.bucketID }
|
|
||||||
|
|
||||||
// IsDir allows to check if object is a directory.
|
|
||||||
func (o *ObjectInfo) IsDir() bool { return o.isDir }
|
|
||||||
|
|
||||||
// GetBoxData extracts accessbox.Box from context.
|
// GetBoxData extracts accessbox.Box from context.
|
||||||
func GetBoxData(ctx context.Context) (*accessbox.Box, error) {
|
func GetBoxData(ctx context.Context) (*accessbox.Box, error) {
|
||||||
var boxData *accessbox.Box
|
var boxData *accessbox.Box
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
|
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
|
||||||
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
||||||
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
|
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/cache"
|
"github.com/nspcc-dev/neofs-s3-gw/api"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ var (
|
||||||
defaultTestContentType = http.DetectContentType(defaultTestPayload)
|
defaultTestContentType = http.DetectContentType(defaultTestPayload)
|
||||||
)
|
)
|
||||||
|
|
||||||
func newTestObject(oid *object.ID, bkt *cache.BucketInfo, name string) *object.Object {
|
func newTestObject(oid *object.ID, bkt *api.BucketInfo, name string) *object.Object {
|
||||||
filename := object.NewAttribute()
|
filename := object.NewAttribute()
|
||||||
filename.SetKey(object.AttributeFileName)
|
filename.SetKey(object.AttributeFileName)
|
||||||
filename.SetValue(name)
|
filename.SetValue(name)
|
||||||
|
@ -44,12 +44,12 @@ func newTestObject(oid *object.ID, bkt *cache.BucketInfo, name string) *object.O
|
||||||
return raw.Object()
|
return raw.Object()
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTestInfo(oid *object.ID, bkt *cache.BucketInfo, name string, isDir bool) *ObjectInfo {
|
func newTestInfo(oid *object.ID, bkt *api.BucketInfo, name string, isDir bool) *api.ObjectInfo {
|
||||||
info := &ObjectInfo{
|
info := &api.ObjectInfo{
|
||||||
id: oid,
|
ID: oid,
|
||||||
Name: name,
|
Name: name,
|
||||||
Bucket: bkt.Name,
|
Bucket: bkt.Name,
|
||||||
bucketID: bkt.CID,
|
CID: bkt.CID,
|
||||||
Size: defaultTestPayloadLength,
|
Size: defaultTestPayloadLength,
|
||||||
ContentType: defaultTestContentType,
|
ContentType: defaultTestContentType,
|
||||||
Created: time.Unix(defaultTestCreated.Unix(), 0),
|
Created: time.Unix(defaultTestCreated.Unix(), 0),
|
||||||
|
@ -58,7 +58,7 @@ func newTestInfo(oid *object.ID, bkt *cache.BucketInfo, name string, isDir bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
if isDir {
|
if isDir {
|
||||||
info.isDir = true
|
info.IsDir = true
|
||||||
info.Size = 0
|
info.Size = 0
|
||||||
info.ContentType = ""
|
info.ContentType = ""
|
||||||
info.Headers = nil
|
info.Headers = nil
|
||||||
|
@ -72,7 +72,7 @@ func Test_objectInfoFromMeta(t *testing.T) {
|
||||||
oid := object.NewID()
|
oid := object.NewID()
|
||||||
containerID := cid.New()
|
containerID := cid.New()
|
||||||
|
|
||||||
bkt := &cache.BucketInfo{
|
bkt := &api.BucketInfo{
|
||||||
Name: "test-container",
|
Name: "test-container",
|
||||||
CID: containerID,
|
CID: containerID,
|
||||||
Owner: uid,
|
Owner: uid,
|
||||||
|
@ -82,7 +82,7 @@ func Test_objectInfoFromMeta(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
name string
|
name string
|
||||||
prefix string
|
prefix string
|
||||||
result *ObjectInfo
|
result *api.ObjectInfo
|
||||||
object *object.Object
|
object *object.Object
|
||||||
delimiter string
|
delimiter string
|
||||||
}{
|
}{
|
||||||
|
|
|
@ -7,13 +7,13 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/cache"
|
"github.com/nspcc-dev/neofs-s3-gw/api"
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
|
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type objectVersions struct {
|
type objectVersions struct {
|
||||||
name string
|
name string
|
||||||
objects []*ObjectInfo
|
objects []*api.ObjectInfo
|
||||||
addList []string
|
addList []string
|
||||||
delList []string
|
delList []string
|
||||||
isSorted bool
|
isSorted bool
|
||||||
|
@ -34,7 +34,7 @@ func newObjectVersions(name string) *objectVersions {
|
||||||
return &objectVersions{name: name}
|
return &objectVersions{name: name}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *objectVersions) appendVersion(oi *ObjectInfo) {
|
func (v *objectVersions) appendVersion(oi *api.ObjectInfo) {
|
||||||
addVers := append(splitVersions(oi.Headers[versionsAddAttr]), oi.Version())
|
addVers := append(splitVersions(oi.Headers[versionsAddAttr]), oi.Version())
|
||||||
delVers := splitVersions(oi.Headers[versionsDelAttr])
|
delVers := splitVersions(oi.Headers[versionsDelAttr])
|
||||||
v.objects = append(v.objects, oi)
|
v.objects = append(v.objects, oi)
|
||||||
|
@ -60,7 +60,7 @@ func (v *objectVersions) sort() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *objectVersions) getLast() *ObjectInfo {
|
func (v *objectVersions) getLast() *api.ObjectInfo {
|
||||||
if len(v.objects) == 0 {
|
if len(v.objects) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -82,14 +82,14 @@ func (v *objectVersions) getLast() *ObjectInfo {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *objectVersions) getFiltered() []*ObjectInfo {
|
func (v *objectVersions) getFiltered() []*api.ObjectInfo {
|
||||||
if len(v.objects) == 0 {
|
if len(v.objects) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
v.sort()
|
v.sort()
|
||||||
existedVersions := getExistedVersions(v)
|
existedVersions := getExistedVersions(v)
|
||||||
res := make([]*ObjectInfo, 0, len(v.objects))
|
res := make([]*api.ObjectInfo, 0, len(v.objects))
|
||||||
|
|
||||||
for _, version := range v.objects {
|
for _, version := range v.objects {
|
||||||
delMark := version.Headers[versionsDeleteMarkAttr]
|
delMark := version.Headers[versionsDeleteMarkAttr]
|
||||||
|
@ -109,15 +109,15 @@ func (v *objectVersions) getDelHeader() string {
|
||||||
return strings.Join(v.delList, ",")
|
return strings.Join(v.delList, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *objectVersions) getVersion(oid *object.ID) *ObjectInfo {
|
func (v *objectVersions) getVersion(oid *object.ID) *api.ObjectInfo {
|
||||||
for _, version := range v.objects {
|
for _, version := range v.objects {
|
||||||
if version.ID() == oid {
|
if version.ID == oid {
|
||||||
return version
|
return version
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (n *layer) PutBucketVersioning(ctx context.Context, p *PutVersioningParams) (*ObjectInfo, error) {
|
func (n *layer) PutBucketVersioning(ctx context.Context, p *PutVersioningParams) (*api.ObjectInfo, error) {
|
||||||
bktInfo, err := n.GetBucketInfo(ctx, p.Bucket)
|
bktInfo, err := n.GetBucketInfo(ctx, p.Bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -171,13 +171,13 @@ func (n *layer) ListObjectVersions(ctx context.Context, p *ListObjectVersionsPar
|
||||||
}
|
}
|
||||||
sort.Strings(sortedNames)
|
sort.Strings(sortedNames)
|
||||||
|
|
||||||
allObjects = make([]*ObjectInfo, 0, p.MaxKeys)
|
allObjects = make([]*api.ObjectInfo, 0, p.MaxKeys)
|
||||||
for _, name := range sortedNames {
|
for _, name := range sortedNames {
|
||||||
allObjects = append(allObjects, versions[name].getFiltered()...)
|
allObjects = append(allObjects, versions[name].getFiltered()...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// putting to cache a copy of allObjects because allObjects can be modified further
|
// putting to cache a copy of allObjects because allObjects can be modified further
|
||||||
n.listsCache.Put(cacheKey, append([]*ObjectInfo(nil), allObjects...))
|
n.listsCache.Put(cacheKey, append([]*api.ObjectInfo(nil), allObjects...))
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, obj := range allObjects {
|
for i, obj := range allObjects {
|
||||||
|
@ -230,7 +230,7 @@ func triageVersions(objVersions []*ObjectVersionInfo) ([]*ObjectVersionInfo, []*
|
||||||
return resVersion, resDelMarkVersions
|
return resVersion, resDelMarkVersions
|
||||||
}
|
}
|
||||||
|
|
||||||
func less(ov1, ov2 *ObjectInfo) bool {
|
func less(ov1, ov2 *api.ObjectInfo) bool {
|
||||||
if ov1.CreationEpoch == ov2.CreationEpoch {
|
if ov1.CreationEpoch == ov2.CreationEpoch {
|
||||||
return ov1.Version() < ov2.Version()
|
return ov1.Version() < ov2.Version()
|
||||||
}
|
}
|
||||||
|
@ -246,7 +246,7 @@ func contains(list []string, elem string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *layer) getBucketSettings(ctx context.Context, bktInfo *cache.BucketInfo) (*BucketSettings, error) {
|
func (n *layer) getBucketSettings(ctx context.Context, bktInfo *api.BucketInfo) (*BucketSettings, error) {
|
||||||
objInfo, err := n.getSystemObject(ctx, bktInfo, bktInfo.SettingsObjectName())
|
objInfo, err := n.getSystemObject(ctx, bktInfo, bktInfo.SettingsObjectName())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -255,7 +255,7 @@ func (n *layer) getBucketSettings(ctx context.Context, bktInfo *cache.BucketInfo
|
||||||
return objectInfoToBucketSettings(objInfo), nil
|
return objectInfoToBucketSettings(objInfo), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func objectInfoToBucketSettings(info *ObjectInfo) *BucketSettings {
|
func objectInfoToBucketSettings(info *api.ObjectInfo) *BucketSettings {
|
||||||
res := &BucketSettings{}
|
res := &BucketSettings{}
|
||||||
|
|
||||||
enabled, ok := info.Headers[attrSettingsVersioningEnabled]
|
enabled, ok := info.Headers[attrSettingsVersioningEnabled]
|
||||||
|
@ -267,7 +267,7 @@ func objectInfoToBucketSettings(info *ObjectInfo) *BucketSettings {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *layer) checkVersionsExist(ctx context.Context, bkt *cache.BucketInfo, obj *VersionedObject) (*object.ID, error) {
|
func (n *layer) checkVersionsExist(ctx context.Context, bkt *api.BucketInfo, obj *VersionedObject) (*object.ID, error) {
|
||||||
id := object.NewID()
|
id := object.NewID()
|
||||||
if err := id.Parse(obj.VersionID); err != nil {
|
if err := id.Parse(obj.VersionID); err != nil {
|
||||||
return nil, errors.GetAPIError(errors.ErrInvalidVersion)
|
return nil, errors.GetAPIError(errors.ErrInvalidVersion)
|
||||||
|
|
|
@ -207,7 +207,7 @@ func (t *testPool) WaitForContainerPresence(ctx context.Context, id *cid.ID, par
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *testContext) putObject(content []byte) *ObjectInfo {
|
func (tc *testContext) putObject(content []byte) *api.ObjectInfo {
|
||||||
objInfo, err := tc.layer.PutObject(tc.ctx, &PutObjectParams{
|
objInfo, err := tc.layer.PutObject(tc.ctx, &PutObjectParams{
|
||||||
Bucket: tc.bkt,
|
Bucket: tc.bkt,
|
||||||
Object: tc.obj,
|
Object: tc.obj,
|
||||||
|
@ -220,7 +220,7 @@ func (tc *testContext) putObject(content []byte) *ObjectInfo {
|
||||||
return objInfo
|
return objInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *testContext) getObject(objectName, versionID string, needError bool) (*ObjectInfo, []byte) {
|
func (tc *testContext) getObject(objectName, versionID string, needError bool) (*api.ObjectInfo, []byte) {
|
||||||
objInfo, err := tc.layer.GetObjectInfo(tc.ctx, &HeadObjectParams{
|
objInfo, err := tc.layer.GetObjectInfo(tc.ctx, &HeadObjectParams{
|
||||||
Bucket: tc.bkt,
|
Bucket: tc.bkt,
|
||||||
Object: objectName,
|
Object: objectName,
|
||||||
|
@ -252,7 +252,7 @@ func (tc *testContext) deleteObject(objectName, versionID string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *testContext) listObjectsV1() []*ObjectInfo {
|
func (tc *testContext) listObjectsV1() []*api.ObjectInfo {
|
||||||
res, err := tc.layer.ListObjectsV1(tc.ctx, &ListObjectsParamsV1{
|
res, err := tc.layer.ListObjectsV1(tc.ctx, &ListObjectsParamsV1{
|
||||||
ListObjectsParamsCommon: ListObjectsParamsCommon{
|
ListObjectsParamsCommon: ListObjectsParamsCommon{
|
||||||
Bucket: tc.bkt,
|
Bucket: tc.bkt,
|
||||||
|
@ -263,7 +263,7 @@ func (tc *testContext) listObjectsV1() []*ObjectInfo {
|
||||||
return res.Objects
|
return res.Objects
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *testContext) listObjectsV2() []*ObjectInfo {
|
func (tc *testContext) listObjectsV2() []*api.ObjectInfo {
|
||||||
res, err := tc.layer.ListObjectsV2(tc.ctx, &ListObjectsParamsV2{
|
res, err := tc.layer.ListObjectsV2(tc.ctx, &ListObjectsParamsV2{
|
||||||
ListObjectsParamsCommon: ListObjectsParamsCommon{
|
ListObjectsParamsCommon: ListObjectsParamsCommon{
|
||||||
Bucket: tc.bkt,
|
Bucket: tc.bkt,
|
||||||
|
@ -357,12 +357,12 @@ func TestSimpleVersioning(t *testing.T) {
|
||||||
|
|
||||||
objv2, buffer2 := tc.getObject(tc.obj, "", false)
|
objv2, buffer2 := tc.getObject(tc.obj, "", false)
|
||||||
require.Equal(t, obj1Content2, buffer2)
|
require.Equal(t, obj1Content2, buffer2)
|
||||||
require.Contains(t, objv2.Headers[versionsAddAttr], obj1v1.ID().String())
|
require.Contains(t, objv2.Headers[versionsAddAttr], obj1v1.ID.String())
|
||||||
|
|
||||||
_, buffer1 := tc.getObject(tc.obj, obj1v1.ID().String(), false)
|
_, buffer1 := tc.getObject(tc.obj, obj1v1.ID.String(), false)
|
||||||
require.Equal(t, obj1Content1, buffer1)
|
require.Equal(t, obj1Content1, buffer1)
|
||||||
|
|
||||||
tc.checkListObjects(obj1v2.ID())
|
tc.checkListObjects(obj1v2.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSimpleNoVersioning(t *testing.T) {
|
func TestSimpleNoVersioning(t *testing.T) {
|
||||||
|
@ -376,10 +376,10 @@ func TestSimpleNoVersioning(t *testing.T) {
|
||||||
|
|
||||||
objv2, buffer2 := tc.getObject(tc.obj, "", false)
|
objv2, buffer2 := tc.getObject(tc.obj, "", false)
|
||||||
require.Equal(t, obj1Content2, buffer2)
|
require.Equal(t, obj1Content2, buffer2)
|
||||||
require.Contains(t, objv2.Headers[versionsDelAttr], obj1v1.ID().String())
|
require.Contains(t, objv2.Headers[versionsDelAttr], obj1v1.ID.String())
|
||||||
|
|
||||||
tc.getObject(tc.obj, obj1v1.ID().String(), true)
|
tc.getObject(tc.obj, obj1v1.ID.String(), true)
|
||||||
tc.checkListObjects(obj1v2.ID())
|
tc.checkListObjects(obj1v2.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVersioningDeleteObject(t *testing.T) {
|
func TestVersioningDeleteObject(t *testing.T) {
|
||||||
|
@ -454,7 +454,7 @@ func TestGetLastVersion(t *testing.T) {
|
||||||
|
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
versions *objectVersions
|
versions *objectVersions
|
||||||
expected *ObjectInfo
|
expected *api.ObjectInfo
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
versions: &objectVersions{},
|
versions: &objectVersions{},
|
||||||
|
@ -462,21 +462,21 @@ func TestGetLastVersion(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
versions: &objectVersions{
|
versions: &objectVersions{
|
||||||
objects: []*ObjectInfo{obj2, obj1},
|
objects: []*api.ObjectInfo{obj2, obj1},
|
||||||
addList: []string{obj1.Version(), obj2.Version()},
|
addList: []string{obj1.Version(), obj2.Version()},
|
||||||
},
|
},
|
||||||
expected: obj2,
|
expected: obj2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
versions: &objectVersions{
|
versions: &objectVersions{
|
||||||
objects: []*ObjectInfo{obj2, obj1, obj3},
|
objects: []*api.ObjectInfo{obj2, obj1, obj3},
|
||||||
addList: []string{obj1.Version(), obj2.Version(), obj3.Version()},
|
addList: []string{obj1.Version(), obj2.Version(), obj3.Version()},
|
||||||
},
|
},
|
||||||
expected: nil,
|
expected: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
versions: &objectVersions{
|
versions: &objectVersions{
|
||||||
objects: []*ObjectInfo{obj2, obj1, obj4},
|
objects: []*api.ObjectInfo{obj2, obj1, obj4},
|
||||||
addList: []string{obj1.Version(), obj2.Version(), obj4.Version()},
|
addList: []string{obj1.Version(), obj2.Version(), obj4.Version()},
|
||||||
delList: []string{obj2.Version()},
|
delList: []string{obj2.Version()},
|
||||||
},
|
},
|
||||||
|
@ -484,7 +484,7 @@ func TestGetLastVersion(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
versions: &objectVersions{
|
versions: &objectVersions{
|
||||||
objects: []*ObjectInfo{obj1, obj5},
|
objects: []*api.ObjectInfo{obj1, obj5},
|
||||||
addList: []string{obj1.Version(), obj5.Version()},
|
addList: []string{obj1.Version(), obj5.Version()},
|
||||||
delList: []string{obj1.Version()},
|
delList: []string{obj1.Version()},
|
||||||
},
|
},
|
||||||
|
@ -492,13 +492,13 @@ func TestGetLastVersion(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
versions: &objectVersions{
|
versions: &objectVersions{
|
||||||
objects: []*ObjectInfo{obj5},
|
objects: []*api.ObjectInfo{obj5},
|
||||||
},
|
},
|
||||||
expected: nil,
|
expected: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
versions: &objectVersions{
|
versions: &objectVersions{
|
||||||
objects: []*ObjectInfo{obj1, obj2, obj3, obj6},
|
objects: []*api.ObjectInfo{obj1, obj2, obj3, obj6},
|
||||||
addList: []string{obj1.Version(), obj2.Version(), obj3.Version(), obj6.Version()},
|
addList: []string{obj1.Version(), obj2.Version(), obj3.Version(), obj6.Version()},
|
||||||
delList: []string{obj3.Version()},
|
delList: []string{obj3.Version()},
|
||||||
},
|
},
|
||||||
|
@ -506,7 +506,7 @@ func TestGetLastVersion(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
versions: &objectVersions{
|
versions: &objectVersions{
|
||||||
objects: []*ObjectInfo{obj1, obj1V2},
|
objects: []*api.ObjectInfo{obj1, obj1V2},
|
||||||
addList: []string{obj1.Version(), obj1V2.Version()},
|
addList: []string{obj1.Version(), obj1V2.Version()},
|
||||||
},
|
},
|
||||||
// creation epochs are equal
|
// creation epochs are equal
|
||||||
|
@ -527,38 +527,38 @@ func TestAppendVersions(t *testing.T) {
|
||||||
|
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
versions *objectVersions
|
versions *objectVersions
|
||||||
objectToAdd *ObjectInfo
|
objectToAdd *api.ObjectInfo
|
||||||
expectedVersions *objectVersions
|
expectedVersions *objectVersions
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
versions: &objectVersions{},
|
versions: &objectVersions{},
|
||||||
objectToAdd: obj1,
|
objectToAdd: obj1,
|
||||||
expectedVersions: &objectVersions{
|
expectedVersions: &objectVersions{
|
||||||
objects: []*ObjectInfo{obj1},
|
objects: []*api.ObjectInfo{obj1},
|
||||||
addList: []string{obj1.Version()},
|
addList: []string{obj1.Version()},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
versions: &objectVersions{objects: []*ObjectInfo{obj1}},
|
versions: &objectVersions{objects: []*api.ObjectInfo{obj1}},
|
||||||
objectToAdd: obj2,
|
objectToAdd: obj2,
|
||||||
expectedVersions: &objectVersions{
|
expectedVersions: &objectVersions{
|
||||||
objects: []*ObjectInfo{obj1, obj2},
|
objects: []*api.ObjectInfo{obj1, obj2},
|
||||||
addList: []string{obj1.Version(), obj2.Version()},
|
addList: []string{obj1.Version(), obj2.Version()},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
versions: &objectVersions{objects: []*ObjectInfo{obj1, obj2}},
|
versions: &objectVersions{objects: []*api.ObjectInfo{obj1, obj2}},
|
||||||
objectToAdd: obj3,
|
objectToAdd: obj3,
|
||||||
expectedVersions: &objectVersions{
|
expectedVersions: &objectVersions{
|
||||||
objects: []*ObjectInfo{obj1, obj2, obj3},
|
objects: []*api.ObjectInfo{obj1, obj2, obj3},
|
||||||
addList: []string{obj1.Version(), obj2.Version(), obj3.Version()},
|
addList: []string{obj1.Version(), obj2.Version(), obj3.Version()},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
versions: &objectVersions{objects: []*ObjectInfo{obj1, obj2}},
|
versions: &objectVersions{objects: []*api.ObjectInfo{obj1, obj2}},
|
||||||
objectToAdd: obj4,
|
objectToAdd: obj4,
|
||||||
expectedVersions: &objectVersions{
|
expectedVersions: &objectVersions{
|
||||||
objects: []*ObjectInfo{obj1, obj2, obj4},
|
objects: []*api.ObjectInfo{obj1, obj2, obj4},
|
||||||
addList: []string{obj1.Version(), obj2.Version(), obj4.Version()},
|
addList: []string{obj1.Version(), obj2.Version(), obj4.Version()},
|
||||||
delList: []string{obj2.Version()},
|
delList: []string{obj2.Version()},
|
||||||
},
|
},
|
||||||
|
@ -569,7 +569,7 @@ func TestAppendVersions(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func joinVers(objs ...*ObjectInfo) string {
|
func joinVers(objs ...*api.ObjectInfo) string {
|
||||||
if len(objs) == 0 {
|
if len(objs) == 0 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -590,7 +590,7 @@ func getOID(id byte) *object.ID {
|
||||||
return oid
|
return oid
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTestObjectInfo(epoch uint64, oid *object.ID, addAttr, delAttr, delMarkAttr string) *ObjectInfo {
|
func getTestObjectInfo(epoch uint64, oid *object.ID, addAttr, delAttr, delMarkAttr string) *api.ObjectInfo {
|
||||||
headers := make(map[string]string)
|
headers := make(map[string]string)
|
||||||
if addAttr != "" {
|
if addAttr != "" {
|
||||||
headers[versionsAddAttr] = addAttr
|
headers[versionsAddAttr] = addAttr
|
||||||
|
@ -602,8 +602,8 @@ func getTestObjectInfo(epoch uint64, oid *object.ID, addAttr, delAttr, delMarkAt
|
||||||
headers[versionsDeleteMarkAttr] = delMarkAttr
|
headers[versionsDeleteMarkAttr] = delMarkAttr
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ObjectInfo{
|
return &api.ObjectInfo{
|
||||||
id: oid,
|
ID: oid,
|
||||||
CreationEpoch: epoch,
|
CreationEpoch: epoch,
|
||||||
Headers: headers,
|
Headers: headers,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue