Change PUT bucket conflict error

When a bucket already exists, PUT returned a BucketAlreadyExists error.
AWS S3 returns BucketAlreadyOwnedByYou error instead, so this changes
the error returned by swift3.

When sending a PUT request to a bucket, if the bucket already exists and
is not owned by the user, return 409 conflict error,
BucketAlreadyExists.

Closes-Bug: #1498231

Change-Id: I675ba610c9345944e4565055b807f8d778b2276f
This commit is contained in:
karen chan
2016-12-05 09:15:23 -08:00
committed by Tim Burke
parent 1fb6a30ee5
commit c07cd16eb9
7 changed files with 27 additions and 12 deletions

View File

@@ -185,7 +185,7 @@ class BucketAclHandler(BaseAclHandler):
# To avoid overwriting the existing bucket's ACL, we send PUT
# request first before setting the ACL to make sure that the target
# container does not exist.
self.req.get_acl_response(app, 'PUT')
self.req.get_acl_response(app, 'PUT', self.container)
# update metadata
self.req.bucket_acl = req_acl

View File

@@ -57,7 +57,7 @@ from swift3.controllers.base import Controller, bucket_operation, \
from swift3.response import InvalidArgument, ErrorResponse, MalformedXML, \
InvalidPart, BucketAlreadyExists, EntityTooSmall, InvalidPartOrder, \
InvalidRequest, HTTPOk, HTTPNoContent, NoSuchKey, NoSuchUpload, \
NoSuchBucket
NoSuchBucket, BucketAlreadyOwnedByYou
from swift3.exception import BadSwiftRequest
from swift3.utils import LOGGER, unique_id, MULTIUPLOAD_SUFFIX, S3Timestamp, \
sysmeta_header
@@ -346,7 +346,7 @@ class UploadsController(Controller):
try:
req.get_response(self.app, 'PUT', container, '')
except BucketAlreadyExists:
except (BucketAlreadyExists, BucketAlreadyOwnedByYou):
pass
obj = '%s/%s' % (req.object_name, upload_id)

View File

