S3 - get_object() should error for Glacier-class (#4523)
This commit is contained in:
parent
4d1eb2c8db
commit
ccd216dfe5
@ -26,6 +26,10 @@ ERROR_WITH_RANGE = """{% extends 'single_error' %}
|
|||||||
<RangeRequested>{{ range_requested }}</RangeRequested>{% endblock %}
|
<RangeRequested>{{ range_requested }}</RangeRequested>{% endblock %}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
ERROR_WITH_STORAGE_CLASS = """{% extends 'single_error' %}
|
||||||
|
{% block extra %}<StorageClass>{{ storage_class }}</StorageClass>{% endblock %}
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class S3ClientError(RESTError):
|
class S3ClientError(RESTError):
|
||||||
# S3 API uses <RequestID> as the XML tag in response messages
|
# S3 API uses <RequestID> as the XML tag in response messages
|
||||||
@ -501,6 +505,20 @@ class InvalidContinuationToken(S3ClientError):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidObjectState(BucketError):
|
||||||
|
code = 400
|
||||||
|
|
||||||
|
def __init__(self, storage_class, **kwargs):
|
||||||
|
kwargs.setdefault("template", "storage_error")
|
||||||
|
self.templates["storage_error"] = ERROR_WITH_STORAGE_CLASS
|
||||||
|
super(BucketError, self).__init__(
|
||||||
|
error_type="InvalidObjectState",
|
||||||
|
message="The operation is not valid for the object's storage class",
|
||||||
|
storage_class=storage_class,
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class LockNotEnabled(S3ClientError):
|
class LockNotEnabled(S3ClientError):
|
||||||
code = 400
|
code = 400
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ from .exceptions import (
|
|||||||
IllegalLocationConstraintException,
|
IllegalLocationConstraintException,
|
||||||
InvalidNotificationARN,
|
InvalidNotificationARN,
|
||||||
InvalidNotificationEvent,
|
InvalidNotificationEvent,
|
||||||
|
InvalidObjectState,
|
||||||
ObjectNotInActiveTierError,
|
ObjectNotInActiveTierError,
|
||||||
NoSystemTags,
|
NoSystemTags,
|
||||||
PreconditionFailed,
|
PreconditionFailed,
|
||||||
@ -1356,6 +1357,8 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
|
|||||||
elif key is None:
|
elif key is None:
|
||||||
raise MissingVersion()
|
raise MissingVersion()
|
||||||
|
|
||||||
|
if key.storage_class == "GLACIER":
|
||||||
|
raise InvalidObjectState(storage_class="GLACIER")
|
||||||
if if_unmodified_since:
|
if if_unmodified_since:
|
||||||
if_unmodified_since = str_to_rfc_1123_datetime(if_unmodified_since)
|
if_unmodified_since = str_to_rfc_1123_datetime(if_unmodified_since)
|
||||||
if key.last_modified > if_unmodified_since:
|
if key.last_modified > if_unmodified_since:
|
||||||
|
@ -247,3 +247,22 @@ def test_s3_copy_object_for_deep_archive_storage_class_restored():
|
|||||||
s3.head_object(Bucket="Bucket2", Key="Second_Object").should.not_have.property(
|
s3.head_object(Bucket="Bucket2", Key="Second_Object").should.not_have.property(
|
||||||
"Restore"
|
"Restore"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_s3
|
||||||
|
def test_s3_get_object_from_glacier():
|
||||||
|
s3 = boto3.client("s3", region_name="us-east-1")
|
||||||
|
bucket_name = "tests3getobjectfromglacier"
|
||||||
|
s3.create_bucket(Bucket=bucket_name)
|
||||||
|
|
||||||
|
s3.put_object(
|
||||||
|
Bucket=bucket_name, Key="test.txt", Body="contents", StorageClass="GLACIER"
|
||||||
|
)
|
||||||
|
with pytest.raises(ClientError) as exc:
|
||||||
|
s3.get_object(Bucket=bucket_name, Key="test.txt")
|
||||||
|
err = exc.value.response["Error"]
|
||||||
|
err["Code"].should.equal("InvalidObjectState")
|
||||||
|
err["Message"].should.equal(
|
||||||
|
"The operation is not valid for the object's storage class"
|
||||||
|
)
|
||||||
|
err["StorageClass"].should.equal("GLACIER")
|
||||||
|
Loading…
Reference in New Issue
Block a user