2023-07-06 14:06:17 +00:00
|
|
|
package client
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"crypto/ecdsa"
|
|
|
|
"fmt"
|
|
|
|
|
2024-10-07 14:20:25 +00:00
|
|
|
"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"
|
2023-07-06 14:06:17 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
2023-09-07 08:53:49 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
2023-07-06 14:06:17 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
|
|
|
)
|
|
|
|
|
|
|
|
// PrmObjectPutSingle groups parameters of PutSingle operation.
|
|
|
|
type PrmObjectPutSingle struct {
|
2023-09-07 08:53:49 +00:00
|
|
|
XHeaders []string
|
|
|
|
|
|
|
|
BearerToken *bearer.Token
|
|
|
|
|
|
|
|
Session *session.Object
|
|
|
|
|
|
|
|
Local bool
|
|
|
|
|
|
|
|
CopiesNumber []uint32
|
|
|
|
|
|
|
|
Object *object.Object
|
|
|
|
|
|
|
|
Key *ecdsa.PrivateKey
|
2023-07-06 14:06:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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.
|
2023-09-07 08:53:49 +00:00
|
|
|
//
|
|
|
|
// Deprecated: Use PrmObjectPutSingle.CopiesNumber instead.
|
|
|
|
func (prm *PrmObjectPutSingle) SetCopiesNumber(v []uint32) {
|
|
|
|
prm.CopiesNumber = v
|
2023-07-06 14:06:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// UseKey specifies private key to sign the requests.
|
|
|
|
// If key is not provided, then Client default key is used.
|
2023-09-07 08:53:49 +00:00
|
|
|
//
|
|
|
|
// Deprecated: Use PrmObjectPutSingle.Key instead.
|
|
|
|
func (prm *PrmObjectPutSingle) UseKey(key *ecdsa.PrivateKey) {
|
|
|
|
prm.Key = key
|
2023-07-06 14:06:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// WithBearerToken attaches bearer token to be used for the operation.
|
|
|
|
// Should be called once before any writing steps.
|
2023-09-07 08:53:49 +00:00
|
|
|
//
|
|
|
|
// Deprecated: Use PrmObjectPutSingle.BearerToken instead.
|
|
|
|
func (prm *PrmObjectPutSingle) WithBearerToken(t bearer.Token) {
|
|
|
|
prm.BearerToken = &t
|
2023-07-06 14:06:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// WithinSession specifies session within which object should be stored.
|
|
|
|
// Should be called once before any writing steps.
|
2023-09-07 08:53:49 +00:00
|
|
|
//
|
|
|
|
// Deprecated: Use PrmObjectPutSingle.Session instead.
|
|
|
|
func (prm *PrmObjectPutSingle) WithinSession(t session.Object) {
|
|
|
|
prm.Session = &t
|
2023-07-06 14:06:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ExecuteLocal tells the server to execute the operation locally.
|
2023-09-07 08:53:49 +00:00
|
|
|
//
|
|
|
|
// Deprecated: Use PrmObjectPutSingle.Local instead.
|
|
|
|
func (prm *PrmObjectPutSingle) ExecuteLocal() {
|
|
|
|
prm.Local = true
|
2023-07-06 14:06:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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.
|
2023-09-07 08:53:49 +00:00
|
|
|
//
|
|
|
|
// Deprecated: Use PrmObjectPutSingle.XHeaders instead.
|
|
|
|
func (prm *PrmObjectPutSingle) WithXHeaders(hs ...string) {
|
|
|
|
prm.XHeaders = hs
|
2023-07-06 14:06:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// SetObject specifies prepared object to put.
|
2023-09-07 08:53:49 +00:00
|
|
|
//
|
|
|
|
// Deprecated: Use PrmObjectPutSingle.Object instead.
|
|
|
|
func (prm *PrmObjectPutSingle) SetObject(o *v2object.Object) {
|
|
|
|
prm.Object = object.NewFromV2(o)
|
2023-07-06 14:06:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ResObjectPutSingle groups resulting values of PutSingle operation.
|
|
|
|
type ResObjectPutSingle struct {
|
|
|
|
statusRes
|
2024-07-12 11:35:01 +00:00
|
|
|
|
|
|
|
epoch uint64
|
|
|
|
}
|
|
|
|
|
|
|
|
// Epoch returns creation epoch of the saved object.
|
|
|
|
func (r *ResObjectPutSingle) Epoch() uint64 {
|
|
|
|
return r.epoch
|
2023-07-06 14:06:17 +00:00
|
|
|
}
|
|
|
|
|
2023-09-07 08:53:49 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2023-07-06 14:06:17 +00:00
|
|
|
// 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) {
|
2023-09-07 08:53:49 +00:00
|
|
|
req, err := prm.buildRequest(c)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2023-07-06 14:06:17 +00:00
|
|
|
|
2023-11-13 12:18:07 +00:00
|
|
|
key := &c.prm.Key
|
2023-09-07 08:53:49 +00:00
|
|
|
if prm.Key != nil {
|
|
|
|
key = prm.Key
|
2023-07-06 14:06:17 +00:00
|
|
|
}
|
|
|
|
|
2023-09-07 08:53:49 +00:00
|
|
|
err = signature.SignServiceMessage(key, req)
|
2023-07-06 14:06:17 +00:00
|
|
|
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 {
|
2024-09-24 13:31:56 +00:00
|
|
|
return &res, err
|
2023-07-06 14:06:17 +00:00
|
|
|
}
|
2024-07-12 11:35:01 +00:00
|
|
|
res.epoch = resp.GetMetaHeader().GetEpoch()
|
2023-07-06 14:06:17 +00:00
|
|
|
|
|
|
|
return &res, nil
|
|
|
|
}
|