Skip to content

Commit

Permalink
S3: complete_multipart_upload() should be able to overwrite (#8418)
Browse files Browse the repository at this point in the history
  • Loading branch information
bblommers authored Dec 18, 2024
1 parent f2e43c6 commit 6bf0cfc
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 3 deletions.
9 changes: 6 additions & 3 deletions moto/s3/responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -2533,9 +2533,12 @@ def _key_response_post(

multipart_id = query["uploadId"][0]

if existing is not None and existing.multipart:
# Based on testing against AWS, operation seems idempotent
# Scenario where both method-calls have a different body hasn't been tested yet
if (
existing is not None
and existing.multipart
and existing.multipart.id == multipart_id
):
# Operation is idempotent
key: Optional[FakeKey] = existing
else:
key = self.backend.complete_multipart_upload(
Expand Down
52 changes: 52 additions & 0 deletions tests/test_s3/test_s3_multipart.py
Original file line number Diff line number Diff line change
Expand Up @@ -1142,3 +1142,55 @@ def test_generate_presigned_url_for_multipart_upload():

resp = requests.put(url, data=data)
assert resp.status_code == 200


@s3_aws_verified
@pytest.mark.aws_verified()
def test_multipart_upload_overwrites(bucket_name=None):
s3_client = boto3.client("s3", "us-east-1")
key = "mykey.txt"

upload_id = s3_client.create_multipart_upload(Bucket=bucket_name, Key=key)[
"UploadId"
]

part_data = b"First part data"
response = s3_client.upload_part(
Bucket=bucket_name,
Key=key,
PartNumber=1,
UploadId=upload_id,
Body=part_data,
)

s3_client.complete_multipart_upload(
Bucket=bucket_name,
Key=key,
UploadId=upload_id,
MultipartUpload={"Parts": [{"PartNumber": 1, "ETag": response["ETag"]}]},
)

upload_id = s3_client.create_multipart_upload(Bucket=bucket_name, Key=key)[
"UploadId"
]

new_data = b"New data that should overwrite"
response = s3_client.upload_part(
Bucket=bucket_name,
Key=key,
PartNumber=1,
UploadId=upload_id,
Body=new_data,
)

s3_client.complete_multipart_upload(
Bucket=bucket_name,
Key=key,
UploadId=upload_id,
MultipartUpload={"Parts": [{"PartNumber": 1, "ETag": response["ETag"]}]},
)

result = s3_client.get_object(Bucket=bucket_name, Key=key)
content = result["Body"].read()

assert content == new_data

0 comments on commit 6bf0cfc

Please sign in to comment.