[#429] Add tree service for cors

Signed-off-by: Angira Kekteeva <kira@nspcc.ru>
This commit is contained in:
Angira Kekteeva 2022-05-12 05:33:03 +03:00 committed by Alex Vanin
parent 7520952792
commit 8eff857e41
4 changed files with 86 additions and 4 deletions

View file

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"context" "context"
"encoding/xml" "encoding/xml"
errorsStd "errors"
"fmt" "fmt"
"io" "io"
@ -35,6 +36,11 @@ func (n *layer) PutBucketCORS(ctx context.Context, p *PutCORSParams) error {
return err return err
} }
ids, nodeIds, err := n.treeService.GetBucketCORS(ctx, &p.BktInfo.CID, false)
if err != nil && !errorsStd.Is(err, ErrNodeNotFound) {
return err
}
s := &PutSystemObjectParams{ s := &PutSystemObjectParams{
BktInfo: p.BktInfo, BktInfo: p.BktInfo,
ObjName: p.BktInfo.CORSObjectName(), ObjName: p.BktInfo.CORSObjectName(),
@ -44,10 +50,27 @@ func (n *layer) PutBucketCORS(ctx context.Context, p *PutCORSParams) error {
Size: int64(buf.Len()), Size: int64(buf.Len()),
} }
if _, err := n.putSystemObjectIntoNeoFS(ctx, s); err != nil { obj, err := n.putSystemObjectIntoNeoFS(ctx, s)
if err != nil {
return fmt.Errorf("put system object: %w", err) return fmt.Errorf("put system object: %w", err)
} }
if err = n.treeService.PutBucketCORS(ctx, &p.BktInfo.CID, &obj.ID); err != nil {
return err
}
for i := 0; i < len(ids); i++ {
if err = n.objectDelete(ctx, p.BktInfo, *ids[i]); err != nil {
n.log.Error("couldn't delete cors object", zap.Error(err),
zap.String("cnrID", p.BktInfo.CID.EncodeToString()),
zap.String("bucket name", p.BktInfo.Name),
zap.String("objID", ids[i].EncodeToString()))
}
if err = n.treeService.DeleteBucketCORS(ctx, &p.BktInfo.CID, nodeIds[i]); err != nil {
return err
}
}
if err := n.systemCache.PutCORS(systemObjectKey(p.BktInfo, s.ObjName), cors); err != nil { if err := n.systemCache.PutCORS(systemObjectKey(p.BktInfo, s.ObjName), cors); err != nil {
n.log.Error("couldn't cache system object", zap.Error(err)) n.log.Error("couldn't cache system object", zap.Error(err))
} }
@ -58,7 +81,7 @@ func (n *layer) PutBucketCORS(ctx context.Context, p *PutCORSParams) error {
func (n *layer) GetBucketCORS(ctx context.Context, bktInfo *data.BucketInfo) (*data.CORSConfiguration, error) { func (n *layer) GetBucketCORS(ctx context.Context, bktInfo *data.BucketInfo) (*data.CORSConfiguration, error) {
cors, err := n.getCORS(ctx, bktInfo, bktInfo.CORSObjectName()) cors, err := n.getCORS(ctx, bktInfo, bktInfo.CORSObjectName())
if err != nil { if err != nil {
if errors.IsS3Error(err, errors.ErrNoSuchKey) { if errorsStd.Is(err, ErrNodeNotFound) {
return nil, errors.GetAPIError(errors.ErrNoSuchCORSConfiguration) return nil, errors.GetAPIError(errors.ErrNoSuchCORSConfiguration)
} }
return nil, err return nil, err
@ -68,7 +91,23 @@ func (n *layer) GetBucketCORS(ctx context.Context, bktInfo *data.BucketInfo) (*d
} }
func (n *layer) DeleteBucketCORS(ctx context.Context, bktInfo *data.BucketInfo) error { func (n *layer) DeleteBucketCORS(ctx context.Context, bktInfo *data.BucketInfo) error {
return n.DeleteSystemObject(ctx, bktInfo, bktInfo.CORSObjectName()) ids, nodeIds, err := n.treeService.GetBucketCORS(ctx, &bktInfo.CID, false)
if err != nil && !errorsStd.Is(err, ErrNodeNotFound) {
return err
}
for i := 0; i < len(ids); i++ {
if err = n.objectDelete(ctx, bktInfo, *ids[i]); err != nil {
return err
}
if err = n.treeService.DeleteBucketCORS(ctx, &bktInfo.CID, nodeIds[i]); err != nil {
return err
}
}
n.systemCache.Delete(systemObjectKey(bktInfo, bktInfo.CORSObjectName()))
return nil
} }
func checkCORS(cors *data.CORSConfiguration) error { func checkCORS(cors *data.CORSConfiguration) error {

View file

@ -181,8 +181,15 @@ func (n *layer) getCORS(ctx context.Context, bkt *data.BucketInfo, sysName strin
if cors := n.systemCache.GetCORS(systemObjectKey(bkt, sysName)); cors != nil { if cors := n.systemCache.GetCORS(systemObjectKey(bkt, sysName)); cors != nil {
return cors, nil return cors, nil
} }
ids, _, err := n.treeService.GetBucketCORS(ctx, &bkt.CID, true)
if err != nil {
return nil, err
}
if len(ids) == 0 {
return nil, errors.GetAPIError(errors.ErrNoSuchCORSConfiguration)
}
obj, err := n.getSystemObjectFromNeoFS(ctx, bkt, sysName) obj, err := n.objectGet(ctx, bkt, *ids[0])
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -22,6 +22,10 @@ type TreeService interface {
GetNotificationConfigurationNodes(ctx context.Context, cnrID *cid.ID, latestOnly bool) ([]*oid.ID, []uint64, error) GetNotificationConfigurationNodes(ctx context.Context, cnrID *cid.ID, latestOnly bool) ([]*oid.ID, []uint64, error)
PutNotificationConfigurationNode(ctx context.Context, cnrID *cid.ID, objID *oid.ID) error PutNotificationConfigurationNode(ctx context.Context, cnrID *cid.ID, objID *oid.ID) error
DeleteNotificationConfigurationNode(ctx context.Context, cnrID *cid.ID, nodeID uint64) error DeleteNotificationConfigurationNode(ctx context.Context, cnrID *cid.ID, nodeID uint64) error
GetBucketCORS(ctx context.Context, cnrID *cid.ID, latestOnly bool) ([]*oid.ID, []uint64, error)
PutBucketCORS(ctx context.Context, cnrID *cid.ID, objID *oid.ID) error
DeleteBucketCORS(ctx context.Context, cnrID *cid.ID, nodeID uint64) error
} }
// ErrNodeNotFound is returned from Tree service in case of not found error. // ErrNodeNotFound is returned from Tree service in case of not found error.

View file

@ -39,8 +39,10 @@ const (
settingsFileName = "bucket-settings" settingsFileName = "bucket-settings"
notifConfFileName = "bucket-notifications" notifConfFileName = "bucket-notifications"
corsFilename = "bucket-cors"
notifTreeID = "notifications" notifTreeID = "notifications"
corsTreeID = "cors"
) )
// NewTreeClient creates instance of TreeClient using provided address and create grpc connection. // NewTreeClient creates instance of TreeClient using provided address and create grpc connection.
@ -159,6 +161,36 @@ func (c *TreeClient) DeleteNotificationConfigurationNode(ctx context.Context, cn
return c.removeNode(ctx, cnrID, notifTreeID, nodeID) return c.removeNode(ctx, cnrID, notifTreeID, nodeID)
} }
func (c *TreeClient) GetBucketCORS(ctx context.Context, cnrID *cid.ID, latestOnly bool) ([]*oid.ID, []uint64, error) {
nodes, err := c.getSystemNodesWithOID(ctx, cnrID, corsTreeID, corsFilename, []string{}, latestOnly)
if err != nil {
return nil, nil, err
}
ids := make([]*oid.ID, 0, len(nodes))
nodeIds := make([]uint64, 0, len(nodes))
for _, n := range nodes {
ids = append(ids, n.ObjID)
nodeIds = append(nodeIds, n.ID)
}
return ids, nodeIds, nil
}
func (c *TreeClient) PutBucketCORS(ctx context.Context, cnrID *cid.ID, objID *oid.ID) error {
meta := make(map[string]string)
meta[systemNameKV] = corsFilename
meta[oidKv] = objID.EncodeToString()
_, err := c.addNode(ctx, cnrID, corsTreeID, 0, meta)
return err
}
func (c *TreeClient) DeleteBucketCORS(ctx context.Context, cnrID *cid.ID, nodeID uint64) error {
return c.removeNode(ctx, cnrID, corsTreeID, nodeID)
}
func (c *TreeClient) Close() error { func (c *TreeClient) Close() error {
if c.conn != nil { if c.conn != nil {
return c.conn.Close() return c.conn.Close()