From 7a4a4d441dd8e39f1a8f4d712d743012693b0056 Mon Sep 17 00:00:00 2001 From: Nikita Zinkevich Date: Wed, 6 Nov 2024 12:34:48 +0300 Subject: [PATCH] [#100] s3: Add a flag for permanent versioned object deletion Signed-off-by: Nikita Zinkevich --- internal/s3/client.go | 70 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/internal/s3/client.go b/internal/s3/client.go index b4824b0..638b6d6 100644 --- a/internal/s3/client.go +++ b/internal/s3/client.go @@ -142,6 +142,76 @@ func (c *Client) Get(bucket, key string) GetResponse { return GetResponse{Success: true} } +func (c *Client) DeleteObjectVersion(bucket, key, version string) DeleteResponse { + var toDelete []types.ObjectIdentifier + + if version != "" { + toDelete = append(toDelete, types.ObjectIdentifier{ + Key: aws.String(key), + VersionId: aws.String(version), + }) + } else { + v, err := c.cli.GetBucketVersioning(c.vu.Context(), &s3.GetBucketVersioningInput{ + Bucket: aws.String(bucket), + }) + if err != nil { + stats.Report(c.vu, objDeleteFails, 1) + return DeleteResponse{Success: false, Error: err.Error()} + } + if v.Status == "" { + // delete non-versioned object + return c.Delete(bucket, key) + } + + versions, err := c.cli.ListObjectVersions(c.vu.Context(), &s3.ListObjectVersionsInput{ + Bucket: aws.String(bucket), + Prefix: aws.String(key), + }) + if err != nil { + stats.Report(c.vu, objDeleteFails, 1) + return DeleteResponse{Success: false, Error: err.Error()} + } + toDelete = append(toDelete, filterObjectVersions(versions, key)...) + } + if len(toDelete) != 0 { + _, err := c.cli.DeleteObjects(c.vu.Context(), &s3.DeleteObjectsInput{ + Bucket: aws.String(bucket), + Delete: &types.Delete{ + Objects: toDelete, + Quiet: true, + }, + }) + if err != nil { + stats.Report(c.vu, objDeleteFails, 1) + return DeleteResponse{Success: false, Error: err.Error()} + } + } + + return DeleteResponse{Success: true} +} + +func filterObjectVersions(versions *s3.ListObjectVersionsOutput, key string) []types.ObjectIdentifier { + var result []types.ObjectIdentifier + + for _, v := range versions.Versions { + if *v.Key == key { + result = append(result, types.ObjectIdentifier{ + Key: v.Key, + VersionId: v.VersionId, + }) + } + } + for _, marker := range versions.DeleteMarkers { + if *marker.Key == key { + result = append(result, types.ObjectIdentifier{ + Key: marker.Key, + VersionId: marker.VersionId, + }) + } + } + return result +} + func get( c *s3.Client, bucket string,