From 349353edaa261a252aa9b8aa45ed2989634a3bee Mon Sep 17 00:00:00 2001 From: Bert Blommers Date: Thu, 7 Mar 2024 19:46:30 +0000 Subject: [PATCH] Techdebt: Move S3 CompleteMultipartUpload to the backend (#7437) --- moto/s3/models.py | 30 ++++++++++++++++++++++++++++-- moto/s3/responses.py | 36 ++++++------------------------------ 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/moto/s3/models.py b/moto/s3/models.py index cf5643d03aa..14bd40c5c1e 100644 --- a/moto/s3/models.py +++ b/moto/s3/models.py @@ -2423,13 +2423,39 @@ def create_multipart_upload( def complete_multipart_upload( self, bucket_name: str, multipart_id: str, body: Iterator[Tuple[int, str]] - ) -> Tuple[FakeMultipart, bytes, str, Optional[str]]: + ) -> Optional[FakeKey]: bucket = self.get_bucket(bucket_name) multipart = bucket.multiparts[multipart_id] value, etag, checksum = multipart.complete(body) if value is not None: del bucket.multiparts[multipart_id] - return multipart, value, etag, checksum + + if value is None: + return None + + key = self.put_object( + bucket_name, + multipart.key_name, + value, + storage=multipart.storage, + etag=etag, + multipart=multipart, + encryption=multipart.sse_encryption, + kms_key_id=multipart.kms_key_id, + ) + key.set_metadata(multipart.metadata) + + if checksum: + key.checksum_algorithm = multipart.metadata.get("x-amz-checksum-algorithm") + key.checksum_value = checksum + + self.put_object_tagging(key, multipart.tags) + self.put_object_acl( + bucket_name=bucket_name, + key_name=key.name, + acl=multipart.acl, + ) + return key def get_all_multiparts(self, bucket_name: str) -> Dict[str, FakeMultipart]: bucket = self.get_bucket(bucket_name) diff --git a/moto/s3/responses.py b/moto/s3/responses.py index 65c31081438..629df1c4ef1 100644 --- a/moto/s3/responses.py +++ b/moto/s3/responses.py @@ -2245,37 +2245,13 @@ def _key_response_post( if query.get("uploadId"): multipart_id = query["uploadId"][0] - multipart, value, etag, checksum = self.backend.complete_multipart_upload( + key = self.backend.complete_multipart_upload( bucket_name, multipart_id, self._complete_multipart_body(body) ) - if value is None: + if key is None: return 400, {}, "" headers: Dict[str, Any] = {} - key = self.backend.put_object( - bucket_name, - multipart.key_name, - value, - storage=multipart.storage, - etag=etag, - multipart=multipart, - encryption=multipart.sse_encryption, - kms_key_id=multipart.kms_key_id, - ) - key.set_metadata(multipart.metadata) - - if checksum: - key.checksum_algorithm = multipart.metadata.get( - "x-amz-checksum-algorithm" - ) - key.checksum_value = checksum - - self.backend.put_object_tagging(key, multipart.tags) - self.backend.put_object_acl( - bucket_name=bucket_name, - key_name=key.name, - acl=multipart.acl, - ) template = self.response_template(S3_MULTIPART_COMPLETE_RESPONSE) if key.version_id: @@ -2299,12 +2275,12 @@ def _key_response_post( es = minidom.parseString(body).getElementsByTagName("Days") days = es[0].childNodes[0].wholeText key = self.backend.get_object(bucket_name, key_name) # type: ignore - if key.storage_class not in ARCHIVE_STORAGE_CLASSES: - raise InvalidObjectState(storage_class=key.storage_class) + if key.storage_class not in ARCHIVE_STORAGE_CLASSES: # type: ignore + raise InvalidObjectState(storage_class=key.storage_class) # type: ignore r = 202 - if key.expiry_date is not None: + if key.expiry_date is not None: # type: ignore r = 200 - key.restore(int(days)) + key.restore(int(days)) # type: ignore return r, {}, "" elif "select" in query: request = xmltodict.parse(body)["SelectObjectContentRequest"]