git.frostfs.info/TrueCloudLab/frostfs-sdk-go@v0.0.0-20241022124111-5361f0ecebd3/client/object_delete.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  	v2refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
    11  	rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
    12  	"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
    13  	v2session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
    14  	"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
    15  	"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
    16  	apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
    17  	cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
    18  	oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
    19  	"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
    20  )
    21  
    22  // PrmObjectDelete groups parameters of ObjectDelete operation.
    23  type PrmObjectDelete struct {
    24  	XHeaders []string
    25  
    26  	BearerToken *bearer.Token
    27  
    28  	Session *session.Object
    29  
    30  	ContainerID *cid.ID
    31  
    32  	ObjectID *oid.ID
    33  
    34  	Key *ecdsa.PrivateKey
    35  }
    36  
    37  // UseKey specifies private key to sign the requests.
    38  // If key is not provided, then Client default key is used.
    39  //
    40  // Deprecated: Use PrmObjectDelete.Key instead.
    41  func (prm *PrmObjectDelete) UseKey(key ecdsa.PrivateKey) {
    42  	prm.Key = &key
    43  }
    44  
    45  // ResObjectDelete groups resulting values of ObjectDelete operation.
    46  type ResObjectDelete struct {
    47  	statusRes
    48  
    49  	tomb oid.ID
    50  }
    51  
    52  // Tombstone returns identifier of the created tombstone object.
    53  func (x ResObjectDelete) Tombstone() oid.ID {
    54  	return x.tomb
    55  }
    56  
    57  func (prm *PrmObjectDelete) buildRequest(c *Client) (*v2object.DeleteRequest, error) {
    58  	if prm.ContainerID == nil {
    59  		return nil, errorMissingContainer
    60  	}
    61  
    62  	if prm.ObjectID == nil {
    63  		return nil, errorMissingObject
    64  	}
    65  
    66  	if len(prm.XHeaders)%2 != 0 {
    67  		return nil, errorInvalidXHeaders
    68  	}
    69  
    70  	meta := new(v2session.RequestMetaHeader)
    71  	writeXHeadersToMeta(prm.XHeaders, meta)
    72  
    73  	if prm.BearerToken != nil {
    74  		v2BearerToken := new(acl.BearerToken)
    75  		prm.BearerToken.WriteToV2(v2BearerToken)
    76  		meta.SetBearerToken(v2BearerToken)
    77  	}
    78  
    79  	if prm.Session != nil {
    80  		v2SessionToken := new(v2session.Token)
    81  		prm.Session.WriteToV2(v2SessionToken)
    82  		meta.SetSessionToken(v2SessionToken)
    83  	}
    84  
    85  	addr := new(v2refs.Address)
    86  
    87  	cnrV2 := new(v2refs.ContainerID)
    88  	prm.ContainerID.WriteToV2(cnrV2)
    89  	addr.SetContainerID(cnrV2)
    90  
    91  	objV2 := new(v2refs.ObjectID)
    92  	prm.ObjectID.WriteToV2(objV2)
    93  	addr.SetObjectID(objV2)
    94  
    95  	body := new(v2object.DeleteRequestBody)
    96  	body.SetAddress(addr)
    97  
    98  	req := new(v2object.DeleteRequest)
    99  	req.SetBody(body)
   100  	c.prepareRequest(req, meta)
   101  
   102  	return req, nil
   103  }
   104  
   105  // ObjectDelete marks an object for deletion from the container using FrostFS API protocol.
   106  // As a marker, a special unit called a tombstone is placed in the container.
   107  // It confirms the user's intent to delete the object, and is itself a container object.
   108  // Explicit deletion is done asynchronously, and is generally not guaranteed.
   109  //
   110  // Returns a list of checksums in raw form: the format of hashes and their number
   111  // is left for the caller to check. Client preserves the order of the server's response.
   112  //
   113  // Exactly one return value is non-nil. By default, server status is returned in res structure.
   114  // Any client's internal or transport errors are returned as `error`,
   115  // If PrmInit.DisableFrostFSFailuresResolution has been called, unsuccessful
   116  // FrostFS status codes are included in the returned result structure,
   117  // otherwise, are also returned as `error`.
   118  //
   119  // Returns an error if parameters are set incorrectly (see PrmObjectDelete docs).
   120  // Context is required and must not be nil. It is used for network communication.
   121  //
   122  // Return statuses:
   123  //   - global (see Client docs)
   124  //   - *apistatus.ContainerNotFound;
   125  //   - *apistatus.ObjectAccessDenied;
   126  //   - *apistatus.ObjectLocked;
   127  //   - *apistatus.SessionTokenExpired.
   128  func (c *Client) ObjectDelete(ctx context.Context, prm PrmObjectDelete) (*ResObjectDelete, error) {
   129  	req, err := prm.buildRequest(c)
   130  	if err != nil {
   131  		return nil, err
   132  	}
   133  
   134  	key := c.prm.Key
   135  	if prm.Key != nil {
   136  		key = *prm.Key
   137  	}
   138  
   139  	err = signature.SignServiceMessage(&key, req)
   140  	if err != nil {
   141  		return nil, fmt.Errorf("sign request: %w", err)
   142  	}
   143  
   144  	resp, err := rpcapi.DeleteObject(&c.c, req, client.WithContext(ctx))
   145  	if err != nil {
   146  		return nil, err
   147  	}
   148  
   149  	var res ResObjectDelete
   150  	res.st, err = c.processResponse(resp)
   151  	if err != nil || !apistatus.IsSuccessful(res.st) {
   152  		return &res, err
   153  	}
   154  
   155  	const fieldTombstone = "tombstone"
   156  
   157  	idTombV2 := resp.GetBody().GetTombstone().GetObjectID()
   158  	if idTombV2 == nil {
   159  		return nil, newErrMissingResponseField(fieldTombstone)
   160  	}
   161  
   162  	err = res.tomb.ReadFromV2(*idTombV2)
   163  	if err != nil {
   164  		return nil, newErrInvalidResponseField(fieldTombstone, err)
   165  	}
   166  
   167  	return &res, nil
   168  }