diff --git a/moto/s3/models.py b/moto/s3/models.py index 8cf875ae9..aeac2307d 100644 --- a/moto/s3/models.py +++ b/moto/s3/models.py @@ -1595,7 +1595,7 @@ class S3Backend(BaseBackend): storage=storage, etag=etag, is_versioned=bucket.is_versioned, - version_id=str(uuid.uuid4()) if bucket.is_versioned else None, + version_id=str(uuid.uuid4()) if bucket.is_versioned else "null", multipart=multipart, encryption=encryption, kms_key_id=kms_key_id, diff --git a/tests/test_s3/test_s3.py b/tests/test_s3/test_s3.py index a355b706b..efd83461e 100644 --- a/tests/test_s3/test_s3.py +++ b/tests/test_s3/test_s3.py @@ -1372,6 +1372,63 @@ def test_delete_keys(): keys[0].name.should.equal("file1") +@mock_s3 +def test_delete_versioned_objects(): + s3 = boto3.client("s3", region_name=DEFAULT_REGION_NAME) + bucket = "test" + key = "test" + + s3.create_bucket(Bucket=bucket) + + s3.put_object(Bucket=bucket, Key=key, Body=b"") + + s3.put_bucket_versioning( + Bucket=bucket, VersioningConfiguration={"Status": "Enabled"}, + ) + + objects = s3.list_objects_v2(Bucket=bucket).get("Contents") + versions = s3.list_object_versions(Bucket=bucket).get("Versions") + delete_markers = s3.list_object_versions(Bucket=bucket).get("DeleteMarkers") + + objects.shouldnt.be.empty + versions.shouldnt.be.empty + delete_markers.should.be.none + + s3.delete_object(Bucket=bucket, Key=key) + + objects = s3.list_objects_v2(Bucket=bucket).get("Contents") + versions = s3.list_object_versions(Bucket=bucket).get("Versions") + delete_markers = s3.list_object_versions(Bucket=bucket).get("DeleteMarkers") + + objects.should.be.none + versions.shouldnt.be.empty + delete_markers.shouldnt.be.empty + + s3.delete_object( + Bucket=bucket, Key=key, VersionId=versions[0].get("VersionId"), + ) + + objects = s3.list_objects_v2(Bucket=bucket).get("Contents") + versions = s3.list_object_versions(Bucket=bucket).get("Versions") + delete_markers = s3.list_object_versions(Bucket=bucket).get("DeleteMarkers") + + objects.should.be.none + versions.should.be.none + delete_markers.shouldnt.be.empty + + s3.delete_object( + Bucket=bucket, Key=key, VersionId=delete_markers[0].get("VersionId"), + ) + + objects = s3.list_objects_v2(Bucket=bucket).get("Contents") + versions = s3.list_object_versions(Bucket=bucket).get("Versions") + delete_markers = s3.list_object_versions(Bucket=bucket).get("DeleteMarkers") + + objects.should.be.none + versions.should.be.none + delete_markers.should.be.none + + # Has boto3 equivalent @mock_s3_deprecated def test_delete_keys_invalid():