Merge "multi_delete: add support for quiet mode"
This commit is contained in:
		@@ -34,22 +34,26 @@ class MultiObjectDeleteController(Controller):
 | 
			
		||||
        """
 | 
			
		||||
        Handles Delete Multiple Objects.
 | 
			
		||||
        """
 | 
			
		||||
        def object_key_iter(xml):
 | 
			
		||||
            elem = fromstring(xml, 'Delete')
 | 
			
		||||
 | 
			
		||||
        def object_key_iter(elem):
 | 
			
		||||
            for obj in elem.iterchildren('Object'):
 | 
			
		||||
                key = obj.find('./Key').text
 | 
			
		||||
                version = obj.find('./VersionId')
 | 
			
		||||
                if version is not None:
 | 
			
		||||
                    version = version.text
 | 
			
		||||
 | 
			
		||||
                yield (key, version)
 | 
			
		||||
 | 
			
		||||
        elem = Element('DeleteResult')
 | 
			
		||||
                yield key, version
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            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:
 | 
			
		||||
                raise MalformedXML()
 | 
			
		||||
        except (XMLSyntaxError, DocumentInvalid):
 | 
			
		||||
@@ -60,6 +64,8 @@ class MultiObjectDeleteController(Controller):
 | 
			
		||||
            LOGGER.error(e)
 | 
			
		||||
            raise
 | 
			
		||||
 | 
			
		||||
        elem = Element('DeleteResult')
 | 
			
		||||
 | 
			
		||||
        for key, version in delete_list:
 | 
			
		||||
            if version is not None:
 | 
			
		||||
                # TODO: delete the specific version of the object
 | 
			
		||||
@@ -78,8 +84,9 @@ class MultiObjectDeleteController(Controller):
 | 
			
		||||
                SubElement(error, 'Message').text = e._msg
 | 
			
		||||
                continue
 | 
			
		||||
 | 
			
		||||
            deleted = SubElement(elem, 'Deleted')
 | 
			
		||||
            SubElement(deleted, 'Key').text = key
 | 
			
		||||
            if not self.quiet:
 | 
			
		||||
                deleted = SubElement(elem, 'Deleted')
 | 
			
		||||
                SubElement(deleted, 'Key').text = key
 | 
			
		||||
 | 
			
		||||
        body = tostring(elem)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@ from swift.common import swob
 | 
			
		||||
from swift.common.swob import Request
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -69,6 +69,34 @@ class TestSwift3MultiDelete(Swift3TestCase):
 | 
			
		||||
        status, headers, body = self.call_swift3(req)
 | 
			
		||||
        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):
 | 
			
		||||
        elem = Element('Delete')
 | 
			
		||||
        for key in ['Key1', 'Key2']:
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user