Handle VersionId in S3:delete_objects
VersionId is not read in delete_objects requests, and the behavior differs from its singular counterpart delete_object. This fixes the issue.
This commit is contained in:
parent
cd6dbe5b03
commit
9ed6e52d0a
@ -840,26 +840,33 @@ class ResponseObject(_TemplateEnvironmentMixin, ActionAuthenticatorMixin):
|
|||||||
def _bucket_response_delete_keys(self, request, body, bucket_name):
|
def _bucket_response_delete_keys(self, request, body, bucket_name):
|
||||||
template = self.response_template(S3_DELETE_KEYS_RESPONSE)
|
template = self.response_template(S3_DELETE_KEYS_RESPONSE)
|
||||||
|
|
||||||
keys = minidom.parseString(body).getElementsByTagName("Key")
|
objects = minidom.parseString(body).getElementsByTagName("Object")
|
||||||
deleted_names = []
|
|
||||||
|
deleted_objects = []
|
||||||
error_names = []
|
error_names = []
|
||||||
if len(keys) == 0:
|
if len(objects) == 0:
|
||||||
raise MalformedXML()
|
raise MalformedXML()
|
||||||
|
|
||||||
for k in keys:
|
for object_ in objects:
|
||||||
key_name = k.firstChild.nodeValue
|
key_name = object_.getElementsByTagName("Key")[0].firstChild.nodeValue
|
||||||
|
version_id_node = object_.getElementsByTagName("VersionId")
|
||||||
|
if version_id_node:
|
||||||
|
version_id = version_id_node[0].firstChild.nodeValue
|
||||||
|
else:
|
||||||
|
version_id = None
|
||||||
|
|
||||||
success = self.backend.delete_key(
|
success = self.backend.delete_key(
|
||||||
bucket_name, undo_clean_key_name(key_name)
|
bucket_name, undo_clean_key_name(key_name), version_id=version_id
|
||||||
)
|
)
|
||||||
if success:
|
if success:
|
||||||
deleted_names.append(key_name)
|
deleted_objects.append((key_name, version_id))
|
||||||
else:
|
else:
|
||||||
error_names.append(key_name)
|
error_names.append(key_name)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
200,
|
200,
|
||||||
{},
|
{},
|
||||||
template.render(deleted=deleted_names, delete_errors=error_names),
|
template.render(deleted=deleted_objects, delete_errors=error_names),
|
||||||
)
|
)
|
||||||
|
|
||||||
def _handle_range_header(self, request, headers, response_content):
|
def _handle_range_header(self, request, headers, response_content):
|
||||||
@ -1861,9 +1868,10 @@ S3_BUCKET_GET_VERSIONS = """<?xml version="1.0" encoding="UTF-8"?>
|
|||||||
|
|
||||||
S3_DELETE_KEYS_RESPONSE = """<?xml version="1.0" encoding="UTF-8"?>
|
S3_DELETE_KEYS_RESPONSE = """<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<DeleteResult xmlns="http://s3.amazonaws.com/doc/2006-03-01">
|
<DeleteResult xmlns="http://s3.amazonaws.com/doc/2006-03-01">
|
||||||
{% for k in deleted %}
|
{% for k, v in deleted %}
|
||||||
<Deleted>
|
<Deleted>
|
||||||
<Key>{{k}}</Key>
|
<Key>{{k}}</Key>
|
||||||
|
{% if v %}<VersionId>{{v}}</VersionId>{% endif %}
|
||||||
</Deleted>
|
</Deleted>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% for k in delete_errors %}
|
{% for k in delete_errors %}
|
||||||
|
@ -2218,6 +2218,29 @@ def test_boto3_deleted_versionings_list():
|
|||||||
assert len(listed["Contents"]) == 1
|
assert len(listed["Contents"]) == 1
|
||||||
|
|
||||||
|
|
||||||
|
@mock_s3
|
||||||
|
def test_boto3_delete_objects_for_specific_version_id():
|
||||||
|
client = boto3.client("s3", region_name=DEFAULT_REGION_NAME)
|
||||||
|
client.create_bucket(Bucket="blah")
|
||||||
|
client.put_bucket_versioning(
|
||||||
|
Bucket="blah", VersioningConfiguration={"Status": "Enabled"}
|
||||||
|
)
|
||||||
|
|
||||||
|
client.put_object(Bucket="blah", Key="test1", Body=b"test1a")
|
||||||
|
client.put_object(Bucket="blah", Key="test1", Body=b"test1b")
|
||||||
|
|
||||||
|
response = client.list_object_versions(Bucket="blah", Prefix="test1")
|
||||||
|
id_to_delete = [v["VersionId"] for v in response["Versions"] if v["IsLatest"]][0]
|
||||||
|
|
||||||
|
response = client.delete_objects(
|
||||||
|
Bucket="blah", Delete={"Objects": [{"Key": "test1", "VersionId": id_to_delete}]}
|
||||||
|
)
|
||||||
|
assert response["Deleted"] == [{"Key": "test1", "VersionId": id_to_delete}]
|
||||||
|
|
||||||
|
listed = client.list_objects_v2(Bucket="blah")
|
||||||
|
assert len(listed["Contents"]) == 1
|
||||||
|
|
||||||
|
|
||||||
@mock_s3
|
@mock_s3
|
||||||
def test_boto3_delete_versioned_bucket():
|
def test_boto3_delete_versioned_bucket():
|
||||||
client = boto3.client("s3", region_name=DEFAULT_REGION_NAME)
|
client = boto3.client("s3", region_name=DEFAULT_REGION_NAME)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user