package layer import ( "context" "encoding/hex" "fmt" "io" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" ) type PatchObjectParams struct { Object *data.ObjectInfo BktInfo *data.BucketInfo NewBytes io.Reader Range *RangeParams VersioningEnabled bool } func (n *Layer) PatchObject(ctx context.Context, p *PatchObjectParams) (*data.ExtendedObjectInfo, error) { if p.Object.Headers[AttributeDecryptedSize] != "" { return nil, fmt.Errorf("patch encrypted object") } if p.Object.Headers[MultipartObjectSize] != "" { // TODO: support multipart object patch return nil, fmt.Errorf("patch multipart object") } prmPatch := PrmObjectPatch{ Container: p.BktInfo.CID, Object: p.Object.ID, Payload: p.NewBytes, Range: p.Range, ObjectSize: p.Object.Size, } n.prepareAuthParameters(ctx, &prmPatch.PrmAuth, p.BktInfo.Owner) objID, err := n.frostFS.PatchObject(ctx, prmPatch) if err != nil { return nil, fmt.Errorf("patch object: %w", err) } obj, err := n.objectHead(ctx, p.BktInfo, objID) if err != nil { return nil, fmt.Errorf("head object: %w", err) } payloadChecksum, _ := obj.PayloadChecksum() hashSum := hex.EncodeToString(payloadChecksum.Value()) newVersion := &data.NodeVersion{ BaseNodeVersion: data.BaseNodeVersion{ OID: objID, ETag: hashSum, FilePath: p.Object.Name, Size: obj.PayloadSize(), Created: &p.Object.Created, Owner: &n.gateOwner, // TODO: Add creation epoch }, IsUnversioned: !p.VersioningEnabled, IsCombined: p.Object.Headers[MultipartObjectSize] != "", } if newVersion.ID, err = n.treeService.AddVersion(ctx, p.BktInfo, newVersion); err != nil { return nil, fmt.Errorf("couldn't add new verion to tree service: %w", err) } p.Object.ID = objID p.Object.Size = obj.PayloadSize() p.Object.MD5Sum = "" p.Object.HashSum = hashSum return &data.ExtendedObjectInfo{ ObjectInfo: p.Object, NodeVersion: newVersion, }, nil }