frostfs-sdk-go/client/object_put_single.go
Pavel Pogodaev 6ce73790ea [#276] Merge repo with frostfs-api-go
Signed-off-by: Pavel Pogodaev <p.pogodaev@yadro.com>
2024-10-22 14:05:12 +00:00

175 lines
4.8 KiB
Go

package client
import (
"context"
"crypto/ecdsa"
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl"
v2object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object"
rpcapi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client"
v2session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
)
// PrmObjectPutSingle groups parameters of PutSingle operation.
type PrmObjectPutSingle struct {
XHeaders []string
BearerToken *bearer.Token
Session *session.Object
Local bool
CopiesNumber []uint32
Object *object.Object
Key *ecdsa.PrivateKey
}
// SetCopiesNumber sets ordered list of minimal required object copies numbers
// per placement vector. List's length MUST equal container's placement vector number,
// otherwise request will fail.
//
// Deprecated: Use PrmObjectPutSingle.CopiesNumber instead.
func (prm *PrmObjectPutSingle) SetCopiesNumber(v []uint32) {
prm.CopiesNumber = v
}
// UseKey specifies private key to sign the requests.
// If key is not provided, then Client default key is used.
//
// Deprecated: Use PrmObjectPutSingle.Key instead.
func (prm *PrmObjectPutSingle) UseKey(key *ecdsa.PrivateKey) {
prm.Key = key
}
// WithBearerToken attaches bearer token to be used for the operation.
// Should be called once before any writing steps.
//
// Deprecated: Use PrmObjectPutSingle.BearerToken instead.
func (prm *PrmObjectPutSingle) WithBearerToken(t bearer.Token) {
prm.BearerToken = &t
}
// WithinSession specifies session within which object should be stored.
// Should be called once before any writing steps.
//
// Deprecated: Use PrmObjectPutSingle.Session instead.
func (prm *PrmObjectPutSingle) WithinSession(t session.Object) {
prm.Session = &t
}
// ExecuteLocal tells the server to execute the operation locally.
//
// Deprecated: Use PrmObjectPutSingle.Local instead.
func (prm *PrmObjectPutSingle) ExecuteLocal() {
prm.Local = true
}
// WithXHeaders specifies list of extended headers (string key-value pairs)
// to be attached to the request. Must have an even length.
//
// Slice must not be mutated until the operation completes.
//
// Deprecated: Use PrmObjectPutSingle.XHeaders instead.
func (prm *PrmObjectPutSingle) WithXHeaders(hs ...string) {
prm.XHeaders = hs
}
// SetObject specifies prepared object to put.
//
// Deprecated: Use PrmObjectPutSingle.Object instead.
func (prm *PrmObjectPutSingle) SetObject(o *v2object.Object) {
prm.Object = object.NewFromV2(o)
}
// ResObjectPutSingle groups resulting values of PutSingle operation.
type ResObjectPutSingle struct {
statusRes
epoch uint64
}
// Epoch returns creation epoch of the saved object.
func (r *ResObjectPutSingle) Epoch() uint64 {
return r.epoch
}
func (prm *PrmObjectPutSingle) buildRequest(c *Client) (*v2object.PutSingleRequest, error) {
if len(prm.XHeaders)%2 != 0 {
return nil, errorInvalidXHeaders
}
body := new(v2object.PutSingleRequestBody)
body.SetCopiesNumber(prm.CopiesNumber)
body.SetObject(prm.Object.ToV2())
meta := new(v2session.RequestMetaHeader)
writeXHeadersToMeta(prm.XHeaders, meta)
if prm.BearerToken != nil {
v2BearerToken := new(acl.BearerToken)
prm.BearerToken.WriteToV2(v2BearerToken)
meta.SetBearerToken(v2BearerToken)
}
if prm.Session != nil {
v2SessionToken := new(v2session.Token)
prm.Session.WriteToV2(v2SessionToken)
meta.SetSessionToken(v2SessionToken)
}
if prm.Local {
meta.SetTTL(1)
}
req := &v2object.PutSingleRequest{}
req.SetBody(body)
c.prepareRequest(req, meta)
return req, nil
}
// ObjectPutSingle writes prepared object to FrostFS.
// Object must have payload, also containerID, objectID, ownerID, payload hash, payload length of an object must be set.
// Exactly one return value is non-nil. By default, server status is returned in res structure.
// Any client's internal or transport errors are returned as Go built-in error.
// If Client is tuned to resolve FrostFS API statuses, then FrostFS failures
// codes are returned as error.
func (c *Client) ObjectPutSingle(ctx context.Context, prm PrmObjectPutSingle) (*ResObjectPutSingle, error) {
req, err := prm.buildRequest(c)
if err != nil {
return nil, err
}
key := &c.prm.Key
if prm.Key != nil {
key = prm.Key
}
err = signature.SignServiceMessage(key, req)
if err != nil {
return nil, fmt.Errorf("sign request: %w", err)
}
resp, err := rpcapi.PutSingleObject(&c.c, req, client.WithContext(ctx))
if err != nil {
return nil, err
}
var res ResObjectPutSingle
res.st, err = c.processResponse(resp)
if err != nil {
return &res, err
}
res.epoch = resp.GetMetaHeader().GetEpoch()
return &res, nil
}