@@ -24,7 +24,7 @@ import six
from six.moves.urllib.parse import quote, unquote, parse_qsl
import string
from swift.common.utils import split_path
from swift.common.utils import split_path, json
from swift.common import swob
from swift.common.http import HTTP_OK, HTTP_CREATED, HTTP_ACCEPTED, \
HTTP_NO_CONTENT, HTTP_UNAUTHORIZED, HTTP_FORBIDDEN, HTTP_NOT_FOUND, \
@@ -44,11 +44,12 @@ from swift3.controllers import ServiceController, BucketController, \
UnsupportedController, S3AclController
from swift3.response import AccessDenied, InvalidArgument, InvalidDigest, \
RequestTimeTooSkewed, Response, SignatureDoesNotMatch, \
BucketAlreadyExists, BucketNotEmpty, EntityTooLarge, \
BucketAlreadyOwnedByYou, BucketNotEmpty, EntityTooLarge, \
InternalError, NoSuchBucket, NoSuchKey, PreconditionFailed, InvalidRange, \
MissingContentLength, InvalidStorageClass, S3NotImplemented, InvalidURI, \
MalformedXML, InvalidRequest, RequestTimeout, InvalidBucketName, \
BadDigest, AuthorizationHeaderMalformed, AuthorizationQueryParametersError
BadDigest, AuthorizationHeaderMalformed, \
AuthorizationQueryParametersError, BucketAlreadyExists
from swift3.exception import NotS3Request, BadSwiftRequest
from swift3.utils import utf8encode, LOGGER, check_path_header, S3Timestamp, \
mktime, MULTIUPLOAD_SUFFIX
@@ -1060,6 +1061,15 @@ class Request(swob.Request):
return code_map[method]
def _bucket_put_accepted_error(self, container, app):
sw_req = self.to_swift_req('HEAD', container, None)
info = get_container_info(sw_req.environ, app)
acl = json.loads(info.get('sysmeta', {}).get('swift3-acl', '{}'))
owner = acl.get('Owner')
if owner is None or owner == self.user_id:
raise BucketAlreadyOwnedByYou(container)
raise BucketAlreadyExists(container)
def _swift_error_codes(self, method, container, obj, env, app):
"""
Returns a dict from expected Swift error codes to the corresponding S3
@@ -1081,7 +1091,9 @@ class Request(swob.Request):
HTTP_NOT_FOUND: (NoSuchBucket, container),
},
'PUT': {
HTTP_ACCEPTED: (BucketAlreadyExists, container),
HTTP_ACCEPTED: (self._bucket_put_accepted_error, container,
app),
HTTP_FORBIDDEN: (BucketAlreadyExists, container),
},
'POST': {
HTTP_NOT_FOUND: (NoSuchBucket, container),

View File

@@ -24,7 +24,6 @@ ceph_s3:
s3tests.functional.test_s3.test_bucket_acl_xml_readacp: {status: KNOWN}
s3tests.functional.test_s3.test_bucket_acl_xml_write: {status: KNOWN}
s3tests.functional.test_s3.test_bucket_acl_xml_writeacp: {status: KNOWN}
s3tests.functional.test_s3.test_bucket_create_exists: {status: KNOWN}
s3tests.functional.test_s3.test_bucket_header_acl_grants: {status: KNOWN}
s3tests.functional.test_s3.test_bucket_list_objects_anonymous: {status: KNOWN}
s3tests.functional.test_s3.test_bucket_list_objects_anonymous_fail: {status: KNOWN}

View File

@@ -12,7 +12,6 @@ ceph_s3:
s3tests.functional.test_s3.test_bucket_acl_grant_email_notexist: {status: KNOWN}
s3tests.functional.test_s3.test_bucket_acl_grant_nonexist_user: {status: KNOWN}
s3tests.functional.test_s3.test_bucket_acl_no_grants: {status: KNOWN}
s3tests.functional.test_s3.test_bucket_create_exists: {status: KNOWN}
s3tests.functional.test_s3.test_bucket_header_acl_grants: {status: KNOWN}
s3tests.functional.test_s3.test_bucket_list_objects_anonymous: {status: KNOWN}
s3tests.functional.test_s3.test_bucket_list_objects_anonymous_fail: {status: KNOWN}

View File

@@ -16,7 +16,8 @@
import unittest
import os
from swift3.test.functional.s3_test_client import Connection
from swift3.test.functional.s3_test_client import Connection, \
get_tester2_connection
from swift3.test.functional.utils import get_error_code
from swift3.etree import fromstring, tostring, Element, SubElement
from swift3.cfg import CONF
@@ -140,6 +141,10 @@ class TestSwift3Bucket(Swift3FunctionalTestCase):
self.conn.make_request('PUT', 'bucket')
status, headers, body = self.conn.make_request('PUT', 'bucket')
self.assertEqual(get_error_code(body), 'BucketAlreadyOwnedByYou')
conn2 = get_tester2_connection()
status, headers, body = conn2.make_request('PUT', 'bucket')
self.assertEqual(get_error_code(body), 'BucketAlreadyExists')
def test_put_bucket_with_LocationConstraint(self):

View File

@@ -469,9 +469,9 @@ class TestSwift3Bucket(Swift3TestCase):
code = self._test_method_error('PUT', '/bucket', swob.HTTPUnauthorized)
self.assertEqual(code, 'SignatureDoesNotMatch')
code = self._test_method_error('PUT', '/bucket', swob.HTTPForbidden)
self.assertEqual(code, 'AccessDenied')
code = self._test_method_error('PUT', '/bucket', swob.HTTPAccepted)
self.assertEqual(code, 'BucketAlreadyExists')
code = self._test_method_error('PUT', '/bucket', swob.HTTPAccepted)
self.assertEqual(code, 'BucketAlreadyOwnedByYou')
code = self._test_method_error('PUT', '/bucket', swob.HTTPServerError)
self.assertEqual(code, 'InternalError')
code = self._test_method_error(