]> git-server-git.apps.pok.os.sepia.ceph.com Git - s3-tests.git/commitdiff
s3: Add a test for attempting to complete an unstarted multipart upload
authorJacques Heunis <jheunis@bloomberg.net>
Mon, 16 Mar 2026 15:13:02 +0000 (15:13 +0000)
committerCasey Bodley <cbodley@redhat.com>
Wed, 29 Apr 2026 17:17:13 +0000 (13:17 -0400)
The AWS documentation for CompleteMultipartUpload specifies that the call will
return a 404 with the text "NoSuchUpload" to indicate that the specified
multipart upload does not exist. This could be the result of an invalid upload
ID or a multipart upload that has been aborted or completed.

Of particular significance is the requirement that this API call return a
400-series error (indicating a client-side problem) and not a 500-series error
(indicating a server-size problem).
At the time of writing, Ceph returns a 500 in this scenario which may be
handled incorrectly by client SDKs and is likely to be misinterpreted by Ceph
monitoring as an increase in errors that require operator intervention to fix.

CompleteMultipartUpload docs available at:
https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html

Signed-off-by: Jacques Heunis <jheunis@bloomberg.net>
(cherry picked from commit 5506af825b6dde397da7926cdcab889ff537c506)

s3tests/functional/test_s3.py

index d063caf30c0bca6a5e60aadf3e3aeaeb1b2dca03..f089642a272c76321ec5387aa874fc71922736e0 100644 (file)
@@ -5975,6 +5975,25 @@ def test_multipart_upload_empty():
     assert status == 400
     assert error_code == 'MalformedXML'
 
+@pytest.mark.fails_on_rgw # TODO: Remove fails_on_rgw when https://tracker.ceph.com/issues/75534 is fixed
+def test_multipart_upload_complete_without_create():
+    bucket_name = get_new_bucket()
+    client = get_client()
+
+    parts = {}
+    upload_opts = {
+        'Bucket': bucket_name,
+        'Key': 'mymultipart',
+        'UploadId': 'abc1234def',
+        'MultipartUpload': {'Parts': [
+            {'ETag': "1234", 'PartNumber': 1}
+        ]}
+    }
+    e = assert_raises(ClientError, client.complete_multipart_upload, **upload_opts)
+    status, error_code = _get_status_and_error_code(e.response)
+    assert status == 404
+    assert error_code == 'NoSuchUpload'
+
 @pytest.mark.fails_on_dbstore
 def test_multipart_upload_small():
     bucket_name = get_new_bucket()