【发布时间】: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