summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Burke <tim.burke@gmail.com>2018-06-15 13:29:16 -0700
committerTim Burke <tim.burke@gmail.com>2018-08-13 14:19:23 -0700
commitbd640cdbae95fe8484a3d94d98f62e30a400ecb1 (patch)
treee354331a3331c6dfc355c59269a0e98cff16d3c6
parent53f9fd2b614f5adc1610043e382871018eab40f4 (diff)
downloadswift-bd640cdbae95fe8484a3d94d98f62e30a400ecb1.tar.gz
Fix the deletion of non-existent keys
On vanilla Swift, deleting an object that doesn't exist will 404. On AWS, deleting a key that doesn't exist will either 404 if the bucket doesn't exist (with a NoSuchBucket code) or 204 (because yep, that's not accessible). Change-Id: Ied2a78b56522316bb374f23961621641af3adc83 Related-Change: I6e154594dfda6c3065774c23b24f728625a842bc
-rw-r--r--swift/common/middleware/s3api/controllers/obj.py5
-rw-r--r--test/functional/s3api/test_object.py11
-rw-r--r--test/unit/common/middleware/s3api/test_multi_delete.py14
-rw-r--r--test/unit/common/middleware/s3api/test_obj.py27
4 files changed, 35 insertions, 22 deletions
diff --git a/swift/common/middleware/s3api/controllers/obj.py b/swift/common/middleware/s3api/controllers/obj.py
index d466edd8f..91abe518c 100644
--- a/swift/common/middleware/s3api/controllers/obj.py
+++ b/swift/common/middleware/s3api/controllers/obj.py
@@ -20,7 +20,7 @@ from swift.common.utils import public
from swift.common.middleware.s3api.utils import S3Timestamp
from swift.common.middleware.s3api.controllers.base import Controller
from swift.common.middleware.s3api.s3response import S3NotImplemented, \
- InvalidRange, NoSuchKey, InvalidArgument
+ InvalidRange, NoSuchKey, InvalidArgument, HTTPNoContent
class ObjectController(Controller):
@@ -143,5 +143,6 @@ class ObjectController(Controller):
except NoSuchKey:
# expect to raise NoSuchBucket when the bucket doesn't exist
req.get_container_info(self.app)
- raise
+ # else -- it's gone! Success.
+ return HTTPNoContent()
return resp
diff --git a/test/functional/s3api/test_object.py b/test/functional/s3api/test_object.py
index 783f48ae9..7424e4006 100644
--- a/test/functional/s3api/test_object.py
+++ b/test/functional/s3api/test_object.py
@@ -139,6 +139,12 @@ class TestS3ApiObject(S3ApiBase):
self.assertEqual(status, 204)
self.assertCommonResponseHeaders(headers)
+ # DELETE Non-Existent Object
+ status, headers, body = \
+ self.conn.make_request('DELETE', self.bucket, 'does-not-exist')
+ self.assertEqual(status, 204)
+ self.assertCommonResponseHeaders(headers)
+
def test_put_object_error(self):
auth_error_conn = Connection(aws_secret_key='invalid')
status, headers, body = \
@@ -239,11 +245,6 @@ class TestS3ApiObject(S3ApiBase):
self.assertEqual(headers['content-type'], 'application/xml')
status, headers, body = \
- self.conn.make_request('DELETE', self.bucket, 'invalid')
- self.assertEqual(get_error_code(body), 'NoSuchKey')
- self.assertEqual(headers['content-type'], 'application/xml')
-
- status, headers, body = \
self.conn.make_request('DELETE', 'invalid', obj)
self.assertEqual(get_error_code(body), 'NoSuchBucket')
self.assertEqual(headers['content-type'], 'application/xml')
diff --git a/test/unit/common/middleware/s3api/test_multi_delete.py b/test/unit/common/middleware/s3api/test_multi_delete.py
index c2ec2e649..91f8e8d22 100644
--- a/test/unit/common/middleware/s3api/test_multi_delete.py
+++ b/test/unit/common/middleware/s3api/test_multi_delete.py
@@ -17,7 +17,6 @@ import unittest
from datetime import datetime
from hashlib import md5
-from six.moves import urllib
from swift.common import swob
from swift.common.swob import Request
@@ -87,11 +86,14 @@ class TestS3ApiMultiDelete(S3ApiTestCase):
elem = fromstring(body)
self.assertEqual(len(elem.findall('Deleted')), 3)
- _, path, _ = self.swift.calls_with_headers[-1]
- path, query_string = path.split('?', 1)
- self.assertEqual(path, '/v1/AUTH_test/bucket/Key3')
- query = dict(urllib.parse.parse_qsl(query_string))
- self.assertEqual(query['multipart-manifest'], 'delete')
+ self.assertEqual(self.swift.calls, [
+ ('HEAD', '/v1/AUTH_test/bucket'),
+ ('HEAD', '/v1/AUTH_test/bucket/Key1'),
+ ('DELETE', '/v1/AUTH_test/bucket/Key1'),
+ ('HEAD', '/v1/AUTH_test/bucket/Key2'),
+ ('HEAD', '/v1/AUTH_test/bucket/Key3'),
+ ('DELETE', '/v1/AUTH_test/bucket/Key3?multipart-manifest=delete'),
+ ])
@s3acl
def test_object_multi_DELETE_quiet(self):
diff --git a/test/unit/common/middleware/s3api/test_obj.py b/test/unit/common/middleware/s3api/test_obj.py
index 601cd7cd0..fdddb0ecd 100644
--- a/test/unit/common/middleware/s3api/test_obj.py
+++ b/test/unit/common/middleware/s3api/test_obj.py
@@ -769,13 +769,6 @@ class TestS3ApiObj(S3ApiTestCase):
with patch(
'swift.common.middleware.s3api.s3request.get_container_info',
- return_value={'status': 204}):
- code = self._test_method_error('DELETE', '/bucket/object',
- swob.HTTPNotFound)
- self.assertEqual(code, 'NoSuchKey')
-
- with patch(
- 'swift.common.middleware.s3api.s3request.get_container_info',
return_value={'status': 404}):
code = self._test_method_error('DELETE', '/bucket/object',
swob.HTTPNotFound)
@@ -809,12 +802,28 @@ class TestS3ApiObj(S3ApiTestCase):
self.assertIn(('HEAD', '/v1/AUTH_test/bucket/object'),
self.swift.calls)
- self.assertIn(('DELETE', '/v1/AUTH_test/bucket/object'),
- self.swift.calls)
+ self.assertEqual(('DELETE', '/v1/AUTH_test/bucket/object'),
+ self.swift.calls[-1])
_, path = self.swift.calls[-1]
self.assertEqual(path.count('?'), 0)
@s3acl
+ def test_object_DELETE_missing(self):
+ self.swift.register('HEAD', '/v1/AUTH_test/bucket/object',
+ swob.HTTPNotFound, {}, None)
+ req = Request.blank('/bucket/object',
+ environ={'REQUEST_METHOD': 'DELETE'},
+ headers={'Authorization': 'AWS test:tester:hmac',
+ 'Date': self.get_date_header()})
+ status, headers, body = self.call_s3api(req)
+ self.assertEqual(status.split()[0], '204')
+
+ self.assertIn(('HEAD', '/v1/AUTH_test/bucket/object'),
+ self.swift.calls)
+ self.assertNotIn(('DELETE', '/v1/AUTH_test/bucket/object'),
+ self.swift.calls)
+
+ @s3acl
def test_slo_object_DELETE(self):
self.swift.register('HEAD', '/v1/AUTH_test/bucket/object',
swob.HTTPOk,