restic/internal/backend/frostfs/utils.go
Aleksey Kravchenko ca638bd459 [#1] Add frostfs backend
Signed-off-by: Aleksey Kravchenko <al.kravchenko@yadro.com>
2024-12-17 11:06:26 +03:00

146 lines
3.6 KiB
Go

package frostfs
import (
"context"
"fmt"
"io"
"strconv"
"time"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
"github.com/nspcc-dev/neo-go/cli/flags"
"github.com/nspcc-dev/neo-go/pkg/wallet"
)
// BuffCloser is wrapper to load files from neofs.
type BuffCloser struct {
io.Reader
}
func (bc *BuffCloser) Close() error {
return nil
}
func createPool(ctx context.Context, acc *wallet.Account, cfg Config) (*pool.Pool, error) {
var prm pool.InitParameters
prm.SetKey(&acc.PrivateKey().PrivateKey)
prm.SetNodeDialTimeout(cfg.Timeout)
prm.SetHealthcheckTimeout(cfg.Timeout)
prm.SetClientRebalanceInterval(cfg.RebalanceInterval)
prm.AddNode(pool.NewNodeParam(1, cfg.Endpoint, 1))
p, err := pool.NewPool(prm)
if err != nil {
return nil, fmt.Errorf("create pool: %w", err)
}
if err = p.Dial(ctx); err != nil {
return nil, fmt.Errorf("dial pool: %w", err)
}
return p, nil
}
func getAccount(cfg Config) (*wallet.Account, error) {
w, err := wallet.NewWalletFromFile(cfg.Wallet)
if err != nil {
return nil, err
}
addr := w.GetChangeAddress()
if cfg.Address != "" {
addr, err = flags.ParseAddress(cfg.Address)
if err != nil {
return nil, fmt.Errorf("invalid address")
}
}
acc := w.GetAccount(addr)
err = acc.Decrypt(cfg.Password, w.Scrypt)
if err != nil {
return nil, err
}
return acc, nil
}
func getContainerID(ctx context.Context, client *pool.Pool, owner user.ID, container string) (cid.ID, error) {
var cnrID cid.ID
if err := cnrID.DecodeString(container); err != nil {
return findContainerID(ctx, client, owner, container)
}
return cnrID, nil
}
func findContainerID(ctx context.Context, client *pool.Pool, owner user.ID, containerName string) (cid.ID, error) {
prm := pool.PrmContainerList{OwnerID: owner}
containerIDs, err := client.ListContainers(ctx, prm)
if err != nil {
return cid.ID{}, fmt.Errorf("list containers: %w", err)
}
for _, cnrID := range containerIDs {
prmGet := pool.PrmContainerGet{ContainerID: cnrID}
cnr, err := client.GetContainer(ctx, prmGet)
if err != nil {
return cid.ID{}, fmt.Errorf("get container: %w", err)
}
if containerName == container.Name(cnr) {
return cnrID, nil
}
}
return cid.ID{}, fmt.Errorf("container '%s' not found", containerName)
}
func formRawObject(own *user.ID, cnrID cid.ID, name string, header map[string]string) *object.Object {
attributes := make([]object.Attribute, 0, 2+len(header))
filename := object.NewAttribute()
filename.SetKey(object.AttributeFileName)
filename.SetValue(name)
createdAt := object.NewAttribute()
createdAt.SetKey(object.AttributeTimestamp)
createdAt.SetValue(strconv.FormatInt(time.Now().UTC().Unix(), 10))
attributes = append(attributes, *filename, *createdAt)
for key, val := range header {
attr := object.NewAttribute()
attr.SetKey(key)
attr.SetValue(val)
attributes = append(attributes, *attr)
}
obj := object.New()
obj.SetOwnerID(*own)
obj.SetContainerID(cnrID)
obj.SetAttributes(attributes...)
return obj
}
func newAddress(cnrID cid.ID, objID oid.ID) oid.Address {
var addr oid.Address
addr.SetContainer(cnrID)
addr.SetObject(objID)
return addr
}
func getNameAttr(obj object.Object) string {
for _, attr := range obj.Attributes() {
if attr.Key() == object.AttributeFileName {
return attr.Value()
}
}
objID, _ := obj.ID()
return objID.EncodeToString()
}