S3 - create_multipart_upload - support tags (#4548)

This commit is contained in:
Bert Blommers 2021-11-09 18:49:29 -01:00 committed by GitHub
parent 669e7048f1
commit 0bad68f9f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 5 deletions

View File

@ -330,9 +330,11 @@ class FakeKey(BaseModel):
class FakeMultipart(BaseModel): class FakeMultipart(BaseModel):
def __init__(self, key_name, metadata): def __init__(self, key_name, metadata, storage=None, tags=None):
self.key_name = key_name self.key_name = key_name
self.metadata = metadata self.metadata = metadata
self.storage = storage
self.tags = tags
self.parts = {} self.parts = {}
self.partlist = [] # ordered list of part ID's self.partlist = [] # ordered list of part ID's
rand_b64 = base64.b64encode(os.urandom(UPLOAD_ID_BYTES)) rand_b64 = base64.b64encode(os.urandom(UPLOAD_ID_BYTES))
@ -1834,9 +1836,10 @@ class S3Backend(BaseBackend):
bucket = self.get_bucket(bucket_name) bucket = self.get_bucket(bucket_name)
return len(bucket.multiparts[multipart_id].parts) >= next_part_number_marker return len(bucket.multiparts[multipart_id].parts) >= next_part_number_marker
def create_multipart_upload(self, bucket_name, key_name, metadata, storage_type): def create_multipart_upload(
multipart = FakeMultipart(key_name, metadata) self, bucket_name, key_name, metadata, storage_type, tags
multipart.storage = storage_type ):
multipart = FakeMultipart(key_name, metadata, storage=storage_type, tags=tags)
bucket = self.get_bucket(bucket_name) bucket = self.get_bucket(bucket_name)
bucket.multiparts[multipart.id] = multipart bucket.multiparts[multipart.id] = multipart

View File

@ -2009,9 +2009,10 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
if body == b"" and "uploads" in query: if body == b"" and "uploads" in query:
metadata = metadata_from_headers(request.headers) metadata = metadata_from_headers(request.headers)
tagging = self._tagging_from_headers(request.headers)
storage_type = request.headers.get("x-amz-storage-class", "STANDARD") storage_type = request.headers.get("x-amz-storage-class", "STANDARD")
multipart_id = self.backend.create_multipart_upload( multipart_id = self.backend.create_multipart_upload(
bucket_name, key_name, metadata, storage_type bucket_name, key_name, metadata, storage_type, tagging
) )
template = self.response_template(S3_MULTIPART_INITIATE_RESPONSE) template = self.response_template(S3_MULTIPART_INITIATE_RESPONSE)
@ -2039,6 +2040,7 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
multipart=multipart, multipart=multipart,
) )
key.set_metadata(multipart.metadata) key.set_metadata(multipart.metadata)
self.backend.set_key_tags(key, multipart.tags)
template = self.response_template(S3_MULTIPART_COMPLETE_RESPONSE) template = self.response_template(S3_MULTIPART_COMPLETE_RESPONSE)
headers = {} headers = {}

View File

@ -1,6 +1,7 @@
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
from moto import mock_s3 from moto import mock_s3
import boto3 import boto3
import os
import pytest import pytest
import sure # pylint: disable=unused-import import sure # pylint: disable=unused-import
@ -52,3 +53,30 @@ def test_boto3_multipart_part_size():
err["Message"].should.equal( err["Message"].should.equal(
"The specified upload does not exist. The upload ID may be invalid, or the upload may have been aborted or completed." "The specified upload does not exist. The upload ID may be invalid, or the upload may have been aborted or completed."
) )
@mock_s3
def test_multipart_upload_with_tags():
bucket = "mybucket"
key = "test/multipartuploadtag/file.txt"
tags = "a=b"
client = boto3.client("s3", region_name="us-east-1")
client.create_bucket(Bucket=bucket)
response = client.create_multipart_upload(Bucket=bucket, Key=key, Tagging=tags)
u = boto3.resource("s3").MultipartUpload(bucket, key, response["UploadId"])
parts = [
{
"ETag": u.Part(i).upload(Body=os.urandom(5 * (2 ** 20)))["ETag"],
"PartNumber": i,
}
for i in range(1, 3)
]
u.complete(MultipartUpload={"Parts": parts})
# check tags
response = client.get_object_tagging(Bucket=bucket, Key=key)
actual = {t["Key"]: t["Value"] for t in response.get("TagSet", [])}
actual.should.equal({"a": "b"})