Merge "multi_delete: add support for quiet mode"
This commit is contained in:
@@ -34,22 +34,26 @@ class MultiObjectDeleteController(Controller):
|
|||||||
"""
|
"""
|
||||||
Handles Delete Multiple Objects.
|
Handles Delete Multiple Objects.
|
||||||
"""
|
"""
|
||||||
def object_key_iter(xml):
|
def object_key_iter(elem):
|
||||||
elem = fromstring(xml, 'Delete')
|
|
||||||
|
|
||||||
for obj in elem.iterchildren('Object'):
|
for obj in elem.iterchildren('Object'):
|
||||||
key = obj.find('./Key').text
|
key = obj.find('./Key').text
|
||||||
version = obj.find('./VersionId')
|
version = obj.find('./VersionId')
|
||||||
if version is not None:
|
if version is not None:
|
||||||
version = version.text
|
version = version.text
|
||||||
|
|
||||||
yield (key, version)
|
yield key, version
|
||||||
|
|
||||||
elem = Element('DeleteResult')
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
xml = req.xml(MAX_MULTI_DELETE_BODY_SIZE, check_md5=True)
|
xml = req.xml(MAX_MULTI_DELETE_BODY_SIZE, check_md5=True)
|
||||||
delete_list = list(object_key_iter(xml))
|
elem = fromstring(xml, 'Delete')
|
||||||
|
|
||||||
|
quiet = elem.find('./Quiet')
|
||||||
|
if quiet is not None and quiet.text.lower() == 'true':
|
||||||
|
self.quiet = True
|
||||||
|
else:
|
||||||
|
self.quiet = False
|
||||||
|
|
||||||
|
delete_list = list(object_key_iter(elem))
|
||||||
if len(delete_list) > CONF.max_multi_delete_objects:
|
if len(delete_list) > CONF.max_multi_delete_objects:
|
||||||
raise MalformedXML()
|
raise MalformedXML()
|
||||||
except (XMLSyntaxError, DocumentInvalid):
|
except (XMLSyntaxError, DocumentInvalid):
|
||||||
@@ -60,6 +64,8 @@ class MultiObjectDeleteController(Controller):
|
|||||||
LOGGER.error(e)
|
LOGGER.error(e)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
elem = Element('DeleteResult')
|
||||||
|
|
||||||
for key, version in delete_list:
|
for key, version in delete_list:
|
||||||
if version is not None:
|
if version is not None:
|
||||||
# TODO: delete the specific version of the object
|
# TODO: delete the specific version of the object
|
||||||
@@ -78,8 +84,9 @@ class MultiObjectDeleteController(Controller):
|
|||||||
SubElement(error, 'Message').text = e._msg
|
SubElement(error, 'Message').text = e._msg
|
||||||
continue
|
continue
|
||||||
|
|
||||||
deleted = SubElement(elem, 'Deleted')
|
if not self.quiet:
|
||||||
SubElement(deleted, 'Key').text = key
|
deleted = SubElement(elem, 'Deleted')
|
||||||
|
SubElement(deleted, 'Key').text = key
|
||||||
|
|
||||||
body = tostring(elem)
|
body = tostring(elem)
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ from swift.common import swob
|
|||||||
from swift.common.swob import Request
|
from swift.common.swob import Request
|
||||||
|
|
||||||
from swift3.test.unit import Swift3TestCase
|
from swift3.test.unit import Swift3TestCase
|
||||||
from swift3.etree import tostring, Element, SubElement
|
from swift3.etree import fromstring, tostring, Element, SubElement
|
||||||
from swift3.cfg import CONF
|
from swift3.cfg import CONF
|
||||||
|
|
||||||
|
|
||||||
@@ -69,6 +69,34 @@ class TestSwift3MultiDelete(Swift3TestCase):
|
|||||||
status, headers, body = self.call_swift3(req)
|
status, headers, body = self.call_swift3(req)
|
||||||
self.assertEquals(status.split()[0], '200')
|
self.assertEquals(status.split()[0], '200')
|
||||||
|
|
||||||
|
elem = fromstring(body)
|
||||||
|
self.assertEquals(len(elem.findall('Deleted')), 2)
|
||||||
|
|
||||||
|
def test_object_multi_DELETE_quiet(self):
|
||||||
|
self.swift.register('DELETE', '/v1/AUTH_test/bucket/Key1',
|
||||||
|
swob.HTTPNoContent, {}, None)
|
||||||
|
self.swift.register('DELETE', '/v1/AUTH_test/bucket/Key2',
|
||||||
|
swob.HTTPNotFound, {}, None)
|
||||||
|
|
||||||
|
elem = Element('Delete')
|
||||||
|
SubElement(elem, 'Quiet').text = 'true'
|
||||||
|
for key in ['Key1', 'Key2']:
|
||||||
|
obj = SubElement(elem, 'Object')
|
||||||
|
SubElement(obj, 'Key').text = key
|
||||||
|
body = tostring(elem, use_s3ns=False)
|
||||||
|
content_md5 = md5(body).digest().encode('base64').strip()
|
||||||
|
|
||||||
|
req = Request.blank('/bucket?delete',
|
||||||
|
environ={'REQUEST_METHOD': 'POST'},
|
||||||
|
headers={'Authorization': 'AWS test:tester:hmac',
|
||||||
|
'Content-MD5': content_md5},
|
||||||
|
body=body)
|
||||||
|
status, headers, body = self.call_swift3(req)
|
||||||
|
self.assertEquals(status.split()[0], '200')
|
||||||
|
|
||||||
|
elem = fromstring(body)
|
||||||
|
self.assertEquals(len(elem.findall('Deleted')), 0)
|
||||||
|
|
||||||
def test_object_multi_DELETE_with_invalid_md5(self):
|
def test_object_multi_DELETE_with_invalid_md5(self):
|
||||||
elem = Element('Delete')
|
elem = Element('Delete')
|
||||||
for key in ['Key1', 'Key2']:
|
for key in ['Key1', 'Key2']:
|
||||||
|
|||||||
Reference in New Issue
Block a user