Amazon web services Cloud Formation不是引用现有的AWS S3 bucket,而是尝试创建bucket

Amazon web services Cloud Formation不是引用现有的AWS S3 bucket,而是尝试创建bucket,amazon-web-services,amazon-s3,aws-lambda,amazon-cloudformation,Amazon Web Services,Amazon S3,Aws Lambda,Amazon Cloudformation,我陷入了一个奇怪的问题。我使用以下云形成模板创建了一个AWS S3 bucket:- AWSTemplateFormatVersion: '2010-09-09' Metadata: License: Unlicensed Description: > This template creates a global unique S3 bucket in a specific region which is unique. The bucket name is formed

我陷入了一个奇怪的问题。我使用以下云形成模板创建了一个AWS S3 bucket:-

AWSTemplateFormatVersion: '2010-09-09'
Metadata: 
  License: Unlicensed
Description: >
  This template creates a global unique S3 bucket in a specific region which is unique. 
  The bucket name is formed by the environment, account id and region

Parameters:
  # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html
  Environment:
    Description: This paramenter will accept the environment details from the user
    Type: String
    Default: sbx
    AllowedValues:
      - sbx
      - dev
      - qa
      - e2e
      - prod
    ConstraintDescription: Invalid environment. Please select one of the given environments only

Resources:
  # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html
  MyS3Bucket:
      Type: AWS::S3::Bucket
      DeletionPolicy: Retain
      Properties: 
        BucketName: !Sub 'global-bucket-${Environment}-${AWS::Region}-${AWS::AccountId}' # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html
        AccessControl: Private                
        LoggingConfiguration:
          DestinationBucketName: !Ref 'LoggingBucket'
          LogFilePrefix:  'access-logs'
        Tags:
          - Key: name
            Value: globalbucket
          - Key: department
            Value: engineering
  LoggingBucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain
    Properties:
      BucketName: !Sub 'global-loggings-${Environment}-${AWS::Region}-${AWS::AccountId}'
      AccessControl: LogDeliveryWrite      

Outputs:
  GlobalS3Bucket:
    Description: A private S3 bucket with deletion policy as retain and logging configuration
    Value: !Ref MyS3Bucket
    Export:
      Name: global-bucket            
如果您在上面的模板中注意到,那么我将在输出部分以名为全局bucket的名称导出此S3 bucket

现在,我打算在任何新资源(如Lambda等)需要S3 bucket时,在我的AWS帐户中引用这个现有bucket。下面是一个使用AWS SAM(无服务器应用程序模型)的示例,我正在尝试创建一个AWS Lambda,并尝试使用属性引用这个现有的S3 bucket!导入值和导出名称作为全局bucket,如下所示:-

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  hellolambda

  Sample SAM Template for hellolambda
  
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello-world/
      Handler: app.lambdaHandler
      Runtime: nodejs12.x
      Events:
        HelloLambdaEvent:
         Type: S3
         Properties:
            Bucket: !Ref SrcBucket
            Events: s3:ObjectCreated:*
  SrcBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !ImportValue global-bucket
现在,问题是,当我执行sam build和sam deploy-guided这样的命令并选择相同的区域(存在我以前的CloudFormation堆栈输出的地方)时,我会得到以下错误:-

global-bucket-sbx-ap-southeast-1-088853283839已存在于堆栈中arn:aws:cloudformation:ap-southeast-1:088853283839:stack/my-s3-global-bucket/aabd20e0-f57d-11ea-80bf-06f1487f6a64

屏幕截图如下:-

问题是AWS CloudFormation试图创建S3存储桶,而不是引用现有的存储桶

但是,如果我尝试像这样更新此SAM模板,然后执行SAM部署,则会出现以下错误:-

正在等待创建变更集。。 错误:未能为堆栈创建更改集:my lambda堆栈,例如:服务员更改集CreateComplete失败:服务员遇到终端故障状态:失败。原因:转换AWS::Serverless-2016-10-31失败,原因是:无服务器应用程序规范文档无效。发现的错误数:1。id为[HelloWorldFunction]的资源无效。id为[HelloLambdaEvent]的事件无效。S3事件必须引用同一模板中的S3存储桶。

我两头都挡住了。如果有人能帮助我在Lambda中正确编写SAM模板,以便我能够正确引用现有的bucket,而不是创建新的bucket,我将不胜感激


谢谢

资源
部分中列出的任何项目都是指堆栈负责维护的资源

当您列出
SrcBucket
时,您要求CloudFormation创建一个新的S3 bucket,其名称为
的值!ImportValue global bucket
,它是您已经创建的S3 bucket的名称

假设这是bucket名称,您只需在模板中引用它,如下所示

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  hellolambda

  Sample SAM Template for hellolambda
  
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello-world/
      Handler: app.lambdaHandler
      Runtime: nodejs12.x
      Events:
        HelloLambdaEvent:
         Type: S3
         Properties:
            Bucket: !ImportValue global-bucket
            Events: s3:ObjectCreated:*

有了这个,我得到了这个错误:-正在等待变更集被创建。。错误:未能为堆栈创建更改集:my lambda堆栈,例如:服务员更改集CreateComplete失败:服务员遇到终端故障状态:失败。原因:转换AWS::Serverless-2016-10-31失败,原因是:无服务器应用程序规范文档无效。发现的错误数:1。id为[HelloWorldFunction]的资源无效。id为[HelloLambdaEvent]的事件无效。S3事件必须引用同一模板中的S3 bucket。不幸的是,如果限制是它必须在同一个bucket中,则需要使用(替换无服务器函数资源)或使用该bucket和所有Lambda函数共享模板,我不明白…你能给我一些参考指针…让我检查一下…我如何在正常的lambda函数中使用无服务器lambda中的事件?对,所以这有点棘手。S3事件本身连接到S3资源,这意味着当您想要重用S3存储桶本身时,实际上需要遵循不同的路径。如果您没有特别绑定到S3事件,那么可以使用CloudWatch事件。看一看。您可以将目标设置为Lambda。此处的文档包括一个目标为Lambda的示例:这是否回答了您的问题?