Aws lambda Amazon Cloudformation堆栈在Lambda函数完成后挂起

Aws lambda Amazon Cloudformation堆栈在Lambda函数完成后挂起,aws-lambda,amazon-cloudformation,Aws Lambda,Amazon Cloudformation,我有一个简单的模板来创建一个S3 bucket,然后调用Lambda函数将一个对象从公共bucket复制到它: AWSTemplateFormatVersion: 2010-09-09 Transform: AWS::Serverless-2016-10-31 Description: Create an S3 Bucket, populate it with a copy of a sample CSV file Parameters: bucketname: Type: Stri

我有一个简单的模板来创建一个S3 bucket,然后调用Lambda函数将一个对象从公共bucket复制到它:

AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Description: Create an S3 Bucket, populate it with a copy of a sample CSV file
Parameters:
  bucketname:
    Type: String
    Description: Name of bucket where the CSV file will be bootstrapped, bucket names MUST be unique across AWS and no Upper Case characters - 8 or more characters
    MinLength: 8
Outputs:
  bucketURL:
    Value:
      Fn::Join:
        - ''
        - - 'https://s3.amazonaws.com/'
          - !Ref bucketname
Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain
    Properties:
      BucketName: !Ref bucketname
  deploytos3:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs12.x
      CodeUri: 's3://mongodb-aws-jam/lambdaDeploy.zip'
      Policies:
        - AWSLambdaBasicExecutionRole
        - AmazonS3FullAccess
  DeploymentCustomResource:
    Type: Custom::deploytos3
    Properties:
      ServiceToken: !GetAtt deploytos3.Arn
      bucketname: !Ref bucketname
这是Lambda函数:

const AWS = require('aws-sdk');
var response = require('cfn-response');

const s3 = new AWS.S3();
const srcBucket = "mongodb-aws-jam"
const srcKey = "SampleData.csv"

exports.handler = async (event, context) => {
    console.log("start")
    myBucket = event.ResourceProperties['bucketname']
    console.log(`Will bootstrap ${srcKey} object in ${myBucket} bucket`)

    const copyparams = {
        Bucket : myBucket,
        CopySource : `/${srcBucket}/${srcKey}`,
        Key : srcKey
    };

    try {
        await s3.copyObject(copyparams).promise();
    } catch (error) {
        const errorText = `Failed to copy file to ${myBucket}/${srcKey}: error`
        console.log(errorText)
        // callback(null, {statusCode: 500, body: errorText})
        response.send(event, context, response.FAILED, {Error: errorText})
        return
    }
    resultText = `Copied file to ${myBucket}/${srcKey}`
    console.log(resultText)
    // callback(null, {statusCode: 200, body: resultText})
    response.send(event, context, response.SUCCESS, {})
};
堆栈成功地创建和引导了新的bucket,但是堆栈历史显示
DeploymentCustomResource
资源从未超过
CREATE\u in\u PROGRESS
状态,即使lambda日志显示函数已成功完成。我尝试过使用回调的各种替代方法,并将函数简化为不做任何工作,但堆栈总是挂起


有什么建议吗?

由于CloudFormation(CFN)等待函数的正确响应,您的函数陷入了创建过程中。您的代码没有提供它

自定义资源的功能需要特殊设计。必须正确处理CFN事件,并做出相应的响应


对于nodejs中的函数,可以使用助手库
cfn response
,如中所示。nodejs中的custom资源函数的例子有。

我认为问题是因为
handler
是异步的

这是工作功能:

const AWS = require('aws-sdk');
var response = require('cfn-response');

const s3 = new AWS.S3();
const srcBucket = "mongodb-aws-jam"
const srcKey = "SampleData.csv"

exports.handler = async (event, context) => {
    console.log("start")
    myBucket = event.ResourceProperties['bucketname']
    console.log(`Will bootstrap ${srcKey} object in ${myBucket} bucket`)

    const copyparams = {
        Bucket : myBucket,
        CopySource : `/${srcBucket}/${srcKey}`,
        Key : srcKey
    };

    try {
        await s3.copyObject(copyparams).promise();
    } catch (error) {
        const errorText = `Failed to copy file to ${myBucket}/${srcKey}: error`
        console.log(errorText)
        // callback(null, {statusCode: 500, body: errorText})
        response.send(event, context, response.FAILED, {Error: errorText})
        return
    }
    resultText = `Copied file to ${myBucket}/${srcKey}`
    console.log(resultText)
    // callback(null, {statusCode: 200, body: resultText})
    response.send(event, context, response.SUCCESS, {})
};
const AWS=require('AWS-sdk');
const response=require('cfn-response');
const s3=新的AWS.s3();
const srcBucket=“mongodb aws jam”
const srcKey=“SampleData.csv”
exports.handler=函数(事件、上下文){
var bucket=event.ResourceProperties.bucketname;
log(`Bucket:${Bucket}`);
常量copyparams={
桶:桶,
CopySource:`/${srcBucket}/${srcKey}`,
密钥:srcKey
};
s3.copyObject(copyparams.promise())
.然后(()=>{
var responseData={Value:bucket};
控制台日志(“成功”);
response.send(事件、上下文、response.SUCCESS、responseData);
},错误=>{
const errorText=`未能将文件复制到${bucket}/${srcKey}:${error}`
console.log(errorText)
send(事件、上下文、response.FAILED,{Error:errorText})
})
};

我也尝试了
cfn response
,例如
var response=require('cfn-response')。。。response.send(event,context,response.SUCCESS,{})
但自定义资源仍处于
CREATE\u in\u PROGRESS
状态。@AndrewMorgan添加
var response=require('cfn-response')
是不够的。您必须完全重新编写函数以符合CFN自定义资源格式。我建议检查文档和示例如何设计这些函数。我通过调用
response.send(event,context,response.SUCCESS,{})来遵循示例。我在日志中看到
响应正文:{“状态”:“成功”,“原因”:“查看CloudWatch日志流中的详细信息:2020/10/12/[$LATEST]…
。还缺少什么?@AndrewMorgan您可以用新版本的代码更新您的问题吗?@AndrewMorgan我想您已经将
cfn响应
模块与您的函数捆绑在一起了?