s3api: Make the 'Quiet' key value case insensitive
When deleting multiple objects, S3 allows to enable a quiet mode with the 'Quiet' key. At AWS S3, the value of this key is case-insensitive. - Quiet mode is enabled if the value is 'true' (regardless of case). - Otherwise, in all other cases (even a non-boolean value), this mode will be disabled. Also, some tools (like Minio's python API) send the value 'True' (and not 'true'). Change-Id: Id9d1da2017b8d13242ae1f410347febb013e9ce1
This commit is contained in:
		@@ -1,6 +1,6 @@
 | 
				
			|||||||
start =
 | 
					start =
 | 
				
			||||||
  element Delete {
 | 
					  element Delete {
 | 
				
			||||||
    element Quiet { xsd:boolean }? &
 | 
					    element Quiet { xsd:string }? &
 | 
				
			||||||
    element Object {
 | 
					    element Object {
 | 
				
			||||||
      element Key { xsd:string } &
 | 
					      element Key { xsd:string } &
 | 
				
			||||||
      element VersionId { xsd:string }?
 | 
					      element VersionId { xsd:string }?
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -81,10 +81,7 @@ class MultiObjectDeleteController(Controller):
 | 
				
			|||||||
            elem = fromstring(xml, 'Delete', self.logger)
 | 
					            elem = fromstring(xml, 'Delete', self.logger)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            quiet = elem.find('./Quiet')
 | 
					            quiet = elem.find('./Quiet')
 | 
				
			||||||
            if quiet is not None and quiet.text.lower() == 'true':
 | 
					            self.quiet = quiet is not None and quiet.text.lower() == 'true'
 | 
				
			||||||
                self.quiet = True
 | 
					 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
                self.quiet = False
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            delete_list = list(object_key_iter(elem))
 | 
					            delete_list = list(object_key_iter(elem))
 | 
				
			||||||
            if len(delete_list) > self.conf.max_multi_delete_objects:
 | 
					            if len(delete_list) > self.conf.max_multi_delete_objects:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@
 | 
				
			|||||||
      <interleave>
 | 
					      <interleave>
 | 
				
			||||||
        <optional>
 | 
					        <optional>
 | 
				
			||||||
          <element name="Quiet">
 | 
					          <element name="Quiet">
 | 
				
			||||||
            <data type="boolean"/>
 | 
					            <data type="string"/>
 | 
				
			||||||
          </element>
 | 
					          </element>
 | 
				
			||||||
        </optional>
 | 
					        </optional>
 | 
				
			||||||
        <oneOrMore>
 | 
					        <oneOrMore>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -249,26 +249,28 @@ class TestS3ApiMultiDelete(S3ApiTestCase):
 | 
				
			|||||||
        self.swift.register('DELETE', '/v1/AUTH_test/bucket/Key2',
 | 
					        self.swift.register('DELETE', '/v1/AUTH_test/bucket/Key2',
 | 
				
			||||||
                            swob.HTTPNotFound, {}, None)
 | 
					                            swob.HTTPNotFound, {}, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        elem = Element('Delete')
 | 
					        for true_value in ('true', 'True', 'TRUE', 'trUE'):
 | 
				
			||||||
        SubElement(elem, 'Quiet').text = 'true'
 | 
					            elem = Element('Delete')
 | 
				
			||||||
        for key in ['Key1', 'Key2']:
 | 
					            SubElement(elem, 'Quiet').text = true_value
 | 
				
			||||||
            obj = SubElement(elem, 'Object')
 | 
					            for key in ['Key1', 'Key2']:
 | 
				
			||||||
            SubElement(obj, 'Key').text = key
 | 
					                obj = SubElement(elem, 'Object')
 | 
				
			||||||
        body = tostring(elem, use_s3ns=False)
 | 
					                SubElement(obj, 'Key').text = key
 | 
				
			||||||
        content_md5 = base64.b64encode(
 | 
					            body = tostring(elem, use_s3ns=False)
 | 
				
			||||||
            md5(body, usedforsecurity=False).digest()).strip()
 | 
					            content_md5 = base64.b64encode(
 | 
				
			||||||
 | 
					                md5(body, usedforsecurity=False).digest()).strip()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        req = Request.blank('/bucket?delete',
 | 
					            req = Request.blank('/bucket?delete',
 | 
				
			||||||
                            environ={'REQUEST_METHOD': 'POST'},
 | 
					                                environ={'REQUEST_METHOD': 'POST'},
 | 
				
			||||||
                            headers={'Authorization': 'AWS test:tester:hmac',
 | 
					                                headers={
 | 
				
			||||||
                                     'Date': self.get_date_header(),
 | 
					                                    'Authorization': 'AWS test:tester:hmac',
 | 
				
			||||||
                                     'Content-MD5': content_md5},
 | 
					                                    'Date': self.get_date_header(),
 | 
				
			||||||
                            body=body)
 | 
					                                    'Content-MD5': content_md5},
 | 
				
			||||||
        status, headers, body = self.call_s3api(req)
 | 
					                                body=body)
 | 
				
			||||||
        self.assertEqual(status.split()[0], '200')
 | 
					            status, headers, body = self.call_s3api(req)
 | 
				
			||||||
 | 
					            self.assertEqual(status.split()[0], '200')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        elem = fromstring(body)
 | 
					            elem = fromstring(body)
 | 
				
			||||||
        self.assertEqual(len(elem.findall('Deleted')), 0)
 | 
					            self.assertEqual(len(elem.findall('Deleted')), 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @s3acl
 | 
					    @s3acl
 | 
				
			||||||
    def test_object_multi_DELETE_no_key(self):
 | 
					    def test_object_multi_DELETE_no_key(self):
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user