it-swarm.com.ru

Удалить все версии объекта в S3, используя python?

У меня есть версионное ведро и я хочу удалить объект (и все его версии) из этого ящика. Однако, когда я пытаюсь удалить объект из консоли, S3 просто добавляет маркер удаления, но не выполняет жесткого удаления. 

Можно ли удалить все версии объекта (hard delete) с определенным ключом ?:

s3resource = boto3.resource('s3')
bucket = s3resource.Bucket('my_bucket')
obj = bucket.Object('my_object_key')

# I would like to delete all versions for the object like so:
obj.delete_all_versions()

# or delete all versions for all objects like so:
bucket.objects.delete_all_versions()
5
mouscous

В качестве дополнения к ответу @jarmod , вот способ, которым я разработал обходной путь к «жесткому удалению» объекта (с включенным удалением отмеченных объектов);

def get_all_versions(bucket, filename):
    s3 = boto3.client('s3')
    keys = ["Versions", "DeleteMarkers"]
    results = []
    for k in keys:
        response = s3.list_object_versions(Bucket=bucket)[k]
        to_delete = [r["VersionId"] for r in response if r["Key"] == filename]
    results.extend(to_delete)
    return results

bucket = "YOUR BUCKET NAME"
file = "YOUR FILE"

for version in get_all_versions(bucket, file):
    s3.delete_object(Bucket=bucket, Key=file, VersionId=version)
0
Mangohero1

У меня были проблемы с использованием других решений этого вопроса, так что вот мое.

import boto3
bucket = "bucket name goes here"
filename = "filename goes here"

client = boto3.client('s3')
paginator = client.get_paginator('list_object_versions')
response_iterator = paginator.paginate(Bucket=bucket)
for response in response_iterator:
    versions = response.get('Versions', [])
    versions.extend(response.get('DeleteMarkers', []))
    for version_id in [x['VersionId'] for x in versions
                       if x['Key'] == filename and x['VersionId'] != 'null']:
        print('Deleting {} version {}'.format(filename, version_id))
        client.delete_object(Bucket=bucket, Key=filename, VersionId=version_id)

Этот код касается случаев, когда

  • управление версиями объекта на самом деле не включено
  • есть DeleteMarker s
  • там нет DeleteMarkers
  • существует больше версий данного файла, чем помещается в одном ответе API

Ответ Махеша Могала не удаляет DeleteMarkers. Mangohero1 ответ терпит неудачу, если объект отсутствует DeleteMarker. ответ Хари повторяется 10 раз (для обхода отсутствующей логики нумерации страниц).

1
gene_wood

документация полезна здесь:

  1. Если в корзине S3 включено управление версиями, простой запрос DeleteObject не может окончательно удалить объект из этой корзины. Вместо этого Amazon S3 вставляет маркер удаления (который фактически является новой версией объекта со своим собственным идентификатором версии).
  2. Когда вы пытаетесь получить объект, текущая версия которого представляет собой маркер удаления, S3 ведет себя так, как будто объект был удален (даже если это не так), и возвращает ошибку 404.
  3. Чтобы окончательно удалить объект из версионной корзины, используйте DeleteObject с соответствующим идентификатором версии для каждой версии объекта (включая маркеры delete ).
1
jarmod

Другие ответы удаляют объекты индивидуально. Более эффективно использовать вызов delete_objects boto3 и выполнить пакетную обработку вашего удаления. Посмотрите код ниже для функции, которая собирает все объекты и удаляет в пакетах по 1000:

bucket = 'bucket-name'
s3_client = boto3.client('s3')
object_response_paginator = s3_client.get_paginator('list_object_versions')

delete_marker_list = []
version_list = []

for object_response_itr in object_response_paginator.paginate(Bucket=bucket):
    if 'DeleteMarkers' in object_response_itr:
        for delete_marker in object_response_itr['DeleteMarkers']:
            delete_marker_list.append({'Key': delete_marker['Key'], 'VersionId': delete_marker['VersionId']})

    if 'Versions' in object_response_itr:
        for version in object_response_itr['Versions']:
            version_list.append({'Key': version['Key'], 'VersionId': version['VersionId']})

for i in range(0, len(delete_marker_list), 1000):
    response = s3_client.delete_objects(
        Bucket=bucket,
        Delete={
            'Objects': delete_marker_list[i:i+1000],
            'Quiet': True
        }
    )
    print(response)

for i in range(0, len(version_list), 1000):
    response = s3_client.delete_objects(
        Bucket=bucket,
        Delete={
            'Objects': version_list[i:i+1000],
            'Quiet': True
        }
    )
    print(response)
1
AndrewC

Этот пост был очень полезным, без этого мы потратили бы огромное количество времени на очистку наших папок S3. 

У нас было требование очищать только определенные папки. Поэтому я попробовал следующий код, и он работал как шарм. Также обратите внимание, что я перебираю 10 раз, чтобы удалить более 1000 объектов, ограниченных этой функцией. Не стесняйтесь изменять лимит по своему желанию. 

import boto3
session = boto3.Session(aws_access_key_id='<YOUR ACCESS KEY>',aws_secret_access_key='<YOUR SECRET KEY>')

bucket_name = '<BUCKET NAME>'
object_name = '<KEY NAME>'

s3 = session.client('s3')

for i in range(10):
   versions = s3.list_object_versions (Bucket = bucket_name, Prefix = object_name)
#print (versions)
   version_list = versions.get('Versions')
   for version in version_list:
      keyName = version.get('Key')
      versionId = version.get('VersionId')
      print (keyName + ':' + versionId)
      s3.delete_object(Bucket = bucket_name, Key= keyName, VersionId = versionId)
   marker_list = versions.get('DeleteMarkers')
#print(marker_list)
   for marker in marker_list:
      keyName1 = marker.get('Key')
      versionId1 = marker.get('VersionId')
      print (keyName1 + ':' + versionId1)
      s3.delete_object(Bucket = bucket_name, Key= keyName1, VersionId = versionId1)
0
Hari

Вы можете удалить объект со всеми его версиями, используя следующий код

session = boto3.Session(aws_access_key_id, aws_secret_access_key)

bucket_name = 'bucket_name'
object_name = 'object_name'

s3 = session.client('s3')

versions = s3.list_object_versions (Bucket = bucket_name, Prefix = object_name)
version_list = versions.get('Versions')
for version in version_list:
    versionId = version.get('VersionId')
    s3.delete_object(Bucket = bucket_name, Key= object_name, VersionId = versionId)
0
Mahesh Mogal