[#42] Fix using separate container for lifecycles
All checks were successful
/ DCO (pull_request) Successful in 1m11s
/ Builds (1.21) (pull_request) Successful in 1m23s
/ Builds (1.22) (pull_request) Successful in 1m21s
/ Vulncheck (pull_request) Successful in 4m33s
/ Lint (pull_request) Successful in 5m56s
/ Tests (1.21) (pull_request) Successful in 1m7s
/ Tests (1.22) (pull_request) Successful in 1m22s
All checks were successful
/ DCO (pull_request) Successful in 1m11s
/ Builds (1.21) (pull_request) Successful in 1m23s
/ Builds (1.22) (pull_request) Successful in 1m21s
/ Vulncheck (pull_request) Successful in 4m33s
/ Lint (pull_request) Successful in 5m56s
/ Tests (1.21) (pull_request) Successful in 1m7s
/ Tests (1.22) (pull_request) Successful in 1m22s
Signed-off-by: Marina Biryukova <m.biryukova@yadro.com>
This commit is contained in:
parent
a4a4573b10
commit
5863af4a26
8 changed files with 131 additions and 90 deletions
|
@ -165,18 +165,14 @@ func prepareHandlerContextBase(t *testing.T, cacheCfg *layer.CachesConfig) *hand
|
||||||
|
|
||||||
features := &layer.FeatureSettingsMock{}
|
features := &layer.FeatureSettingsMock{}
|
||||||
|
|
||||||
res, err := tp.CreateContainer(context.Background(), layer.PrmContainerCreate{Name: ".bucket-lifecycles"})
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
layerCfg := &layer.Config{
|
layerCfg := &layer.Config{
|
||||||
Cache: layer.NewCache(cacheCfg),
|
Cache: layer.NewCache(cacheCfg),
|
||||||
AnonKey: layer.AnonymousKey{Key: key},
|
AnonKey: layer.AnonymousKey{Key: key},
|
||||||
Resolver: testResolver,
|
Resolver: testResolver,
|
||||||
TreeService: treeMock,
|
TreeService: treeMock,
|
||||||
Features: features,
|
Features: features,
|
||||||
GateOwner: owner,
|
GateOwner: owner,
|
||||||
LifecycleCnrInfo: &data.BucketInfo{CID: res.ContainerID},
|
GateKey: key,
|
||||||
GateKey: key,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var pp netmap.PlacementPolicy
|
var pp netmap.PlacementPolicy
|
||||||
|
|
|
@ -817,5 +817,20 @@ func (n *Layer) DeleteBucket(ctx context.Context, p *DeleteBucketParams) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
n.cache.DeleteBucket(p.BktInfo)
|
n.cache.DeleteBucket(p.BktInfo)
|
||||||
return n.frostFS.DeleteContainer(ctx, p.BktInfo.CID, p.SessionToken)
|
|
||||||
|
lifecycleObj, err := n.treeService.GetBucketLifecycleConfiguration(ctx, p.BktInfo)
|
||||||
|
if err != nil {
|
||||||
|
n.reqLogger(ctx).Error(logs.GetBucketLifecycle, zap.Error(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
err = n.frostFS.DeleteContainer(ctx, p.BktInfo.CID, p.SessionToken)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("delete container: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !lifecycleObj.Container().Equals(p.BktInfo.CID) {
|
||||||
|
n.deleteLifecycleObject(ctx, p.BktInfo, lifecycleObj)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
apiErr "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
apiErr "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/errors"
|
||||||
"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/object"
|
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
@ -45,7 +44,7 @@ func (n *Layer) PutBucketLifecycleConfiguration(ctx context.Context, p *PutBucke
|
||||||
|
|
||||||
createdObj, err := n.objectPutAndHash(ctx, prm, lifecycleBkt)
|
createdObj, err := n.objectPutAndHash(ctx, prm, lifecycleBkt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("put lifecycle object: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
hashBytes, err := base64.StdEncoding.DecodeString(p.MD5Hash)
|
hashBytes, err := base64.StdEncoding.DecodeString(p.MD5Hash)
|
||||||
|
@ -54,19 +53,19 @@ func (n *Layer) PutBucketLifecycleConfiguration(ctx context.Context, p *PutBucke
|
||||||
}
|
}
|
||||||
|
|
||||||
if !bytes.Equal(hashBytes, createdObj.MD5Sum) {
|
if !bytes.Equal(hashBytes, createdObj.MD5Sum) {
|
||||||
n.deleteLifecycleObject(ctx, lifecycleBkt, createdObj.ID)
|
n.deleteLifecycleObject(ctx, p.BktInfo, newAddress(lifecycleBkt.CID, createdObj.ID))
|
||||||
|
|
||||||
return apiErr.GetAPIError(apiErr.ErrInvalidDigest)
|
return apiErr.GetAPIError(apiErr.ErrInvalidDigest)
|
||||||
}
|
}
|
||||||
|
|
||||||
objIDToDelete, err := n.treeService.PutBucketLifecycleConfiguration(ctx, p.BktInfo, createdObj.ID)
|
objToDelete, err := n.treeService.PutBucketLifecycleConfiguration(ctx, p.BktInfo, newAddress(lifecycleBkt.CID, createdObj.ID))
|
||||||
objIDToDeleteNotFound := errors.Is(err, ErrNoNodeToRemove)
|
objToDeleteNotFound := errors.Is(err, ErrNoNodeToRemove)
|
||||||
if err != nil && !objIDToDeleteNotFound {
|
if err != nil && !objToDeleteNotFound {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !objIDToDeleteNotFound {
|
if !objToDeleteNotFound {
|
||||||
n.deleteLifecycleObject(ctx, lifecycleBkt, objIDToDelete)
|
n.deleteLifecycleObject(ctx, p.BktInfo, objToDelete)
|
||||||
}
|
}
|
||||||
|
|
||||||
n.cache.PutLifecycleConfiguration(n.BearerOwner(ctx), p.BktInfo, p.LifecycleCfg)
|
n.cache.PutLifecycleConfiguration(n.BearerOwner(ctx), p.BktInfo, p.LifecycleCfg)
|
||||||
|
@ -75,18 +74,18 @@ func (n *Layer) PutBucketLifecycleConfiguration(ctx context.Context, p *PutBucke
|
||||||
}
|
}
|
||||||
|
|
||||||
// deleteLifecycleObject removes object and logs in case of error.
|
// deleteLifecycleObject removes object and logs in case of error.
|
||||||
func (n *Layer) deleteLifecycleObject(ctx context.Context, lifecycleBkt *data.BucketInfo, objID oid.ID) {
|
func (n *Layer) deleteLifecycleObject(ctx context.Context, bktInfo *data.BucketInfo, addr oid.Address) {
|
||||||
var err error
|
var prmAuth PrmAuth
|
||||||
if n.lifecycleCnrInfo == nil {
|
lifecycleBkt := bktInfo
|
||||||
err = n.objectDelete(ctx, lifecycleBkt, objID)
|
if !addr.Container().Equals(bktInfo.CID) {
|
||||||
} else {
|
lifecycleBkt = &data.BucketInfo{CID: addr.Container()}
|
||||||
err = n.objectDeleteWithAuth(ctx, lifecycleBkt, objID, PrmAuth{PrivateKey: &n.gateKey.PrivateKey})
|
prmAuth.PrivateKey = &n.gateKey.PrivateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err := n.objectDeleteWithAuth(ctx, lifecycleBkt, addr.Object(), prmAuth); err != nil {
|
||||||
n.reqLogger(ctx).Error(logs.CouldntDeleteLifecycleObject, zap.Error(err),
|
n.reqLogger(ctx).Error(logs.CouldntDeleteLifecycleObject, zap.Error(err),
|
||||||
zap.String("cid", lifecycleBkt.CID.EncodeToString()),
|
zap.String("cid", lifecycleBkt.CID.EncodeToString()),
|
||||||
zap.String("oid", objID.EncodeToString()))
|
zap.String("oid", addr.Object().EncodeToString()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,25 +95,26 @@ func (n *Layer) GetBucketLifecycleConfiguration(ctx context.Context, bktInfo *da
|
||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
objID, err := n.treeService.GetBucketLifecycleConfiguration(ctx, bktInfo)
|
addr, err := n.treeService.GetBucketLifecycleConfiguration(ctx, bktInfo)
|
||||||
objIDNotFound := errors.Is(err, ErrNodeNotFound)
|
objNotFound := errors.Is(err, ErrNodeNotFound)
|
||||||
if err != nil && !objIDNotFound {
|
if err != nil && !objNotFound {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if objIDNotFound {
|
if objNotFound {
|
||||||
return nil, fmt.Errorf("%w: %s", apiErr.GetAPIError(apiErr.ErrNoSuchLifecycleConfiguration), err.Error())
|
return nil, fmt.Errorf("%w: %s", apiErr.GetAPIError(apiErr.ErrNoSuchLifecycleConfiguration), err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
var obj *object.Object
|
var prmAuth PrmAuth
|
||||||
if n.lifecycleCnrInfo == nil {
|
lifecycleBkt := bktInfo
|
||||||
if obj, err = n.objectGet(ctx, bktInfo, objID); err != nil {
|
if !addr.Container().Equals(bktInfo.CID) {
|
||||||
return nil, err
|
lifecycleBkt = &data.BucketInfo{CID: addr.Container()}
|
||||||
}
|
prmAuth.PrivateKey = &n.gateKey.PrivateKey
|
||||||
} else {
|
}
|
||||||
if obj, err = n.objectGetWithAuth(ctx, n.lifecycleCnrInfo, objID, PrmAuth{PrivateKey: &n.gateKey.PrivateKey}); err != nil {
|
|
||||||
return nil, err
|
obj, err := n.objectGetWithAuth(ctx, lifecycleBkt, addr.Object(), prmAuth)
|
||||||
}
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("get lifecycle object: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
lifecycleCfg := &data.LifecycleConfiguration{}
|
lifecycleCfg := &data.LifecycleConfiguration{}
|
||||||
|
@ -129,20 +129,22 @@ func (n *Layer) GetBucketLifecycleConfiguration(ctx context.Context, bktInfo *da
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Layer) DeleteBucketLifecycleConfiguration(ctx context.Context, bktInfo *data.BucketInfo) error {
|
func (n *Layer) DeleteBucketLifecycleConfiguration(ctx context.Context, bktInfo *data.BucketInfo) error {
|
||||||
objID, err := n.treeService.DeleteBucketLifecycleConfiguration(ctx, bktInfo)
|
obj, err := n.treeService.DeleteBucketLifecycleConfiguration(ctx, bktInfo)
|
||||||
objIDNotFound := errors.Is(err, ErrNoNodeToRemove)
|
objNotFound := errors.Is(err, ErrNoNodeToRemove)
|
||||||
if err != nil && !objIDNotFound {
|
if err != nil && !objNotFound {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !objIDNotFound {
|
|
||||||
if n.lifecycleCnrInfo == nil {
|
if !objNotFound {
|
||||||
if err = n.objectDelete(ctx, bktInfo, objID); err != nil {
|
var prmAuth PrmAuth
|
||||||
return err
|
lifecycleBkt := bktInfo
|
||||||
}
|
if !obj.Container().Equals(bktInfo.CID) {
|
||||||
} else {
|
lifecycleBkt = &data.BucketInfo{CID: obj.Container()}
|
||||||
if err = n.objectDeleteWithAuth(ctx, n.lifecycleCnrInfo, objID, PrmAuth{PrivateKey: &n.gateKey.PrivateKey}); err != nil {
|
prmAuth.PrivateKey = &n.gateKey.PrivateKey
|
||||||
return err
|
}
|
||||||
}
|
|
||||||
|
if err = n.objectDeleteWithAuth(ctx, lifecycleBkt, obj.Object(), prmAuth); err != nil {
|
||||||
|
return fmt.Errorf("delete lifecycle object: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -392,49 +392,49 @@ LOOP:
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TreeServiceMock) PutBucketLifecycleConfiguration(_ context.Context, bktInfo *data.BucketInfo, objID oid.ID) (oid.ID, error) {
|
func (t *TreeServiceMock) PutBucketLifecycleConfiguration(_ context.Context, bktInfo *data.BucketInfo, addr oid.Address) (oid.Address, error) {
|
||||||
systemMap, ok := t.system[bktInfo.CID.EncodeToString()]
|
systemMap, ok := t.system[bktInfo.CID.EncodeToString()]
|
||||||
if !ok {
|
if !ok {
|
||||||
systemMap = make(map[string]*data.BaseNodeVersion)
|
systemMap = make(map[string]*data.BaseNodeVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
systemMap["lifecycle"] = &data.BaseNodeVersion{
|
systemMap["lifecycle"] = &data.BaseNodeVersion{
|
||||||
OID: objID,
|
OID: addr.Object(),
|
||||||
}
|
}
|
||||||
|
|
||||||
t.system[bktInfo.CID.EncodeToString()] = systemMap
|
t.system[bktInfo.CID.EncodeToString()] = systemMap
|
||||||
|
|
||||||
return oid.ID{}, ErrNoNodeToRemove
|
return oid.Address{}, ErrNoNodeToRemove
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TreeServiceMock) GetBucketLifecycleConfiguration(_ context.Context, bktInfo *data.BucketInfo) (oid.ID, error) {
|
func (t *TreeServiceMock) GetBucketLifecycleConfiguration(_ context.Context, bktInfo *data.BucketInfo) (oid.Address, error) {
|
||||||
systemMap, ok := t.system[bktInfo.CID.EncodeToString()]
|
systemMap, ok := t.system[bktInfo.CID.EncodeToString()]
|
||||||
if !ok {
|
if !ok {
|
||||||
return oid.ID{}, ErrNodeNotFound
|
return oid.Address{}, ErrNodeNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
node, ok := systemMap["lifecycle"]
|
node, ok := systemMap["lifecycle"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return oid.ID{}, ErrNodeNotFound
|
return oid.Address{}, ErrNodeNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
return node.OID, nil
|
return newAddress(bktInfo.CID, node.OID), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TreeServiceMock) DeleteBucketLifecycleConfiguration(_ context.Context, bktInfo *data.BucketInfo) (oid.ID, error) {
|
func (t *TreeServiceMock) DeleteBucketLifecycleConfiguration(_ context.Context, bktInfo *data.BucketInfo) (oid.Address, error) {
|
||||||
systemMap, ok := t.system[bktInfo.CID.EncodeToString()]
|
systemMap, ok := t.system[bktInfo.CID.EncodeToString()]
|
||||||
if !ok {
|
if !ok {
|
||||||
return oid.ID{}, ErrNoNodeToRemove
|
return oid.Address{}, ErrNoNodeToRemove
|
||||||
}
|
}
|
||||||
|
|
||||||
node, ok := systemMap["lifecycle"]
|
node, ok := systemMap["lifecycle"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return oid.ID{}, ErrNoNodeToRemove
|
return oid.Address{}, ErrNoNodeToRemove
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(systemMap, "lifecycle")
|
delete(systemMap, "lifecycle")
|
||||||
|
|
||||||
return node.OID, nil
|
return newAddress(bktInfo.CID, node.OID), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TreeServiceMock) DeleteMultipartUpload(_ context.Context, bktInfo *data.BucketInfo, multipartInfo *data.MultipartInfo) error {
|
func (t *TreeServiceMock) DeleteMultipartUpload(_ context.Context, bktInfo *data.BucketInfo, multipartInfo *data.MultipartInfo) error {
|
||||||
|
|
|
@ -63,9 +63,9 @@ type TreeService interface {
|
||||||
AddPart(ctx context.Context, bktInfo *data.BucketInfo, multipartNodeID uint64, info *data.PartInfo) (oldObjIDToDelete oid.ID, err error)
|
AddPart(ctx context.Context, bktInfo *data.BucketInfo, multipartNodeID uint64, info *data.PartInfo) (oldObjIDToDelete oid.ID, err error)
|
||||||
GetParts(ctx context.Context, bktInfo *data.BucketInfo, multipartNodeID uint64) ([]*data.PartInfo, error)
|
GetParts(ctx context.Context, bktInfo *data.BucketInfo, multipartNodeID uint64) ([]*data.PartInfo, error)
|
||||||
|
|
||||||
PutBucketLifecycleConfiguration(ctx context.Context, bktInfo *data.BucketInfo, objID oid.ID) (oldObjIDToDelete oid.ID, err error)
|
PutBucketLifecycleConfiguration(ctx context.Context, bktInfo *data.BucketInfo, addr oid.Address) (oldObjToDelete oid.Address, err error)
|
||||||
GetBucketLifecycleConfiguration(ctx context.Context, bktInfo *data.BucketInfo) (oid.ID, error)
|
GetBucketLifecycleConfiguration(ctx context.Context, bktInfo *data.BucketInfo) (oid.Address, error)
|
||||||
DeleteBucketLifecycleConfiguration(ctx context.Context, bktInfo *data.BucketInfo) (oid.ID, error)
|
DeleteBucketLifecycleConfiguration(ctx context.Context, bktInfo *data.BucketInfo) (oid.Address, error)
|
||||||
|
|
||||||
// Compound methods for optimizations
|
// Compound methods for optimizations
|
||||||
|
|
||||||
|
|
|
@ -168,13 +168,12 @@ func prepareContext(t *testing.T, cachesConfig ...*CachesConfig) *testContext {
|
||||||
user.IDFromKey(&owner, key.PrivateKey.PublicKey)
|
user.IDFromKey(&owner, key.PrivateKey.PublicKey)
|
||||||
|
|
||||||
layerCfg := &Config{
|
layerCfg := &Config{
|
||||||
Cache: NewCache(config),
|
Cache: NewCache(config),
|
||||||
AnonKey: AnonymousKey{Key: key},
|
AnonKey: AnonymousKey{Key: key},
|
||||||
TreeService: NewTreeService(),
|
TreeService: NewTreeService(),
|
||||||
Features: &FeatureSettingsMock{},
|
Features: &FeatureSettingsMock{},
|
||||||
GateOwner: owner,
|
GateOwner: owner,
|
||||||
LifecycleCnrInfo: &data.BucketInfo{CID: res.ContainerID},
|
GateKey: key,
|
||||||
GateKey: key,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &testContext{
|
return &testContext{
|
||||||
|
|
|
@ -153,4 +153,5 @@ const (
|
||||||
CouldntCacheLifecycleConfiguration = "couldn't cache lifecycle configuration"
|
CouldntCacheLifecycleConfiguration = "couldn't cache lifecycle configuration"
|
||||||
CouldNotFetchLifecycleContainerInfo = "couldn't fetch lifecycle container info"
|
CouldNotFetchLifecycleContainerInfo = "couldn't fetch lifecycle container info"
|
||||||
FoundSeveralBucketLifecycleNodes = "found several bucket lifecycle nodes, latest be used"
|
FoundSeveralBucketLifecycleNodes = "found several bucket lifecycle nodes, latest be used"
|
||||||
|
GetBucketLifecycle = "get bucket lifecycle"
|
||||||
)
|
)
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
|
||||||
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
@ -84,6 +85,7 @@ const (
|
||||||
ownerKeyKV = "ownerKey"
|
ownerKeyKV = "ownerKey"
|
||||||
lockConfigurationKV = "LockConfiguration"
|
lockConfigurationKV = "LockConfiguration"
|
||||||
oidKV = "OID"
|
oidKV = "OID"
|
||||||
|
cidKV = "CID"
|
||||||
|
|
||||||
isCombinedKV = "IsCombined"
|
isCombinedKV = "IsCombined"
|
||||||
isUnversionedKV = "IsUnversioned"
|
isUnversionedKV = "IsUnversioned"
|
||||||
|
@ -1374,22 +1376,23 @@ func (c *Tree) GetParts(ctx context.Context, bktInfo *data.BucketInfo, multipart
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Tree) PutBucketLifecycleConfiguration(ctx context.Context, bktInfo *data.BucketInfo, objID oid.ID) (oid.ID, error) {
|
func (c *Tree) PutBucketLifecycleConfiguration(ctx context.Context, bktInfo *data.BucketInfo, addr oid.Address) (oid.Address, error) {
|
||||||
node, err := c.getSystemNode(ctx, bktInfo, []string{bucketLifecycleFilename})
|
node, err := c.getSystemNode(ctx, bktInfo, []string{bucketLifecycleFilename})
|
||||||
isErrNotFound := errors.Is(err, layer.ErrNodeNotFound)
|
isErrNotFound := errors.Is(err, layer.ErrNodeNotFound)
|
||||||
if err != nil && !isErrNotFound {
|
if err != nil && !isErrNotFound {
|
||||||
return oid.ID{}, fmt.Errorf("couldn't get node: %w", err)
|
return oid.Address{}, fmt.Errorf("couldn't get node: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
meta := make(map[string]string)
|
meta := make(map[string]string)
|
||||||
meta[FileNameKey] = bucketLifecycleFilename
|
meta[FileNameKey] = bucketLifecycleFilename
|
||||||
meta[oidKV] = objID.EncodeToString()
|
meta[oidKV] = addr.Object().EncodeToString()
|
||||||
|
meta[cidKV] = addr.Container().EncodeToString()
|
||||||
|
|
||||||
if isErrNotFound {
|
if isErrNotFound {
|
||||||
if _, err = c.service.AddNode(ctx, bktInfo, systemTree, 0, meta); err != nil {
|
if _, err = c.service.AddNode(ctx, bktInfo, systemTree, 0, meta); err != nil {
|
||||||
return oid.ID{}, err
|
return oid.Address{}, err
|
||||||
}
|
}
|
||||||
return oid.ID{}, layer.ErrNoNodeToRemove
|
return oid.Address{}, layer.ErrNoNodeToRemove
|
||||||
}
|
}
|
||||||
|
|
||||||
ind := node.GetLatestNodeIndex()
|
ind := node.GetLatestNodeIndex()
|
||||||
|
@ -1397,22 +1400,27 @@ func (c *Tree) PutBucketLifecycleConfiguration(ctx context.Context, bktInfo *dat
|
||||||
c.reqLogger(ctx).Warn(logs.FoundSeveralBucketLifecycleNodes)
|
c.reqLogger(ctx).Warn(logs.FoundSeveralBucketLifecycleNodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
return node.ObjID, c.service.MoveNode(ctx, bktInfo, systemTree, node.ID[ind], 0, meta)
|
prevAddr, err := getAddress(node)
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Tree) GetBucketLifecycleConfiguration(ctx context.Context, bktInfo *data.BucketInfo) (oid.ID, error) {
|
|
||||||
node, err := c.getSystemNode(ctx, bktInfo, []string{bucketLifecycleFilename})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return oid.ID{}, err
|
return oid.Address{}, fmt.Errorf("couldn't get prev lifecycle object addr: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return node.ObjID, nil
|
return prevAddr, c.service.MoveNode(ctx, bktInfo, systemTree, node.ID[ind], 0, meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Tree) DeleteBucketLifecycleConfiguration(ctx context.Context, bktInfo *data.BucketInfo) (oid.ID, error) {
|
func (c *Tree) GetBucketLifecycleConfiguration(ctx context.Context, bktInfo *data.BucketInfo) (oid.Address, error) {
|
||||||
|
node, err := c.getSystemNode(ctx, bktInfo, []string{bucketLifecycleFilename})
|
||||||
|
if err != nil {
|
||||||
|
return oid.Address{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return getAddress(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Tree) DeleteBucketLifecycleConfiguration(ctx context.Context, bktInfo *data.BucketInfo) (oid.Address, error) {
|
||||||
node, err := c.getSystemNode(ctx, bktInfo, []string{bucketLifecycleFilename})
|
node, err := c.getSystemNode(ctx, bktInfo, []string{bucketLifecycleFilename})
|
||||||
if err != nil && !errors.Is(err, layer.ErrNodeNotFound) {
|
if err != nil && !errors.Is(err, layer.ErrNodeNotFound) {
|
||||||
return oid.ID{}, err
|
return oid.Address{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if node != nil {
|
if node != nil {
|
||||||
|
@ -1421,10 +1429,30 @@ func (c *Tree) DeleteBucketLifecycleConfiguration(ctx context.Context, bktInfo *
|
||||||
c.reqLogger(ctx).Warn(logs.FoundSeveralBucketLifecycleNodes)
|
c.reqLogger(ctx).Warn(logs.FoundSeveralBucketLifecycleNodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
return node.ObjID, c.service.RemoveNode(ctx, bktInfo, systemTree, node.ID[ind])
|
addr, err := getAddress(node)
|
||||||
|
if err != nil {
|
||||||
|
return oid.Address{}, fmt.Errorf("couldn't get lifecycle object addr: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return addr, c.service.RemoveNode(ctx, bktInfo, systemTree, node.ID[ind])
|
||||||
}
|
}
|
||||||
|
|
||||||
return oid.ID{}, layer.ErrNoNodeToRemove
|
return oid.Address{}, layer.ErrNoNodeToRemove
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAddress(node *treeNode) (oid.Address, error) {
|
||||||
|
var addr oid.Address
|
||||||
|
addr.SetObject(node.ObjID)
|
||||||
|
|
||||||
|
if cidStr, ok := node.Get(cidKV); ok {
|
||||||
|
var cnrID cid.ID
|
||||||
|
if err := cnrID.DecodeString(cidStr); err != nil {
|
||||||
|
return oid.Address{}, fmt.Errorf("couldn't decode cid: %w", err)
|
||||||
|
}
|
||||||
|
addr.SetContainer(cnrID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return addr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Tree) DeleteMultipartUpload(ctx context.Context, bktInfo *data.BucketInfo, multipartInfo *data.MultipartInfo) error {
|
func (c *Tree) DeleteMultipartUpload(ctx context.Context, bktInfo *data.BucketInfo, multipartInfo *data.MultipartInfo) error {
|
||||||
|
|
Loading…
Reference in a new issue