S3 - Correct error when creating a bucket that already exists (#4257)

This commit is contained in:
Bert Blommers 2021-09-01 16:30:01 +01:00 committed by GitHub
parent 0659ac6192
commit c53183db70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 92 additions and 17 deletions

View File

@ -63,6 +63,8 @@ class BucketAlreadyExists(BucketError):
code = 409
def __init__(self, *args, **kwargs):
kwargs.setdefault("template", "bucket_error")
self.templates["bucket_error"] = ERROR_WITH_BUCKET_NAME
super(BucketAlreadyExists, self).__init__(
"BucketAlreadyExists",
(

View File

@ -811,11 +811,16 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
try:
new_bucket = self.backend.create_bucket(bucket_name, region_name)
except BucketAlreadyExists:
if region_name == DEFAULT_REGION_NAME:
# us-east-1 has different behavior
new_bucket = self.backend.get_bucket(bucket_name)
new_bucket = self.backend.get_bucket(bucket_name)
if (
new_bucket.region_name == DEFAULT_REGION_NAME
and region_name == DEFAULT_REGION_NAME
):
# us-east-1 has different behavior - creating a bucket there is an idempotent operation
pass
else:
raise
template = self.response_template(S3_DUPLICATE_BUCKET_ERROR)
return 409, {}, template.render(bucket_name=bucket_name)
if "x-amz-acl" in request.headers:
# TODO: Support the XML-based ACL format
@ -2662,3 +2667,13 @@ S3_BUCKET_LOCK_CONFIGURATION = """
#</Rule>
</ObjectLockConfiguration>
"""
S3_DUPLICATE_BUCKET_ERROR = """<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>BucketAlreadyOwnedByYou</Code>
<Message>Your previous request to create the named bucket succeeded and you already own it.</Message>
<BucketName>{{ bucket_name }}</BucketName>
<RequestId>44425877V1D0A2F9</RequestId>
<HostId>9Gjjt1m+cjU4OPvX9O9/8RuvnG41MRb/18Oux2o5H5MY7ISNTlXN+Dz9IG62/ILVxhAGI0qyPfg=</HostId>
</Error>
"""

View File

@ -2106,19 +2106,6 @@ def test_boto3_bucket_create():
)
@mock_s3
def test_bucket_create_duplicate():
s3 = boto3.resource("s3", region_name="us-west-2")
s3.create_bucket(
Bucket="blah", CreateBucketConfiguration={"LocationConstraint": "us-west-2"}
)
with pytest.raises(ClientError) as exc:
s3.create_bucket(
Bucket="blah", CreateBucketConfiguration={"LocationConstraint": "us-west-2"}
)
exc.value.response["Error"]["Code"].should.equal("BucketAlreadyExists")
@mock_s3
def test_bucket_create_force_us_east_1():
s3 = boto3.resource("s3", region_name=DEFAULT_REGION_NAME)
@ -5353,3 +5340,74 @@ def test_get_object_versions_with_prefix():
versions = s3_client.list_object_versions(Bucket=bucket_name, Prefix="file")
versions["Versions"].should.have.length_of(3)
versions["Prefix"].should.equal("file")
@mock_s3
def test_create_bucket_duplicate():
bucket_name = "same-bucket-test-1371"
alternate_region = "eu-north-1"
# Create it in the default region
default_client = boto3.client("s3", region_name=DEFAULT_REGION_NAME)
default_client.create_bucket(Bucket=bucket_name)
# Create it again in the same region - should just return that same bucket
default_client.create_bucket(Bucket=bucket_name)
# Create the bucket in a different region - should return an error
diff_client = boto3.client("s3", region_name=alternate_region)
with pytest.raises(ClientError) as ex:
diff_client.create_bucket(
Bucket=bucket_name,
CreateBucketConfiguration={"LocationConstraint": alternate_region},
)
err = ex.value.response["Error"]
err["Code"].should.equal("BucketAlreadyOwnedByYou")
err["Message"].should.equal(
"Your previous request to create the named bucket succeeded and you already own it."
)
err["BucketName"].should.equal(bucket_name)
# Try this again - but creating the bucket in a non-default region in the first place
bucket_name = "same-bucket-nondefault-region-test-1371"
diff_client.create_bucket(
Bucket=bucket_name,
CreateBucketConfiguration={"LocationConstraint": alternate_region},
)
# Recreating the bucket in the same non-default region should fail
with pytest.raises(ClientError) as ex:
diff_client.create_bucket(
Bucket=bucket_name,
CreateBucketConfiguration={"LocationConstraint": alternate_region},
)
err = ex.value.response["Error"]
err["Code"].should.equal("BucketAlreadyOwnedByYou")
err["Message"].should.equal(
"Your previous request to create the named bucket succeeded and you already own it."
)
err["BucketName"].should.equal(bucket_name)
# Recreating the bucket in the default region should fail
diff_client = boto3.client("s3", region_name=DEFAULT_REGION_NAME)
with pytest.raises(ClientError) as ex:
diff_client.create_bucket(Bucket=bucket_name)
err = ex.value.response["Error"]
err["Code"].should.equal("BucketAlreadyOwnedByYou")
err["Message"].should.equal(
"Your previous request to create the named bucket succeeded and you already own it."
)
err["BucketName"].should.equal(bucket_name)
# Recreating the bucket in a third region should fail
diff_client = boto3.client("s3", region_name="ap-northeast-1")
with pytest.raises(ClientError) as ex:
diff_client.create_bucket(
Bucket=bucket_name,
CreateBucketConfiguration={"LocationConstraint": "ap-northeast-1"},
)
err = ex.value.response["Error"]
err["Code"].should.equal("BucketAlreadyOwnedByYou")
err["Message"].should.equal(
"Your previous request to create the named bucket succeeded and you already own it."
)
err["BucketName"].should.equal(bucket_name)