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 }