diff --git a/s3api/controllers/object-delete.go b/s3api/controllers/object-delete.go index 59d56705..bac9d456 100644 --- a/s3api/controllers/object-delete.go +++ b/s3api/controllers/object-delete.go @@ -72,6 +72,9 @@ func (c S3ApiController) DeleteObjectTagging(ctx *fiber.Ctx) (*Response, error) err = c.be.DeleteObjectTagging(ctx.Context(), bucket, key, versionId) return &Response{ + Headers: map[string]*string{ + "x-amz-version-id": &versionId, + }, MetaOpts: &MetaOptions{ Status: http.StatusNoContent, BucketOwner: parsedAcl.Owner, diff --git a/s3api/controllers/object-delete_test.go b/s3api/controllers/object-delete_test.go index 935bb42b..512954f6 100644 --- a/s3api/controllers/object-delete_test.go +++ b/s3api/controllers/object-delete_test.go @@ -20,12 +20,14 @@ import ( "testing" "github.com/aws/aws-sdk-go-v2/service/s3" + "github.com/oklog/ulid/v2" "github.com/versity/versitygw/s3api/utils" "github.com/versity/versitygw/s3err" "github.com/versity/versitygw/s3event" ) func TestS3ApiController_DeleteObjectTagging(t *testing.T) { + versionId := ulid.Make().String() tests := []struct { name string input testInput @@ -65,11 +67,17 @@ func TestS3ApiController_DeleteObjectTagging(t *testing.T) { { name: "backend returns error", input: testInput{ + queries: map[string]string{ + "versionId": versionId, + }, locals: defaultLocals, beErr: s3err.GetAPIError(s3err.ErrInvalidRequest), }, output: testOutput{ response: &Response{ + Headers: map[string]*string{ + "x-amz-version-id": &versionId, + }, MetaOpts: &MetaOptions{ BucketOwner: "root", Status: http.StatusNoContent, @@ -83,9 +91,15 @@ func TestS3ApiController_DeleteObjectTagging(t *testing.T) { name: "successful response", input: testInput{ locals: defaultLocals, + queries: map[string]string{ + "versionId": versionId, + }, }, output: testOutput{ response: &Response{ + Headers: map[string]*string{ + "x-amz-version-id": &versionId, + }, MetaOpts: &MetaOptions{ BucketOwner: "root", Status: http.StatusNoContent, diff --git a/s3api/controllers/object-get.go b/s3api/controllers/object-get.go index f8d938f7..b54a82fd 100644 --- a/s3api/controllers/object-get.go +++ b/s3api/controllers/object-get.go @@ -93,6 +93,9 @@ func (c S3ApiController) GetObjectTagging(ctx *fiber.Ctx) (*Response, error) { return &Response{ Data: tags, + Headers: map[string]*string{ + "x-amz-version-id": &versionId, + }, MetaOpts: &MetaOptions{ BucketOwner: parsedAcl.Owner, }, diff --git a/s3api/controllers/object-get_test.go b/s3api/controllers/object-get_test.go index 229be064..2c45a03f 100644 --- a/s3api/controllers/object-get_test.go +++ b/s3api/controllers/object-get_test.go @@ -26,6 +26,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/aws/aws-sdk-go-v2/service/s3/types" + "github.com/oklog/ulid/v2" "github.com/stretchr/testify/assert" "github.com/versity/versitygw/s3api/utils" "github.com/versity/versitygw/s3err" @@ -33,6 +34,7 @@ import ( ) func TestS3ApiController_GetObjectTagging(t *testing.T) { + versionId := ulid.Make().String() tests := []struct { name string input testInput @@ -88,6 +90,9 @@ func TestS3ApiController_GetObjectTagging(t *testing.T) { { name: "successful response", input: testInput{ + queries: map[string]string{ + "versionId": versionId, + }, locals: defaultLocals, beRes: map[string]string{ "key": "val", @@ -95,6 +100,9 @@ func TestS3ApiController_GetObjectTagging(t *testing.T) { }, output: testOutput{ response: &Response{ + Headers: map[string]*string{ + "x-amz-version-id": utils.GetStringPtr(versionId), + }, Data: s3response.Tagging{ TagSet: s3response.TagSet{ Tags: []s3response.Tag{ diff --git a/s3api/controllers/object-put.go b/s3api/controllers/object-put.go index 65784708..8d3a67ae 100644 --- a/s3api/controllers/object-put.go +++ b/s3api/controllers/object-put.go @@ -86,6 +86,9 @@ func (c S3ApiController) PutObjectTagging(ctx *fiber.Ctx) (*Response, error) { err = c.be.PutObjectTagging(ctx.Context(), bucket, key, versionId, tagging) return &Response{ + Headers: map[string]*string{ + "x-amz-version-id": &versionId, + }, MetaOpts: &MetaOptions{ BucketOwner: parsedAcl.Owner, EventName: s3event.EventObjectTaggingPut, diff --git a/s3api/controllers/object-put_test.go b/s3api/controllers/object-put_test.go index 844da873..13b48db9 100644 --- a/s3api/controllers/object-put_test.go +++ b/s3api/controllers/object-put_test.go @@ -23,6 +23,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/aws/aws-sdk-go-v2/service/s3/types" + "github.com/oklog/ulid/v2" "github.com/stretchr/testify/assert" "github.com/versity/versitygw/auth" "github.com/versity/versitygw/s3api/utils" @@ -45,6 +46,8 @@ func TestS3ApiController_PutObjectTagging(t *testing.T) { }) assert.NoError(t, err) + versionId := ulid.Make().String() + tests := []struct { name string input testInput @@ -102,9 +105,15 @@ func TestS3ApiController_PutObjectTagging(t *testing.T) { locals: defaultLocals, beErr: s3err.GetAPIError(s3err.ErrNoSuchBucket), body: validTaggingBody, + queries: map[string]string{ + "versionId": versionId, + }, }, output: testOutput{ response: &Response{ + Headers: map[string]*string{ + "x-amz-version-id": &versionId, + }, MetaOpts: &MetaOptions{ BucketOwner: "root", EventName: s3event.EventObjectTaggingPut, @@ -118,9 +127,15 @@ func TestS3ApiController_PutObjectTagging(t *testing.T) { input: testInput{ locals: defaultLocals, body: validTaggingBody, + queries: map[string]string{ + "versionId": versionId, + }, }, output: testOutput{ response: &Response{ + Headers: map[string]*string{ + "x-amz-version-id": &versionId, + }, MetaOpts: &MetaOptions{ BucketOwner: "root", EventName: s3event.EventObjectTaggingPut, diff --git a/tests/integration/versioning.go b/tests/integration/versioning.go index bb70a082..e1e7cad2 100644 --- a/tests/integration/versioning.go +++ b/tests/integration/versioning.go @@ -3362,8 +3362,16 @@ func Versioning_PutGetDeleteObjectTagging_success(s *S3Conf) error { }, } + compareVersionId := func(expected, input *string) error { + if getString(expected) != getString(input) { + return fmt.Errorf("expected the response versionId to be %s, instead got %s", getString(expected), getString(input)) + } + + return nil + } + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) - _, err = s3client.PutObjectTagging(ctx, &s3.PutObjectTaggingInput{ + res, err := s3client.PutObjectTagging(ctx, &s3.PutObjectTaggingInput{ Bucket: &bucket, Key: &obj, Tagging: &tagging, @@ -3374,6 +3382,10 @@ func Versioning_PutGetDeleteObjectTagging_success(s *S3Conf) error { return err } + if err := compareVersionId(versionId, res.VersionId); err != nil { + return err + } + ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) out, err := s3client.GetObjectTagging(ctx, &s3.GetObjectTaggingInput{ Bucket: &bucket, @@ -3387,9 +3399,12 @@ func Versioning_PutGetDeleteObjectTagging_success(s *S3Conf) error { if !areTagsSame(tagging.TagSet, out.TagSet) { return fmt.Errorf("expected the object version tags to be %v, instead got %v", tagging.TagSet, out.TagSet) } + if err := compareVersionId(versionId, out.VersionId); err != nil { + return err + } ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) - _, err = s3client.DeleteObjectTagging(ctx, &s3.DeleteObjectTaggingInput{ + resp, err := s3client.DeleteObjectTagging(ctx, &s3.DeleteObjectTaggingInput{ Bucket: &bucket, Key: &obj, VersionId: versionId, @@ -3399,6 +3414,10 @@ func Versioning_PutGetDeleteObjectTagging_success(s *S3Conf) error { return err } + if err := compareVersionId(versionId, resp.VersionId); err != nil { + return err + } + ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) _, err = s3client.GetObjectTagging(ctx, &s3.GetObjectTaggingInput{ Bucket: &bucket,