Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Amazon web services 我可以强制CloudFormation删除非空的S3存储桶吗?_Amazon Web Services_Amazon S3_Aws Cli - Fatal编程技术网

Amazon web services 我可以强制CloudFormation删除非空的S3存储桶吗?

Amazon web services 我可以强制CloudFormation删除非空的S3存储桶吗?,amazon-web-services,amazon-s3,aws-cli,Amazon Web Services,Amazon S3,Aws Cli,有没有办法强制CloudFormation删除一个非空的S3存储桶?您可以创建一个lambda函数来清理您的存储桶,并使用自定义资源从CloudFormation堆栈调用lambda 下面是一个清洁铲斗的lambda示例: #!/usr/bin/env python # -*- coding: utf-8 -*- import json import boto3 from botocore.vendored import requests def lambda_handler(event,

有没有办法强制CloudFormation删除一个非空的S3存储桶?

您可以创建一个lambda函数来清理您的存储桶,并使用自定义资源从CloudFormation堆栈调用lambda

下面是一个清洁铲斗的lambda示例:

#!/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))
创建上面的lambda后,只需将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
请记住将具有从bucket中删除对象权限的角色附加到lambda

此外,请记住,可以使用lambda函数cli2cloudformation创建接受CLI命令行的lambda函数。您可以从下载和安装。使用它,您只需创建一个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在错误的资源中,至少它对我来说没有正常工作,因为在堆栈删除(通过控制台),它将尝试首先强制删除存储桶,这将失败,然后尝试删除自定义资源,这将触发lambda清空存储桶。这将清空bucket,但堆栈删除将失败,因为它试图在bucket为空之前删除它。我们想先启动自定义资源删除,然后在自定义资源删除后尝试删除bucket,所以我这样做,它对我有效:

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
通过这种方式,您可以确保不会首先删除bucket,因为有另一个资源依赖于它,因此首先删除依赖的资源(这会触发lambda清空bucket),然后删除bucket。
希望有人觉得它有用。

你应该清空这个桶:

$ aws s3 rm s3://bucket-name --recursive
然后删除Bucket

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

botocore.vendored已弃用,将于2021/01/30后从Lambda中删除

这是一个更新版本

Type: AWS::Lambda::Function
Properties:
  Code: 
    ZipFile: 
      !Sub |
        import json, boto3, logging
        import cfnresponse
        logger = logging.getLogger()
        logger.setLevel(logging.INFO)

        def lambda_handler(event, context):
            logger.info("event: {}".format(event))
            try:
                bucket = event['ResourceProperties']['BucketName']
                logger.info("bucket: {}, event['RequestType']: {}".format(bucket,event['RequestType']))
                if event['RequestType'] == 'Delete':
                    s3 = boto3.resource('s3')
                    bucket = s3.Bucket(bucket)
                    for obj in bucket.objects.filter():
                        logger.info("delete obj: {}".format(obj))
                        s3.Object(bucket.name, obj.key).delete()

                sendResponseCfn(event, context, cfnresponse.SUCCESS)
            except Exception as e:
                logger.info("Exception: {}".format(e))
                sendResponseCfn(event, context, cfnresponse.FAILED)

        def sendResponseCfn(event, context, responseStatus):
            responseData = {}
            responseData['Data'] = {}
            cfnresponse.send(event, context, responseStatus, responseData, "CustomResourcePhysicalID")            

  Handler: "index.lambda_handler"
  Runtime: python3.7
  MemorySize: 128
  Timeout: 60
  Role: !GetAtt TSIemptyBucketOnDeleteFunctionRole.Arn    

在Python3.8上使用它需要一点时间,所以我将与社区分享它

Python 3.8 lambda不再支持botocore.vendored导入请求的

您可以使用下面的代码通知Cloudformation

import urllib

request = urllib.request.Request(event['ResponseURL'],
                                 method="PUT",
                                 data=json.dumps(response_body).encode('utf-8'),
                                 headers={'Content-Type': "''"})

with urllib.request.urlopen(request) as response:
    print("Status code: " + response.reason)

另一个小提示:当lambda从cloudformation接收到
create
请求时,您可以在PhysicalResourceId响应中输入任何唯一的值。当它是更新/删除时,您也会从CloudFormation收到该参数,并且您必须重用响应中输入的值。

这是处理从CloudFormation中删除bucket的一个很好的方法,但我认为答案是否定的-因此我不能将其标记为答案(但我确实投了反对票)-谢谢关于这个主题的更深入的博文:@JamieCzuy:这是一个有效的答案。您应该将其标记为解析器。事实上,在cloudformation(CFN定制资源)的上下文中,还有一个第三方软件包,它利用了NPM,并通过NPM提供,这样做可以避免您自己编写:我同意这一点。您还可以通过将BucketName作为Bucket的引用来避免DependsOn,如下所示:BucketName:!参考Mybucketresource,这是真的。我修好了感谢OP问是否有办法不必这么做。