diff --git a/backend/posix/posix.go b/backend/posix/posix.go index 5640a2c0..f00a8c0d 100644 --- a/backend/posix/posix.go +++ b/backend/posix/posix.go @@ -3044,7 +3044,6 @@ func (p *Posix) DeleteObject(ctx context.Context, input *s3.DeleteObjectInput) ( // if the specified VersionId is the same as in the latest version, // remove the latest version, find the latest version from the versioning // directory and move to the place of the deleted object, to make it the latest - isDelMarker, err := p.isObjDeleteMarker(bucket, object) if err != nil { return nil, err @@ -3056,6 +3055,7 @@ func (p *Posix) DeleteObject(ctx context.Context, input *s3.DeleteObjectInput) ( ents, err := os.ReadDir(versionPath) if errors.Is(err, fs.ErrNotExist) { + p.removeParents(bucket, object) return &s3.DeleteObjectOutput{ DeleteMarker: &isDelMarker, VersionId: input.VersionId, @@ -3066,6 +3066,7 @@ func (p *Posix) DeleteObject(ctx context.Context, input *s3.DeleteObjectInput) ( } if len(ents) == 0 { + p.removeParents(bucket, object) return &s3.DeleteObjectOutput{ DeleteMarker: &isDelMarker, VersionId: input.VersionId, diff --git a/tests/integration/group-tests.go b/tests/integration/group-tests.go index 41e4c272..ea9f856f 100644 --- a/tests/integration/group-tests.go +++ b/tests/integration/group-tests.go @@ -692,6 +692,7 @@ func TestVersioning(s *S3Conf) { Versioning_DeleteObject_non_existing_object(s) Versioning_DeleteObject_delete_a_delete_marker(s) Versioning_Delete_null_versionId_object(s) + Versioning_DeleteObject_nested_dir_object(s) Versioning_DeleteObject_suspended(s) Versioning_DeleteObjects_success(s) Versioning_DeleteObjects_delete_deleteMarkers(s) @@ -1151,6 +1152,7 @@ func GetIntTests() IntTests { "Versioning_DeleteObject_non_existing_object": Versioning_DeleteObject_non_existing_object, "Versioning_DeleteObject_delete_a_delete_marker": Versioning_DeleteObject_delete_a_delete_marker, "Versioning_Delete_null_versionId_object": Versioning_Delete_null_versionId_object, + "Versioning_DeleteObject_nested_dir_object": Versioning_DeleteObject_nested_dir_object, "Versioning_DeleteObject_suspended": Versioning_DeleteObject_suspended, "Versioning_DeleteObjects_success": Versioning_DeleteObjects_success, "Versioning_DeleteObjects_delete_deleteMarkers": Versioning_DeleteObjects_delete_deleteMarkers, diff --git a/tests/integration/tests.go b/tests/integration/tests.go index 13e798a9..91e13594 100644 --- a/tests/integration/tests.go +++ b/tests/integration/tests.go @@ -14904,6 +14904,51 @@ func Versioning_Delete_null_versionId_object(s *S3Conf) error { }) } +func Versioning_DeleteObject_nested_dir_object(s *S3Conf) error { + testName := "Versioning_DeleteObject_nested_dir_object" + return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { + obj := "foo/bar/baz" + out, err := putObjectWithData(1000, &s3.PutObjectInput{ + Bucket: &bucket, + Key: &obj, + }, s3client) + if err != nil { + return err + } + + ctx, cancel := context.WithTimeout(context.Background(), shortTimeout) + res, err := s3client.DeleteObject(ctx, &s3.DeleteObjectInput{ + Bucket: &bucket, + Key: &obj, + VersionId: out.res.VersionId, + }) + cancel() + if err != nil { + return err + } + + if getString(res.VersionId) != getString(out.res.VersionId) { + return fmt.Errorf("expected the versionId to be %v, instead got %v", getString(out.res.VersionId), getString(res.VersionId)) + } + + ctx, cancel = context.WithTimeout(context.Background(), shortTimeout) + _, err = s3client.DeleteBucket(ctx, &s3.DeleteBucketInput{ + Bucket: &bucket, + }) + cancel() + if err != nil { + return err + } + + // Then create the bucket back to not get error on teardown + if err := setup(s, bucket); err != nil { + return err + } + + return nil + }, withLock()) +} + func Versioning_DeleteObject_suspended(s *S3Conf) error { testName := "Versioning_DeleteObject_suspended" return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error {