【问题标题】:S3 object still in bucket after successfully deleting it and the delete marker成功删除 S3 对象和删除标记后仍在存储桶中
【发布时间】:2020-11-23 01:54:25
【问题描述】:

我已经构建了这个上下文管理器来在 S3 中创建一个临时对象用于测试目的:

from types import TracebackType
from typing import BinaryIO, Optional, Type

import boto3


class S3Object:
    def __init__(self, file_object: BinaryIO, bucket_name: str, key: str):
        self.file_object = file_object
        self.bucket_name = bucket_name
        self.key = key
        self.s3 = boto3.client("s3")

    def __enter__(self) -> "S3Object":
        self.s3.upload_fileobj(self.file_object, self.bucket_name, self.key)
        return self

    def __exit__(
        self,
        exc_type: Optional[Type[BaseException]],
        exc_val: Optional[BaseException],
        exc_tb: Optional[TracebackType],
    ) -> bool:
        delete_object_response = self.s3.delete_object(Bucket=self.bucket_name, Key=self.key)
        # Delete version marker
        self.s3.delete_object(
            Bucket=self.bucket_name, Key=self.key, VersionId=delete_object_response["VersionId"]
        )
        print("Deleted object")  # debugging
        return False  # Propagate exception

我在单个测试中这样使用它:

with S3Object(BytesIO(), bucket_name, filename) as s3_object:
    …

奇怪的是,即使测试输出包含“已删除对象”调试输出,原始项目仍在存储桶中。来自cdk destroy 输出:

您尝试删除的存储桶不为空。您必须删除存储桶中的所有版本。

这绝对是正确的文件,因为我根据测试名称生成了一个唯一的文件名。这似乎也不是时间问题,因为这是 100% 可重现的。

我可以手动删除文件,所以似乎也没有任何特殊保护。

修改代码以打印两个响应后,我想知道我是否只是删除了两次删除标记?为便于阅读而缩写:

{'ResponseMetadata': {'HTTPStatusCode': 204, 'HTTPHeaders': {'x-amz-version-id': 'd08uv05t7lU7YKle4kMSURa_jrMU.GSL', 'x-amz-delete-marker': 'true'}}, 'DeleteMarker': True, 'VersionId': 'd08uv05t7lU7YKle4kMSURa_jrMU.GSL'}
{'ResponseMetadata': {'HTTPStatusCode': 204, 'HTTPHeaders': {'x-amz-version-id': 'd08uv05t7lU7YKle4kMSURa_jrMU.GSL', 'x-amz-delete-marker': 'true'}}, 'DeleteMarker': True, 'VersionId': 'd08uv05t7lU7YKle4kMSURa_jrMU.GSL'}

【问题讨论】:

  • 也许我看错了,但要永久删除版本化对象,请删除对象版本 ID。您似乎正在删除插入删除标记并将其版本 ID 返回给您的对象(无版本),然后您删除了删除标记,这实际上使对象恢复了生机。
  • 我认为@jarmod 是正确的。如果您想永久删除对象并且只进行一次 API 调用并提供版本 ID,则应使用 ListObjectVersions:docs.aws.amazon.com/AmazonS3/latest/API/…

标签: amazon-web-services amazon-s3 boto3 aws-cdk


【解决方案1】:

基于 cmets 和 another answer 我最终得到了这个:

from types import TracebackType
from typing import BinaryIO, Optional, Type

import boto3

DELETE_OBJECTS_MAX_KEYS = 1000


class S3Object:
    def __init__(self, file_object: BinaryIO, bucket_name: str, key: str):
        self.file_object = file_object
        self.bucket_name = bucket_name
        self.key = key
        self.s3 = boto3.client("s3")

    def __enter__(self) -> "S3Object":
        self.s3.upload_fileobj(self.file_object, self.bucket_name, self.key)
        return self

    def __exit__(
        self,
        exc_type: Optional[Type[BaseException]],
        exc_val: Optional[BaseException],
        exc_tb: Optional[TracebackType],
    ) -> bool:
        version_list = []
        object_versions_paginator = self.s3.get_paginator("list_object_versions")
        for object_versions_page in object_versions_paginator.paginate(Bucket=self.bucket_name):
            for marker in object_versions_page.get("DeleteMarkers", []):
                if marker["Key"] == self.key:
                    version_list.append({"Key": self.key, "VersionId": marker["VersionId"]})
            for version in object_versions_page.get("Versions", []):
                if version["Key"] == self.key:
                    version_list.append({"Key": self.key, "VersionId": version["VersionId"]})

        for index in range(0, len(version_list), DELETE_OBJECTS_MAX_KEYS):
            response = self.s3.delete_objects(
                Bucket=self.bucket_name,
                Delete={
                    "Objects": version_list[index : index + DELETE_OBJECTS_MAX_KEYS],
                },
            )
            print(response)

        return False  # Propagate exception

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-20
    • 2013-08-23
    • 2012-05-16
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    相关资源
    最近更新 更多