AWS CloudFormation 自定义 lambda 函数卡在创建状态

AWS CloudFormation custom lambda function stuck in create state

我正在尝试使用从 lambda 函数返回的值。 CloudFormation 自定义资源;然而,当我尝试时,CloudFormation 自定义资源无限地停留在等待状态。

以下是我正在尝试的 Lambda 节点代码

exports.handler = function(event, context) {
  var date = new Date();
  var current_hour = date.getHours();
  console.log("START :: " + current_hour);

    console.log("END :: " + current_hour);
    data = {
        "val1" : "val1",
        "val2" : "val2"
    };

    result = {
      "Status" : "SUCCESS",
      "Reason" : "Success Reason",
      "PhysicalResourceId" : "LambdaCustomDelayFunction",
      "StackId" : event.StackId,
      "RequestId" : event.RequestId,
      "LogicalResourceId" : event.LogicalResourceId,
      "Data" : data
    };
    console.log('---Event---');
    console.log(event);
    console.log('---Context---');
    console.log(context);
    console.log('---Result---');
    console.log(result);

    context.done(null, result);
};

以下 CloudFormation 脚本,我正在尝试使用 lambda

"DelayFunction" : {
      "Type" : "Custom::Delayer",
      "Properties" : {
        "ServiceToken" : "arn:aws:lambda:us-east-1-123456778:function:delayfunction"
      }
      },
"MySG": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "GroupDescription": " Server SG 1",
        "VpcId": {
          "Ref": "VPC"
        },
        "SecurityGroupIngress": [
          {
            "IpProtocol": "-1",
            "CidrIp": "10.0.0.0/16"
          }
        ],
        "SecurityGroupEgress": [
          {
            "IpProtocol": "-1",
            "CidrIp": "0.0.0.0/0"
          }
        ],
        "Tags": [
          {
            "Key": "Name",
            "Value": "SG 1"
          },
          {"Key":"Lambda", "Value":{ "Fn::GetAtt" : ["DelayFunction", "val1"]}} <------ Trying to retrieve the value
        ]
      }
    }

我在你的代码中只能看到调用上下文方法来发出完成信号,但你需要专门与 CloudFormation 通信(类似于 cfn-signal)

请在此处查看 cfn 响应部分: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-code.html

我的函数的基本示例:

var response = require('cfn-response');
cloudwatchevents.putTargets(putTargetsParams, function (err, data) {
                    if (err) {
                        console.log(err, err.stack); // an error occurred
                        response.send(event, context, response.FAILED, err.stack);
                    }
                    else {
                        console.log(data);           // successful response
                        response.send(event, context, response.SUCCESS);
                    }
                });

response.send() 在内部为您调用上下文方法。

您走在正确的轨道上,但 CloudFormation API 要求您将 result 对象作为 JSON 编码的主体放入预签名 ResponseURL 在请求事件中提供。请参阅 Custom Resources:

上的文档
  1. The custom resource provider processes the AWS CloudFormation request and returns a response of SUCCESS or FAILED to the pre-signed URL. [...] AWS CloudFormation waits and listens for a response in the pre-signed URL location. [...]
  2. After getting a SUCCESS response, AWS CloudFormation proceeds with the stack operation. If a FAILURE or no response is returned, the operation fails.

在您的示例中,您可以将 Lambda 函数中的 context.done(null, result); 行替换为如下内容:

var responseBody = JSON.stringify(result);
var https = require("https");
var url = require("url");

var parsedUrl = url.parse(event.ResponseURL);
var options = {
    hostname: parsedUrl.hostname,
    port: 443,
    path: parsedUrl.path,
    method: "PUT",
    headers: {
        "content-type": "",
        "content-length": responseBody.length
    }
};

var request = https.request(options, function(response) {
    console.log("Status code: " + response.statusCode);
    console.log("Status message: " + response.statusMessage);
    context.done();
});

request.on("error", function(error) {
    console.log("send(..) failed executing https.request(..): " + error);
    context.done();
});

request.write(responseBody);
request.end();

请参阅 AWS Lambda Function Code for the contents of cfn-response module, which implements this response logic in a self-contained function. Keep in mind, however, that the cfn-response module can only be referenced directly when a ZipFile parameter provides Javascript code inline to an AWS::Lambda::Function 资源(最多 4096 个字符)。由于您在示例中将 Lambda 函数上传到 CloudFormation 之外,因此将上述代码直接内联到现有函数中可能会更容易。