diff options
author | Zuul <zuul@review.opendev.org> | 2019-10-22 18:33:36 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2019-10-22 18:33:36 +0000 |
commit | c08da08e08570ab80ea827138a276abe5e89c033 (patch) | |
tree | 06e0d91f6fcdbaf08ecd12d99c599db3c80c0473 | |
parent | 9d6514ac1a941bd3f710f36a5a9250c4ff003055 (diff) | |
parent | 9bcce90be0c0d8a9cf0d2bb03cc02fb5ceb62970 (diff) | |
download | swift-c08da08e08570ab80ea827138a276abe5e89c033.tar.gz |
Merge "s3api: Delete multipart uploads via multi-delete" into stable/rocky
-rw-r--r-- | swift/common/middleware/s3api/controllers/multi_delete.py | 26 | ||||
-rw-r--r-- | test/functional/s3api/test_multi_upload.py | 24 | ||||
-rw-r--r-- | test/unit/common/middleware/s3api/test_multi_delete.py | 10 |
3 files changed, 57 insertions, 3 deletions
diff --git a/swift/common/middleware/s3api/controllers/multi_delete.py b/swift/common/middleware/s3api/controllers/multi_delete.py index a7e95a7bd..682b7bb36 100644 --- a/swift/common/middleware/s3api/controllers/multi_delete.py +++ b/swift/common/middleware/s3api/controllers/multi_delete.py @@ -14,6 +14,7 @@ # limitations under the License. from swift.common.utils import public +import json from swift.common.middleware.s3api.controllers.base import Controller, \ bucket_operation @@ -104,7 +105,30 @@ class MultiObjectDeleteController(Controller): try: query = req.gen_multipart_manifest_delete_query(self.app) - req.get_response(self.app, method='DELETE', query=query) + resp = req.get_response(self.app, method='DELETE', query=query, + headers={'Accept': 'application/json'}) + # Have to read the response to actually do the SLO delete + if query: + try: + delete_result = json.loads(resp.body) + if delete_result['Errors']: + # NB: bulk includes 404s in "Number Not Found", + # not "Errors" + msg_parts = [delete_result['Response Status']] + msg_parts.extend( + '%s: %s' % (obj, status) + for obj, status in delete_result['Errors']) + return key, {'code': 'SLODeleteError', + 'message': '\n'.join(msg_parts)} + # else, all good + except (ValueError, TypeError, KeyError): + # Logs get all the gory details + self.logger.exception( + 'Could not parse SLO delete response: %r', + resp.body) + # Client gets something more generic + return key, {'code': 'SLODeleteError', + 'message': 'Unexpected swift response'} except NoSuchKey: pass except ErrorResponse as e: diff --git a/test/functional/s3api/test_multi_upload.py b/test/functional/s3api/test_multi_upload.py index 33b6cadfe..0aaa7b8fd 100644 --- a/test/functional/s3api/test_multi_upload.py +++ b/test/functional/s3api/test_multi_upload.py @@ -32,7 +32,8 @@ from swift.common.middleware.s3api.utils import mktime from test.functional.s3api import S3ApiBase from test.functional.s3api.s3_test_client import Connection -from test.functional.s3api.utils import get_error_code, get_error_msg +from test.functional.s3api.utils import get_error_code, get_error_msg, \ + calculate_md5 def setUpModule(): @@ -844,6 +845,27 @@ class TestS3ApiMultiUploadSigV4(TestS3ApiMultiUpload): self.assertEqual(status, 200) # sanity self.assertEqual(content, body) # sanity + # Can delete it with DeleteMultipleObjects request + elem = Element('Delete') + SubElement(elem, 'Quiet').text = 'true' + obj_elem = SubElement(elem, 'Object') + SubElement(obj_elem, 'Key').text = key + body = tostring(elem, use_s3ns=False) + + status, headers, body = self.conn.make_request( + 'POST', bucket, body=body, query='delete', + headers={'Content-MD5': calculate_md5(body)}) + self.assertEqual(status, 200) + self.assertCommonResponseHeaders(headers) + + status, headers, body = \ + self.conn.make_request('GET', bucket, key) + self.assertEqual(status, 404) # sanity + + # Now we can delete + status, headers, body = \ + self.conn.make_request('DELETE', bucket) + self.assertEqual(status, 204) # sanity if __name__ == '__main__': unittest2.main() diff --git a/test/unit/common/middleware/s3api/test_multi_delete.py b/test/unit/common/middleware/s3api/test_multi_delete.py index 91f8e8d22..155227ce5 100644 --- a/test/unit/common/middleware/s3api/test_multi_delete.py +++ b/test/unit/common/middleware/s3api/test_multi_delete.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import json import unittest from datetime import datetime from hashlib import md5 @@ -64,8 +65,15 @@ class TestS3ApiMultiDelete(S3ApiTestCase): swob.HTTPNoContent, {}, None) self.swift.register('DELETE', '/v1/AUTH_test/bucket/Key2', swob.HTTPNotFound, {}, None) + slo_delete_resp = { + 'Number Not Found': 0, + 'Response Status': '200 OK', + 'Errors': [], + 'Response Body': '', + 'Number Deleted': 8 + } self.swift.register('DELETE', '/v1/AUTH_test/bucket/Key3', - swob.HTTPOk, {}, None) + swob.HTTPOk, {}, json.dumps(slo_delete_resp)) elem = Element('Delete') for key in ['Key1', 'Key2', 'Key3']: |