2022-02-15 05:36:47 +00:00
|
|
|
package client
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2022-02-21 12:02:23 +00:00
|
|
|
"crypto/ecdsa"
|
2022-08-25 10:51:46 +00:00
|
|
|
"fmt"
|
2022-02-15 05:36:47 +00:00
|
|
|
|
2023-03-07 11:20:03 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
|
|
|
v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
|
|
|
v2refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
|
|
|
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"
|
|
|
|
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
|
|
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
|
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
2022-02-15 05:36:47 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// PrmObjectDelete groups parameters of ObjectDelete operation.
|
|
|
|
type PrmObjectDelete struct {
|
2023-09-04 10:23:10 +00:00
|
|
|
XHeaders []string
|
2022-02-15 05:36:47 +00:00
|
|
|
|
2023-09-04 10:23:10 +00:00
|
|
|
BearerToken *bearer.Token
|
2022-02-15 05:36:47 +00:00
|
|
|
|
2023-09-04 10:23:10 +00:00
|
|
|
Session *session.Object
|
2022-02-21 12:02:23 +00:00
|
|
|
|
2023-09-04 10:23:10 +00:00
|
|
|
ContainerID *cid.ID
|
2022-02-15 05:36:47 +00:00
|
|
|
|
2023-09-04 10:23:10 +00:00
|
|
|
ObjectID *oid.ID
|
2022-04-07 16:09:15 +00:00
|
|
|
|
2023-09-04 10:23:10 +00:00
|
|
|
Key *ecdsa.PrivateKey
|
2022-02-15 05:36:47 +00:00
|
|
|
}
|
|
|
|
|
2022-02-21 12:02:23 +00:00
|
|
|
// UseKey specifies private key to sign the requests.
|
|
|
|
// If key is not provided, then Client default key is used.
|
2022-03-03 11:04:53 +00:00
|
|
|
//
|
2023-09-04 10:23:10 +00:00
|
|
|
// Deprecated: Use PrmObjectDelete.Key instead.
|
|
|
|
func (prm *PrmObjectDelete) UseKey(key ecdsa.PrivateKey) {
|
|
|
|
prm.Key = &key
|
2022-03-03 11:04:53 +00:00
|
|
|
}
|
|
|
|
|
2022-02-15 05:36:47 +00:00
|
|
|
// ResObjectDelete groups resulting values of ObjectDelete operation.
|
|
|
|
type ResObjectDelete struct {
|
|
|
|
statusRes
|
|
|
|
|
2022-08-05 07:56:49 +00:00
|
|
|
tomb oid.ID
|
2022-02-15 05:36:47 +00:00
|
|
|
}
|
|
|
|
|
2022-08-05 07:56:49 +00:00
|
|
|
// Tombstone returns identifier of the created tombstone object.
|
|
|
|
func (x ResObjectDelete) Tombstone() oid.ID {
|
|
|
|
return x.tomb
|
2022-02-15 05:36:47 +00:00
|
|
|
}
|
|
|
|
|
2023-09-04 10:23:10 +00:00
|
|
|
func (prm *PrmObjectDelete) buildRequest(c *Client) (*v2object.DeleteRequest, error) {
|
|
|
|
if prm.ContainerID == nil {
|
|
|
|
return nil, errorMissingContainer
|
|
|
|
}
|
|
|
|
|
|
|
|
if prm.ObjectID == nil {
|
|
|
|
return nil, errorMissingObject
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(prm.XHeaders)%2 != 0 {
|
|
|
|
return nil, errorInvalidXHeaders
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
|
|
|
addr := new(v2refs.Address)
|
|
|
|
|
|
|
|
cnrV2 := new(v2refs.ContainerID)
|
|
|
|
prm.ContainerID.WriteToV2(cnrV2)
|
|
|
|
addr.SetContainerID(cnrV2)
|
|
|
|
|
|
|
|
objV2 := new(v2refs.ObjectID)
|
|
|
|
prm.ObjectID.WriteToV2(objV2)
|
|
|
|
addr.SetObjectID(objV2)
|
|
|
|
|
|
|
|
body := new(v2object.DeleteRequestBody)
|
|
|
|
body.SetAddress(addr)
|
|
|
|
|
|
|
|
req := new(v2object.DeleteRequest)
|
|
|
|
req.SetBody(body)
|
|
|
|
c.prepareRequest(req, meta)
|
|
|
|
|
|
|
|
return req, nil
|
|
|
|
}
|
|
|
|
|
2022-12-29 10:46:18 +00:00
|
|
|
// ObjectDelete marks an object for deletion from the container using FrostFS API protocol.
|
2022-02-15 05:36:47 +00:00
|
|
|
// As a marker, a special unit called a tombstone is placed in the container.
|
|
|
|
// It confirms the user's intent to delete the object, and is itself a container object.
|
|
|
|
// Explicit deletion is done asynchronously, and is generally not guaranteed.
|
|
|
|
//
|
|
|
|
// Returns a list of checksums in raw form: the format of hashes and their number
|
|
|
|
// is left for the caller to check. Client preserves the order of the server's response.
|
|
|
|
//
|
|
|
|
// 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 `error`,
|
2023-09-15 15:52:08 +00:00
|
|
|
// If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful
|
2023-09-12 15:57:04 +00:00
|
|
|
// FrostFS status codes are included in the returned result structure,
|
|
|
|
// otherwise, are also returned as `error`.
|
2022-02-15 05:36:47 +00:00
|
|
|
//
|
2023-02-27 07:53:27 +00:00
|
|
|
// Returns an error if parameters are set incorrectly (see PrmObjectDelete docs).
|
2022-02-15 05:36:47 +00:00
|
|
|
// Context is required and must not be nil. It is used for network communication.
|
|
|
|
//
|
|
|
|
// Return statuses:
|
2022-02-28 10:56:46 +00:00
|
|
|
// - global (see Client docs)
|
|
|
|
// - *apistatus.ContainerNotFound;
|
|
|
|
// - *apistatus.ObjectAccessDenied;
|
|
|
|
// - *apistatus.ObjectLocked;
|
|
|
|
// - *apistatus.SessionTokenExpired.
|
2022-02-15 05:36:47 +00:00
|
|
|
func (c *Client) ObjectDelete(ctx context.Context, prm PrmObjectDelete) (*ResObjectDelete, error) {
|
2023-09-04 10:23:10 +00:00
|
|
|
req, err := prm.buildRequest(c)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2022-02-15 05:36:47 +00:00
|
|
|
}
|
|
|
|
|
2023-11-13 12:18:07 +00:00
|
|
|
key := c.prm.Key
|
2023-09-04 10:23:10 +00:00
|
|
|
if prm.Key != nil {
|
|
|
|
key = *prm.Key
|
2022-08-25 10:51:46 +00:00
|
|
|
}
|
|
|
|
|
2023-09-04 10:23:10 +00:00
|
|
|
err = signature.SignServiceMessage(&key, req)
|
2022-08-25 10:51:46 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("sign request: %w", err)
|
|
|
|
}
|
|
|
|
|
2023-09-04 10:23:10 +00:00
|
|
|
resp, err := rpcapi.DeleteObject(&c.c, req, client.WithContext(ctx))
|
2022-08-25 10:51:46 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2022-02-21 12:02:23 +00:00
|
|
|
}
|
|
|
|
|
2022-08-25 10:51:46 +00:00
|
|
|
var res ResObjectDelete
|
|
|
|
res.st, err = c.processResponse(resp)
|
2024-09-24 13:31:56 +00:00
|
|
|
if err != nil || !apistatus.IsSuccessful(res.st) {
|
|
|
|
return &res, err
|
2022-08-25 10:51:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const fieldTombstone = "tombstone"
|
|
|
|
|
|
|
|
idTombV2 := resp.GetBody().GetTombstone().GetObjectID()
|
|
|
|
if idTombV2 == nil {
|
|
|
|
return nil, newErrMissingResponseField(fieldTombstone)
|
2022-02-15 05:36:47 +00:00
|
|
|
}
|
|
|
|
|
2022-08-25 10:51:46 +00:00
|
|
|
err = res.tomb.ReadFromV2(*idTombV2)
|
|
|
|
if err != nil {
|
|
|
|
return nil, newErrInvalidResponseField(fieldTombstone, err)
|
2022-02-15 05:36:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return &res, nil
|
|
|
|
}
|