web-dev-qa-db-ja.com

CloudFormationに空でないS3バケットを強制的に削除できますか?

CloudFormationに空でないS3バケットを強制的に削除する方法はありますか?

29
Jamie Czuy

lambda関数を作成してバケットをクリーンアップし、CustomResourceを使用してCloudFormationスタックからラムダを呼び出すことができます。

バケットをクリーンアップするラムダの例の下:

#!/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))

上記のラムダを作成したら、CloudFormationスタックにCustomResourceを配置します。

 ---
 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

バケットからオブジェクトを削除する権限を持つラムダにロールをアタッチすることを忘れないでください。

さらに、ラムダ関数cli2cloudformationを使用してCLIコマンドラインを受け入れるラムダ関数を作成できることに注意してください。 here からダウンロードしてインストールできます。それを使用して、次のような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",
        }
}

あなたのDependsOnは間違ったリソースにあると思います、少なくともそれはスタックでdeletion(コンソールを介して)、最初にバケットを強制的に削除しようとしますが、失敗してからラムダをトリガーしてバケットを空にするカスタムリソースを削除します。これによりバケットが空になりますが、空になる前にバケットを削除しようとしたため、スタックの削除は失敗します。最初にカスタムリソースの削除を開始し、カスタムリソースが削除された後にバケットを削除しようとするため、次のようにしました。

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

この方法では、バケットに依存する別のリソースがあるため、バケットの削除が最初に行われないようにします。したがって、依存するリソースが最初に削除され(ラムダがバケットを空にする)、その後バケットが削除されます。誰かがそれが役に立つと思うことを願っています。

3
OkayWhatever

バケットを空にする必要があります。

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

次に、バケットを削除します

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

まあ

これはどう:

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
0
VFagundes