wake-up-neo.com

Kann ich CloudFormation zwingen, nicht leeren S3-Bucket zu löschen?

Gibt es eine Möglichkeit, CloudFormation zum Löschen eines nicht leeren S3-Buckets zu zwingen?

18
Jamie Czuy

Sie können eine lambda-Funktion erstellen, um Ihren Bucket aufzuräumen und Ihr Lambda mithilfe eines CustomResource aus Ihrem CloudFormation-Stack aufzurufen.

Nachfolgend ein Lambda-Beispiel für die Reinigung Ihres Eimers:

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

Nachdem Sie das Lambda oben erstellt haben, fügen Sie einfach die CustomResource in Ihren CloudFormation-Stapel ein:

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

 Resources:

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

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

Denken Sie daran, Ihrem Lambda eine Rolle beizufügen, die berechtigt ist, Objekte aus dem Bucket zu entfernen.

Denken Sie außerdem daran, dass Sie eine Lambda-Funktion erstellen können, die die CLI-Befehlszeile akzeptiert, indem Sie die Lambda-Funktion cli2cloudformation verwenden. Sie können von hier herunterladen und installieren. Um dies zu erreichen, müssen Sie einfach eine CustomResource wie folgt erstellen:

"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",
        }
}

Ich glaube, Ihr DependsOn ist in einer falschen Ressource, zumindest hat es nicht richtig für mich funktioniert, da es auf Stack Deletion (über die Konsole) versuchen würde, zuerst den Bucket-Löschvorgang zu erzwingen, der fehlschlägt und anschließend versucht, die benutzerdefinierte Ressource zu löschen , wodurch der Lambda den Eimer entleert. Dadurch wird der Bucket geleert. Das Löschen des Stapels schlägt jedoch fehl, da versucht wurde, den Bucket zu löschen, bevor er leer war. Wir möchten zuerst das Löschen von benutzerdefinierten Ressourcen einleiten und dann versuchen, den Bucket zu löschen, nachdem die benutzerdefinierte Ressource gelöscht wurde. Deshalb habe ich es so gemacht und es funktioniert für mich:

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

Auf diese Weise stellen Sie sicher, dass das Löschen des Buckets nicht an erster Stelle steht, da es eine andere Ressource gibt, die davon abhängt. Daher wird zuerst die abhängige Ressource gelöscht (die das Lambda auslöst, um den Bucket zu leeren). Anschließend wird der Bucket gelöscht es ist hilfreich.

1
OkayWhatever

Gut

wie wäre es damit:

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

Sie sollten den Eimer leeren:

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

Dann löschen Sie den Eimer

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