Могу ли я заставить CloudFormation удалить непустую ведро S3?

Есть ли способ заставить CloudFormation удалить непустую ведро S3?

Ответы

Ответ 1

Вы можете создать лямбда-функцию для очистки вашей корзины и вызова лямбды из стека CloudFormation с помощью CustomResource.

Ниже лямбда-пример очистки вашего ведра:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import json
import boto3
from botocore.vendored import requests


def lambda_handler(event, context):
    try:
        bucket = event['ResourceProperties']['BucketName']

        if event['RequestType'] == 'Delete':
            s3 = boto3.resource('s3')
            bucket = s3.Bucket(bucket)
            for obj in bucket.objects.filter():
                s3.Object(bucket.name, obj.key).delete()

        sendResponseCfn(event, context, "SUCCESS")
    except Exception as e:
        print(e)
        sendResponseCfn(event, context, "FAILED")


def sendResponseCfn(event, context, responseStatus):
    response_body = {'Status': responseStatus,
                     'Reason': 'Log stream name: ' + context.log_stream_name,
                     'PhysicalResourceId': context.log_stream_name,
                     'StackId': event['StackId'],
                     'RequestId': event['RequestId'],
                     'LogicalResourceId': event['LogicalResourceId'],
                     'Data': json.loads("{}")}

    requests.put(event['ResponseURL'], data=json.dumps(response_body))

После того, как вы создадите лямбду выше, просто поместите CustomResource в ваш стек CloudFormation:

 ---
 AWSTemplateFormatVersion: '2010-09-09'

 Resources:

   myBucketResource:
     Type: AWS::S3::Bucket
     Properties:
       BucketName: my-test-bucket-cleaning-on-delete

   cleanupBucketOnDelete:
     Type: Custom::cleanupbucket
     Properties:
       ServiceToken: arn:aws:lambda:eu-west-1:123456789012:function:clean-bucket-lambda
       BucketName: !Ref myBucketResource

Не забудьте прикрепить роль к вашей лямбде, которая имеет разрешение на удаление объектов из вашего ведра.

Кроме того, имейте в виду, что вы можете создать лямбда-функцию, которая принимает командную строку CLI, используя лямбда-функцию cli2cloudformation. Вы можете скачать и установить здесь. Для этого вам просто нужно создать CustomResource, как показано ниже:

"removeBucket": {
        "Type": "Custom::cli2cloudformation",
        "Properties": {
          "ServiceToken": "arn:aws:lambda:eu-west-1:123456789000:function:custom-lambda-name",
          "CliCommandDelete": "aws s3 rb s3://bucket-name --force",
        }
}

Ответ 2

Нет, я не думаю, что это можно сделать. Этот документ подтверждает это.

Ответ 3

Я думаю, что ваш DependsOn находится в неправильном ресурсе, по крайней мере, он не работал для меня должным образом, потому что при удалении стека (через консоль), он попытается сначала принудительно удалить удаление корзины, а затем попытается удалить пользовательский ресурс, который вызывает лямбда для опорожнения ведра. Это опустошит корзину, но удаление стека не удастся, потому что она попыталась удалить корзину до того, как она была пуста. Мы хотим сначала инициировать удаление пользовательского ресурса, а затем пытаться удалить корзину после удаления пользовательского ресурса, поэтому я сделал это следующим образом, и он работает для меня:

myBucketResource:
  Type: AWS::S3::Bucket
  Properties:
    BucketName: my-test-bucket-cleaning-on-delete

cleanupBucketOnDelete:
  Type: Custom::cleanupbucket
  Properties:
    ServiceToken: arn:aws:lambda:eu-west-1:123456789012:function:clean-bucket-lambda
    BucketName: my-test-bucket-cleaning-on-delete
  DependsOn: myBucketResource

Таким образом, вы гарантируете, что удаление корзины не будет первым, потому что есть другой ресурс, который зависит от него, следовательно, зависимый ресурс сначала удаляется (который запускает лямбду, чтобы очистить корзину), а затем корзина удаляется. Надеюсь, кто-то найдет это полезным.

Ответ 4

Что ж

как насчет этого:

import boto3

s3 = boto3.client('s3')
res = boto3.resource('s3')

buckets = s3.list_buckets()

try:
    for bk in buckets['Buckets']:
            bucket = res.Bucket(bk['Name'])
            bucket.objects.all().delete()
            bucket.delete()

except Exception as e:
    print e

Ответ 5

Вы должны очистить ведро:

$ aws s3 rm s3://bucket-name --recursive

Затем удалите Bucket

$ aws cloudformation delete-stack --stack-name mys3stack