Merge branch 'master' into bucket-name-length-limit
This commit is contained in:
commit
e681f55ba1
58 changed files with 2794 additions and 277 deletions
|
|
@ -179,7 +179,7 @@ class InvalidStorageClass(S3ClientError):
|
|||
"The storage class you specified is not valid",
|
||||
*args, **kwargs)
|
||||
|
||||
|
||||
|
||||
class InvalidBucketName(S3ClientError):
|
||||
code = 400
|
||||
|
||||
|
|
@ -187,4 +187,13 @@ class InvalidBucketName(S3ClientError):
|
|||
super(InvalidBucketName, self).__init__(
|
||||
"InvalidBucketName",
|
||||
"The specified bucket is not valid.",
|
||||
|
||||
|
||||
class DuplicateTagKeys(S3ClientError):
|
||||
code = 400
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(DuplicateTagKeys, self).__init__(
|
||||
"InvalidTag",
|
||||
"Cannot provide multiple Tags with the same key",
|
||||
*args, **kwargs)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ from bisect import insort
|
|||
from moto.core import BaseBackend, BaseModel
|
||||
from moto.core.utils import iso_8601_datetime_with_milliseconds, rfc_1123_datetime
|
||||
from .exceptions import BucketAlreadyExists, MissingBucket, InvalidBucketName, InvalidPart, \
|
||||
EntityTooSmall, MissingKey, InvalidNotificationDestination, MalformedXML, InvalidStorageClass
|
||||
EntityTooSmall, MissingKey, InvalidNotificationDestination, MalformedXML, InvalidStorageClass, DuplicateTagKeys
|
||||
from .utils import clean_key_name, _VersionedKeyStore
|
||||
|
||||
MAX_BUCKET_NAME_LENGTH = 63
|
||||
|
|
@ -777,6 +777,9 @@ class S3Backend(BaseBackend):
|
|||
return key
|
||||
|
||||
def put_bucket_tagging(self, bucket_name, tagging):
|
||||
tag_keys = [tag.key for tag in tagging.tag_set.tags]
|
||||
if len(tag_keys) != len(set(tag_keys)):
|
||||
raise DuplicateTagKeys()
|
||||
bucket = self.get_bucket(bucket_name)
|
||||
bucket.set_tags(tagging)
|
||||
|
||||
|
|
|
|||
|
|
@ -193,7 +193,13 @@ class ResponseObject(_TemplateEnvironmentMixin):
|
|||
elif 'location' in querystring:
|
||||
bucket = self.backend.get_bucket(bucket_name)
|
||||
template = self.response_template(S3_BUCKET_LOCATION)
|
||||
return template.render(location=bucket.location)
|
||||
|
||||
location = bucket.location
|
||||
# us-east-1 is different - returns a None location
|
||||
if location == DEFAULT_REGION_NAME:
|
||||
location = None
|
||||
|
||||
return template.render(location=location)
|
||||
elif 'lifecycle' in querystring:
|
||||
bucket = self.backend.get_bucket(bucket_name)
|
||||
if not bucket.rules:
|
||||
|
|
@ -432,8 +438,19 @@ class ResponseObject(_TemplateEnvironmentMixin):
|
|||
|
||||
else:
|
||||
if body:
|
||||
# us-east-1, the default AWS region behaves a bit differently
|
||||
# - you should not use it as a location constraint --> it fails
|
||||
# - querying the location constraint returns None
|
||||
try:
|
||||
region_name = xmltodict.parse(body)['CreateBucketConfiguration']['LocationConstraint']
|
||||
forced_region = xmltodict.parse(body)['CreateBucketConfiguration']['LocationConstraint']
|
||||
|
||||
if forced_region == DEFAULT_REGION_NAME:
|
||||
raise S3ClientError(
|
||||
'InvalidLocationConstraint',
|
||||
'The specified location-constraint is not valid'
|
||||
)
|
||||
else:
|
||||
region_name = forced_region
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
|
|
@ -1176,7 +1193,7 @@ S3_DELETE_BUCKET_WITH_ITEMS_ERROR = """<?xml version="1.0" encoding="UTF-8"?>
|
|||
</Error>"""
|
||||
|
||||
S3_BUCKET_LOCATION = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<LocationConstraint xmlns="http://s3.amazonaws.com/doc/2006-03-01/">{{ location }}</LocationConstraint>"""
|
||||
<LocationConstraint xmlns="http://s3.amazonaws.com/doc/2006-03-01/">{% if location != None %}{{ location }}{% endif %}</LocationConstraint>"""
|
||||
|
||||
S3_BUCKET_LIFECYCLE_CONFIGURATION = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<LifecycleConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue