Nikita Zinkevich
b9e44c603d
All checks were successful
/ DCO (pull_request) Successful in 2m27s
/ Vulncheck (pull_request) Successful in 3m24s
/ Lint (pull_request) Successful in 3m30s
/ Tests (pull_request) Successful in 3m38s
/ Builds (pull_request) Successful in 2m52s
/ Vulncheck (push) Successful in 3m36s
/ Builds (push) Successful in 2m3s
/ Lint (push) Successful in 4m54s
/ Tests (push) Successful in 2m11s
Add tree service's GetBucketSettings to use them to check for protocol to use (S3 or native). Also add mock implementations for this and GetLatestVersion methods. Signed-off-by: Nikita Zinkevich <n.zinkevich@yadro.com>
163 lines
4 KiB
Go
163 lines
4 KiB
Go
package frostfs
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/data"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/tokens"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/tree"
|
|
apitree "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/tree"
|
|
treepool "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool/tree"
|
|
)
|
|
|
|
type GetNodeByPathResponseInfoWrapper struct {
|
|
response *apitree.GetNodeByPathResponseInfo
|
|
}
|
|
|
|
func (n GetNodeByPathResponseInfoWrapper) GetNodeID() []uint64 {
|
|
return []uint64{n.response.GetNodeID()}
|
|
}
|
|
|
|
func (n GetNodeByPathResponseInfoWrapper) GetParentID() []uint64 {
|
|
return []uint64{n.response.GetParentID()}
|
|
}
|
|
|
|
func (n GetNodeByPathResponseInfoWrapper) GetTimestamp() []uint64 {
|
|
return []uint64{n.response.GetTimestamp()}
|
|
}
|
|
|
|
func (n GetNodeByPathResponseInfoWrapper) GetMeta() []tree.Meta {
|
|
res := make([]tree.Meta, len(n.response.GetMeta()))
|
|
for i, value := range n.response.GetMeta() {
|
|
res[i] = value
|
|
}
|
|
return res
|
|
}
|
|
|
|
type PoolWrapper struct {
|
|
p *treepool.Pool
|
|
}
|
|
|
|
func NewPoolWrapper(p *treepool.Pool) *PoolWrapper {
|
|
return &PoolWrapper{p: p}
|
|
}
|
|
|
|
func (w *PoolWrapper) GetNodes(ctx context.Context, prm *tree.GetNodesParams) ([]tree.NodeResponse, error) {
|
|
poolPrm := treepool.GetNodesParams{
|
|
CID: prm.CnrID,
|
|
TreeID: prm.TreeID,
|
|
Path: prm.Path,
|
|
Meta: prm.Meta,
|
|
PathAttribute: tree.FileNameKey,
|
|
LatestOnly: prm.LatestOnly,
|
|
AllAttrs: prm.AllAttrs,
|
|
BearerToken: getBearer(ctx),
|
|
}
|
|
|
|
nodes, err := w.p.GetNodes(ctx, poolPrm)
|
|
if err != nil {
|
|
return nil, handleError(err)
|
|
}
|
|
|
|
res := make([]tree.NodeResponse, len(nodes))
|
|
for i, info := range nodes {
|
|
res[i] = GetNodeByPathResponseInfoWrapper{info}
|
|
}
|
|
|
|
return res, nil
|
|
}
|
|
|
|
func getBearer(ctx context.Context) []byte {
|
|
token, err := tokens.LoadBearerToken(ctx)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
return token.Marshal()
|
|
}
|
|
|
|
func handleError(err error) error {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
if errors.Is(err, treepool.ErrNodeNotFound) {
|
|
return fmt.Errorf("%w: %s", tree.ErrNodeNotFound, err.Error())
|
|
}
|
|
if errors.Is(err, treepool.ErrNodeAccessDenied) {
|
|
return fmt.Errorf("%w: %s", tree.ErrNodeAccessDenied, err.Error())
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
func (w *PoolWrapper) GetSubTree(ctx context.Context, bktInfo *data.BucketInfo, treeID string, rootID []uint64, depth uint32, sort bool) ([]tree.NodeResponse, error) {
|
|
order := treepool.NoneOrder
|
|
if sort {
|
|
order = treepool.AscendingOrder
|
|
}
|
|
poolPrm := treepool.GetSubTreeParams{
|
|
CID: bktInfo.CID,
|
|
TreeID: treeID,
|
|
RootID: rootID,
|
|
Depth: depth,
|
|
BearerToken: getBearer(ctx),
|
|
Order: order,
|
|
}
|
|
if len(rootID) == 1 && rootID[0] == 0 {
|
|
// storage node interprets 'nil' value as []uint64{0}
|
|
// gate wants to send 'nil' value instead of []uint64{0}, because
|
|
// it provides compatibility with previous tree service api where
|
|
// single uint64(0) value is dropped from signature
|
|
poolPrm.RootID = nil
|
|
}
|
|
|
|
subTreeReader, err := w.p.GetSubTree(ctx, poolPrm)
|
|
if err != nil {
|
|
return nil, handleError(err)
|
|
}
|
|
|
|
var subtree []tree.NodeResponse
|
|
|
|
node, err := subTreeReader.Next()
|
|
for err == nil {
|
|
subtree = append(subtree, GetSubTreeResponseBodyWrapper{node})
|
|
node, err = subTreeReader.Next()
|
|
}
|
|
if err != io.EOF {
|
|
return nil, handleError(err)
|
|
}
|
|
|
|
return subtree, nil
|
|
}
|
|
|
|
type GetSubTreeResponseBodyWrapper struct {
|
|
response *apitree.GetSubTreeResponseBody
|
|
}
|
|
|
|
func (n GetSubTreeResponseBodyWrapper) GetNodeID() []uint64 {
|
|
return n.response.GetNodeID()
|
|
}
|
|
|
|
func (n GetSubTreeResponseBodyWrapper) GetParentID() []uint64 {
|
|
resp := n.response.GetParentID()
|
|
if resp == nil {
|
|
// storage sends nil that should be interpreted as []uint64{0}
|
|
// due to protobuf compatibility, see 'GetSubTree' function
|
|
return []uint64{0}
|
|
}
|
|
return resp
|
|
}
|
|
|
|
func (n GetSubTreeResponseBodyWrapper) GetTimestamp() []uint64 {
|
|
return n.response.GetTimestamp()
|
|
}
|
|
|
|
func (n GetSubTreeResponseBodyWrapper) GetMeta() []tree.Meta {
|
|
res := make([]tree.Meta, len(n.response.GetMeta()))
|
|
for i, value := range n.response.GetMeta() {
|
|
res[i] = value
|
|
}
|
|
return res
|
|
}
|