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:
@@ -185,7 +185,7 @@ class BucketAclHandler(BaseAclHandler):
|
|||||||
# To avoid overwriting the existing bucket's ACL, we send PUT
|
# To avoid overwriting the existing bucket's ACL, we send PUT
|
||||||
# request first before setting the ACL to make sure that the target
|
# request first before setting the ACL to make sure that the target
|
||||||
# container does not exist.
|
# container does not exist.
|
||||||
self.req.get_acl_response(app, 'PUT')
|
self.req.get_acl_response(app, 'PUT', self.container)
|
||||||
|
|
||||||
# update metadata
|
# update metadata
|
||||||
self.req.bucket_acl = req_acl
|
self.req.bucket_acl = req_acl
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ from swift3.controllers.base import Controller, bucket_operation, \
|
|||||||
from swift3.response import InvalidArgument, ErrorResponse, MalformedXML, \
|
from swift3.response import InvalidArgument, ErrorResponse, MalformedXML, \
|
||||||
InvalidPart, BucketAlreadyExists, EntityTooSmall, InvalidPartOrder, \
|
InvalidPart, BucketAlreadyExists, EntityTooSmall, InvalidPartOrder, \
|
||||||
InvalidRequest, HTTPOk, HTTPNoContent, NoSuchKey, NoSuchUpload, \
|
InvalidRequest, HTTPOk, HTTPNoContent, NoSuchKey, NoSuchUpload, \
|
||||||
NoSuchBucket
|
NoSuchBucket, BucketAlreadyOwnedByYou
|
||||||
from swift3.exception import BadSwiftRequest
|
from swift3.exception import BadSwiftRequest
|
||||||
from swift3.utils import LOGGER, unique_id, MULTIUPLOAD_SUFFIX, S3Timestamp, \
|
from swift3.utils import LOGGER, unique_id, MULTIUPLOAD_SUFFIX, S3Timestamp, \
|
||||||
sysmeta_header
|
sysmeta_header
|
||||||
@@ -346,7 +346,7 @@ class UploadsController(Controller):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
req.get_response(self.app, 'PUT', container, '')
|
req.get_response(self.app, 'PUT', container, '')
|
||||||
except BucketAlreadyExists:
|
except (BucketAlreadyExists, BucketAlreadyOwnedByYou):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
obj = '%s/%s' % (req.object_name, upload_id)
|
obj = '%s/%s' % (req.object_name, upload_id)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import six
|
|||||||
from six.moves.urllib.parse import quote, unquote, parse_qsl
|
from six.moves.urllib.parse import quote, unquote, parse_qsl
|
||||||
import string
|
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 import swob
|
||||||
from swift.common.http import HTTP_OK, HTTP_CREATED, HTTP_ACCEPTED, \
|
from swift.common.http import HTTP_OK, HTTP_CREATED, HTTP_ACCEPTED, \
|
||||||
HTTP_NO_CONTENT, HTTP_UNAUTHORIZED, HTTP_FORBIDDEN, HTTP_NOT_FOUND, \
|
HTTP_NO_CONTENT, HTTP_UNAUTHORIZED, HTTP_FORBIDDEN, HTTP_NOT_FOUND, \
|
||||||
@@ -44,11 +44,12 @@ from swift3.controllers import ServiceController, BucketController, \
|
|||||||
UnsupportedController, S3AclController
|
UnsupportedController, S3AclController
|
||||||
from swift3.response import AccessDenied, InvalidArgument, InvalidDigest, \
|
from swift3.response import AccessDenied, InvalidArgument, InvalidDigest, \
|
||||||
RequestTimeTooSkewed, Response, SignatureDoesNotMatch, \
|
RequestTimeTooSkewed, Response, SignatureDoesNotMatch, \
|
||||||
BucketAlreadyExists, BucketNotEmpty, EntityTooLarge, \
|
BucketAlreadyOwnedByYou, BucketNotEmpty, EntityTooLarge, \
|
||||||
InternalError, NoSuchBucket, NoSuchKey, PreconditionFailed, InvalidRange, \
|
InternalError, NoSuchBucket, NoSuchKey, PreconditionFailed, InvalidRange, \
|
||||||
MissingContentLength, InvalidStorageClass, S3NotImplemented, InvalidURI, \
|
MissingContentLength, InvalidStorageClass, S3NotImplemented, InvalidURI, \
|
||||||
MalformedXML, InvalidRequest, RequestTimeout, InvalidBucketName, \
|
MalformedXML, InvalidRequest, RequestTimeout, InvalidBucketName, \
|
||||||
BadDigest, AuthorizationHeaderMalformed, AuthorizationQueryParametersError
|
BadDigest, AuthorizationHeaderMalformed, \
|
||||||
|
AuthorizationQueryParametersError, BucketAlreadyExists
|
||||||
from swift3.exception import NotS3Request, BadSwiftRequest
|
from swift3.exception import NotS3Request, BadSwiftRequest
|
||||||
from swift3.utils import utf8encode, LOGGER, check_path_header, S3Timestamp, \
|
from swift3.utils import utf8encode, LOGGER, check_path_header, S3Timestamp, \
|
||||||
mktime, MULTIUPLOAD_SUFFIX
|
mktime, MULTIUPLOAD_SUFFIX
|
||||||
@@ -1060,6 +1061,15 @@ class Request(swob.Request):
|
|||||||
|
|
||||||
return code_map[method]
|
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):
|
def _swift_error_codes(self, method, container, obj, env, app):
|
||||||
"""
|
"""
|
||||||
Returns a dict from expected Swift error codes to the corresponding S3
|
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),
|
HTTP_NOT_FOUND: (NoSuchBucket, container),
|
||||||
},
|
},
|
||||||
'PUT': {
|
'PUT': {
|
||||||
HTTP_ACCEPTED: (BucketAlreadyExists, container),
|
HTTP_ACCEPTED: (self._bucket_put_accepted_error, container,
|
||||||
|
app),
|
||||||
|
HTTP_FORBIDDEN: (BucketAlreadyExists, container),
|
||||||
},
|
},
|
||||||
'POST': {
|
'POST': {
|
||||||
HTTP_NOT_FOUND: (NoSuchBucket, container),
|
HTTP_NOT_FOUND: (NoSuchBucket, container),
|
||||||
|
|||||||
@@ -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_readacp: {status: KNOWN}
|
||||||
s3tests.functional.test_s3.test_bucket_acl_xml_write: {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_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_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: {status: KNOWN}
|
||||||
s3tests.functional.test_s3.test_bucket_list_objects_anonymous_fail: {status: KNOWN}
|
s3tests.functional.test_s3.test_bucket_list_objects_anonymous_fail: {status: KNOWN}
|
||||||
|
|||||||
@@ -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_email_notexist: {status: KNOWN}
|
||||||
s3tests.functional.test_s3.test_bucket_acl_grant_nonexist_user: {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_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_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: {status: KNOWN}
|
||||||
s3tests.functional.test_s3.test_bucket_list_objects_anonymous_fail: {status: KNOWN}
|
s3tests.functional.test_s3.test_bucket_list_objects_anonymous_fail: {status: KNOWN}
|
||||||
|
|||||||
@@ -16,7 +16,8 @@
|
|||||||
import unittest
|
import unittest
|
||||||
import os
|
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.test.functional.utils import get_error_code
|
||||||
from swift3.etree import fromstring, tostring, Element, SubElement
|
from swift3.etree import fromstring, tostring, Element, SubElement
|
||||||
from swift3.cfg import CONF
|
from swift3.cfg import CONF
|
||||||
@@ -140,6 +141,10 @@ class TestSwift3Bucket(Swift3FunctionalTestCase):
|
|||||||
|
|
||||||
self.conn.make_request('PUT', 'bucket')
|
self.conn.make_request('PUT', 'bucket')
|
||||||
status, headers, body = 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')
|
self.assertEqual(get_error_code(body), 'BucketAlreadyExists')
|
||||||
|
|
||||||
def test_put_bucket_with_LocationConstraint(self):
|
def test_put_bucket_with_LocationConstraint(self):
|
||||||
|
|||||||
@@ -469,9 +469,9 @@ class TestSwift3Bucket(Swift3TestCase):
|
|||||||
code = self._test_method_error('PUT', '/bucket', swob.HTTPUnauthorized)
|
code = self._test_method_error('PUT', '/bucket', swob.HTTPUnauthorized)
|
||||||
self.assertEqual(code, 'SignatureDoesNotMatch')
|
self.assertEqual(code, 'SignatureDoesNotMatch')
|
||||||
code = self._test_method_error('PUT', '/bucket', swob.HTTPForbidden)
|
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')
|
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)
|
code = self._test_method_error('PUT', '/bucket', swob.HTTPServerError)
|
||||||
self.assertEqual(code, 'InternalError')
|
self.assertEqual(code, 'InternalError')
|
||||||
code = self._test_method_error(
|
code = self._test_method_error(
|
||||||
|
|||||||
Reference in New Issue
Block a user