package client import ( "context" "crypto/ecdsa" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" ) // PrmObjectPutSingle groups parameters of PutSingle operation. type PrmObjectPutSingle struct { copyNum []uint32 meta v2session.RequestMetaHeader object *v2object.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. func (x *PrmObjectPutSingle) SetCopiesNumber(v []uint32) { x.copyNum = v } // UseKey specifies private key to sign the requests. // If key is not provided, then Client default key is used. func (x *PrmObjectPutSingle) UseKey(key *ecdsa.PrivateKey) { x.key = key } // WithBearerToken attaches bearer token to be used for the operation. // Should be called once before any writing steps. func (x *PrmObjectPutSingle) WithBearerToken(t bearer.Token) { v2token := &acl.BearerToken{} t.WriteToV2(v2token) x.meta.SetBearerToken(v2token) } // WithinSession specifies session within which object should be stored. // Should be called once before any writing steps. func (x *PrmObjectPutSingle) WithinSession(t session.Object) { tv2 := &v2session.Token{} t.WriteToV2(tv2) x.meta.SetSessionToken(tv2) } // ExecuteLocal tells the server to execute the operation locally. func (x *PrmObjectPutSingle) ExecuteLocal() { x.meta.SetTTL(1) } // 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. func (x *PrmObjectPutSingle) WithXHeaders(hs ...string) { writeXHeadersToMeta(hs, &x.meta) } // SetObject specifies prepared object to put. func (x *PrmObjectPutSingle) SetObject(o *v2object.Object) { x.object = o } // ResObjectPutSingle groups resulting values of PutSingle operation. type ResObjectPutSingle struct { statusRes } // 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) { body := &v2object.PutSingleRequestBody{} body.SetCopiesNumber(prm.copyNum) body.SetObject(prm.object) req := &v2object.PutSingleRequest{} req.SetBody(body) c.prepareRequest(req, &prm.meta) 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 nil, err } return &res, nil }