git.frostfs.info/TrueCloudLab/frostfs-sdk-go@v0.0.0-20241022124111-5361f0ecebd3/client/object_put_single.go (about)

     1  package client
     2  
     3  import (
     4  	"context"
     5  	"crypto/ecdsa"
     6  	"fmt"
     7  
     8  	"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
     9  	v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
    10  	rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
    11  	"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
    12  	v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
    13  	"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
    14  	"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
    15  	"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
    16  	"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
    17  )
    18  
    19  // PrmObjectPutSingle groups parameters of PutSingle operation.
    20  type PrmObjectPutSingle struct {
    21  	XHeaders []string
    22  
    23  	BearerToken *bearer.Token
    24  
    25  	Session *session.Object
    26  
    27  	Local bool
    28  
    29  	CopiesNumber []uint32
    30  
    31  	Object *object.Object
    32  
    33  	Key *ecdsa.PrivateKey
    34  }
    35  
    36  // SetCopiesNumber sets ordered list of minimal required object copies numbers
    37  // per placement vector. List's length MUST equal container's placement vector number,
    38  // otherwise request will fail.
    39  //
    40  // Deprecated: Use PrmObjectPutSingle.CopiesNumber instead.
    41  func (prm *PrmObjectPutSingle) SetCopiesNumber(v []uint32) {
    42  	prm.CopiesNumber = v
    43  }
    44  
    45  // UseKey specifies private key to sign the requests.
    46  // If key is not provided, then Client default key is used.
    47  //
    48  // Deprecated: Use PrmObjectPutSingle.Key instead.
    49  func (prm *PrmObjectPutSingle) UseKey(key *ecdsa.PrivateKey) {
    50  	prm.Key = key
    51  }
    52  
    53  // WithBearerToken attaches bearer token to be used for the operation.
    54  // Should be called once before any writing steps.
    55  //
    56  // Deprecated: Use PrmObjectPutSingle.BearerToken instead.
    57  func (prm *PrmObjectPutSingle) WithBearerToken(t bearer.Token) {
    58  	prm.BearerToken = &t
    59  }
    60  
    61  // WithinSession specifies session within which object should be stored.
    62  // Should be called once before any writing steps.
    63  //
    64  // Deprecated: Use PrmObjectPutSingle.Session instead.
    65  func (prm *PrmObjectPutSingle) WithinSession(t session.Object) {
    66  	prm.Session = &t
    67  }
    68  
    69  // ExecuteLocal tells the server to execute the operation locally.
    70  //
    71  // Deprecated: Use PrmObjectPutSingle.Local instead.
    72  func (prm *PrmObjectPutSingle) ExecuteLocal() {
    73  	prm.Local = true
    74  }
    75  
    76  // WithXHeaders specifies list of extended headers (string key-value pairs)
    77  // to be attached to the request. Must have an even length.
    78  //
    79  // Slice must not be mutated until the operation completes.
    80  //
    81  // Deprecated: Use PrmObjectPutSingle.XHeaders instead.
    82  func (prm *PrmObjectPutSingle) WithXHeaders(hs ...string) {
    83  	prm.XHeaders = hs
    84  }
    85  
    86  // SetObject specifies prepared object to put.
    87  //
    88  // Deprecated: Use PrmObjectPutSingle.Object instead.
    89  func (prm *PrmObjectPutSingle) SetObject(o *v2object.Object) {
    90  	prm.Object = object.NewFromV2(o)
    91  }
    92  
    93  // ResObjectPutSingle groups resulting values of PutSingle operation.
    94  type ResObjectPutSingle struct {
    95  	statusRes
    96  
    97  	epoch uint64
    98  }
    99  
   100  // Epoch returns creation epoch of the saved object.
   101  func (r *ResObjectPutSingle) Epoch() uint64 {
   102  	return r.epoch
   103  }
   104  
   105  func (prm *PrmObjectPutSingle) buildRequest(c *Client) (*v2object.PutSingleRequest, error) {
   106  	if len(prm.XHeaders)%2 != 0 {
   107  		return nil, errorInvalidXHeaders
   108  	}
   109  
   110  	body := new(v2object.PutSingleRequestBody)
   111  	body.SetCopiesNumber(prm.CopiesNumber)
   112  	body.SetObject(prm.Object.ToV2())
   113  
   114  	meta := new(v2session.RequestMetaHeader)
   115  	writeXHeadersToMeta(prm.XHeaders, meta)
   116  
   117  	if prm.BearerToken != nil {
   118  		v2BearerToken := new(acl.BearerToken)
   119  		prm.BearerToken.WriteToV2(v2BearerToken)
   120  		meta.SetBearerToken(v2BearerToken)
   121  	}
   122  
   123  	if prm.Session != nil {
   124  		v2SessionToken := new(v2session.Token)
   125  		prm.Session.WriteToV2(v2SessionToken)
   126  		meta.SetSessionToken(v2SessionToken)
   127  	}
   128  
   129  	if prm.Local {
   130  		meta.SetTTL(1)
   131  	}
   132  
   133  	req := &v2object.PutSingleRequest{}
   134  	req.SetBody(body)
   135  	c.prepareRequest(req, meta)
   136  
   137  	return req, nil
   138  }
   139  
   140  // ObjectPutSingle writes prepared object to FrostFS.
   141  // Object must have payload, also containerID, objectID, ownerID, payload hash, payload length of an object must be set.
   142  // Exactly one return value is non-nil. By default, server status is returned in res structure.
   143  // Any client's internal or transport errors are returned as Go built-in error.
   144  // If Client is tuned to resolve FrostFS API statuses, then FrostFS failures
   145  // codes are returned as error.
   146  func (c *Client) ObjectPutSingle(ctx context.Context, prm PrmObjectPutSingle) (*ResObjectPutSingle, error) {
   147  	req, err := prm.buildRequest(c)
   148  	if err != nil {
   149  		return nil, err
   150  	}
   151  
   152  	key := &c.prm.Key
   153  	if prm.Key != nil {
   154  		key = prm.Key
   155  	}
   156  
   157  	err = signature.SignServiceMessage(key, req)
   158  	if err != nil {
   159  		return nil, fmt.Errorf("sign request: %w", err)
   160  	}
   161  
   162  	resp, err := rpcapi.PutSingleObject(&c.c, req, client.WithContext(ctx))
   163  	if err != nil {
   164  		return nil, err
   165  	}
   166  
   167  	var res ResObjectPutSingle
   168  	res.st, err = c.processResponse(resp)
   169  	if err != nil {
   170  		return &res, err
   171  	}
   172  	res.epoch = resp.GetMetaHeader().GetEpoch()
   173  
   174  	return &res, nil
   175  }