From d24678dd58e23e90dc053797caa66941e43eadc3 Mon Sep 17 00:00:00 2001 From: Tim Burke Date: Fri, 29 Jul 2022 10:28:40 -0700 Subject: [PATCH] s3api: Be more consistent about CompleteMultipartUpload logging Co-Authored-By: Jianjian Huo Change-Id: I7837a2ec7dee9a657e36147c208c524b5a01671d --- .../s3api/controllers/multi_upload.py | 6 +++ .../middleware/s3api/test_multi_upload.py | 38 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/swift/common/middleware/s3api/controllers/multi_upload.py b/swift/common/middleware/s3api/controllers/multi_upload.py index 3f23f25a1c..3a30bb091f 100644 --- a/swift/common/middleware/s3api/controllers/multi_upload.py +++ b/swift/common/middleware/s3api/controllers/multi_upload.py @@ -109,6 +109,7 @@ def _get_upload_info(req, app, upload_id): try: return req.get_response(app, 'HEAD', container=container, obj=obj) except NoSuchKey: + upload_marker_path = req.environ.get('s3api.backend_path') try: resp = req.get_response(app, 'HEAD') if resp.sysmeta_headers.get(sysmeta_header( @@ -116,6 +117,11 @@ def _get_upload_info(req, app, upload_id): return resp except NoSuchKey: pass + finally: + # Ops often find it more useful for us to log the upload marker + # path, so put it back + if upload_marker_path is not None: + req.environ['s3api.backend_path'] = upload_marker_path raise NoSuchUpload(upload_id=upload_id) finally: # ...making sure to restore any copy-source before returning diff --git a/test/unit/common/middleware/s3api/test_multi_upload.py b/test/unit/common/middleware/s3api/test_multi_upload.py index 4eff8015a1..ed883d0bb2 100644 --- a/test/unit/common/middleware/s3api/test_multi_upload.py +++ b/test/unit/common/middleware/s3api/test_multi_upload.py @@ -1050,6 +1050,8 @@ class TestS3ApiMultiUpload(S3ApiTestCase): # Delete the in-progress-upload marker ('DELETE', '/v1/AUTH_test/bucket+segments/object/X') ]) + self.assertEqual(req.environ['swift.backend_path'], + '/v1/AUTH_test/bucket+segments/object/X') _, _, headers = self.swift.calls_with_headers[-2] self.assertEqual(headers.get('X-Object-Meta-Foo'), 'bar') @@ -1166,6 +1168,8 @@ class TestS3ApiMultiUpload(S3ApiTestCase): ('HEAD', '/v1/AUTH_test/bucket/object'), # So no PUT necessary ]) + self.assertEqual(req.environ['swift.backend_path'], + '/v1/AUTH_test/bucket+segments/object/X') def test_object_multipart_upload_retry_complete_etag_mismatch(self): content_md5 = base64.b64encode(md5( @@ -1206,6 +1210,8 @@ class TestS3ApiMultiUpload(S3ApiTestCase): # Retry deleting the marker for the sake of completeness ('DELETE', '/v1/AUTH_test/bucket+segments/object/X') ]) + self.assertEqual(req.environ['swift.backend_path'], + '/v1/AUTH_test/bucket+segments/object/X') _, _, headers = self.swift.calls_with_headers[-2] self.assertEqual(headers.get('X-Object-Meta-Foo'), 'bar') @@ -1249,6 +1255,38 @@ class TestS3ApiMultiUpload(S3ApiTestCase): # But the object does, and with the same upload ID ('HEAD', '/v1/AUTH_test/bucket/object'), ]) + self.assertEqual(req.environ['swift.backend_path'], + '/v1/AUTH_test/bucket+segments/object/X') + + def test_object_multipart_upload_retry_complete_nothing_there(self): + content_md5 = base64.b64encode(md5( + XML.encode('ascii'), usedforsecurity=False).digest()) + self.swift.register('HEAD', '/v1/AUTH_test/bucket+segments/object/X', + swob.HTTPNotFound, {}, None) + self.swift.register('HEAD', '/v1/AUTH_test/bucket/object', + swob.HTTPNotFound, {}, None) + req = Request.blank('/bucket/object?uploadId=X', + environ={'REQUEST_METHOD': 'POST'}, + headers={'Authorization': 'AWS test:tester:hmac', + 'Date': self.get_date_header(), + 'Content-MD5': content_md5, }, + body=XML) + status, headers, body = self.call_s3api(req) + elem = fromstring(body, 'Error') + self.assertEqual(elem.find('Code').text, 'NoSuchUpload') + self.assertEqual(status.split()[0], '404') + + self.assertEqual(self.swift.calls, [ + # Bucket exists + ('HEAD', '/v1/AUTH_test'), + ('HEAD', '/v1/AUTH_test/bucket'), + # Upload marker does not exist + ('HEAD', '/v1/AUTH_test/bucket+segments/object/X'), + # Neither does the object + ('HEAD', '/v1/AUTH_test/bucket/object'), + ]) + self.assertEqual(req.environ['swift.backend_path'], + '/v1/AUTH_test/bucket+segments/object/X') def test_object_multipart_upload_invalid_md5(self): bad_md5 = base64.b64encode(md5(