首页 > 解决方案 > 将 Cloudformation 模板中的自定义资源支持的 lambda 从 6.10 更新到 8.10 不再发送请求

问题描述

我们使用 cloudformation 模板向客户提供我们软件的测试驱动,以启动 AWS AMI。最近,我向此模板添加了一个自定义资源,该资源生成一个试用许可证密钥以在试驾期间使用并保存一个 cloudformation 输出。许可证是通过运行存储在 S3 上的 lambda zip 文件生成的。这首先在 node4.10 中运行,然后在 node6.10 中运行,但现在我已经移至 node8.10,等待来自 parsedUrl 响应的步骤在收到响应之前结束。由于没有返回到 cloudformation 的响应,如果此资源等待 60 分钟,则创建会发出删除堆栈命令的信号。

我认为问题在于 nodejs 的异步特性以及我对如何转换代码缺乏了解。

exports.handler = (event, context) => {

return genKey("./lic_wrp.sh", [arg1]).then(function(resp) {
    responseStatus = "SUCCESS";
    responseData["trialkey"] = resp;
    console.log ('Here is the response', responseData);

    sendResponse(event, context, responseStatus, responseData);
  }
);

该片段是原始的 node6.10 工作版本。我已更改为:

exports.handler = async (event,context) => {

try {
  var resp = await helpers.genKey("./lic_wrp.sh", [arg1]);
  responseStatus = "SUCCESS";
  responseData["trialkey"] = resp;
  console.log ('Here is the response', responseData);
  try {
    const rest2 = await sendResponse(event,  context, responseStatus, responseData)
    return rest2;
  } catch (e){
    console.log(e);
  }
} catch (e){
  console.log(e);
}

sendResponse 代码保持不变,我使用了 AWS 站点中的示例:

function sendResponse(event, context, responseStatus, responseData) {

    var responseBody = JSON.stringify({
        StackId: event.StackId,
        RequestId: event.RequestId,
        LogicalResourceId: event.LogicalResourceId,
        PhysicalResourceId: context.logStreamName,
        Status: responseStatus,
        Reason: "See the details in CloudWatch Log " + context.logStreamName,
        Data: responseData
    });

    console.log("RESPONSE BODY:\n", responseBody);

    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
        }
    };

    console.log("SENDING RESPONSE...\n");

    var request = https.request(options, function(response) {
        console.log("STATUS: " + response.statusCode);
        console.log("HEADERS: " + JSON.stringify(response.headers));
        // Tell AWS Lambda that the function execution is done
        context.done();
    });

    request.on("error", function(error) {
        console.log("sendResponse Error:\n", error);
        // Tell AWS Lambda that the function execution is done
        context.done(error);
    });

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

在 cloudwatch 中,我看到 responseBody 仍然很好。

2019-05-21T05:02:50.450Z    ba8542ed-66cf-4ada-9ae6-fd4f1920faee    RESPONSE BODY:
{
    "StackId": "arn:aws:cloudformation:ap-southeast-2:267176467350:stack/laatest52/9c35f740-7b85-11e9-9ba3-0217b90f9ac8",
    "RequestId": "1eafeb08-fadc-4bc5-a476-19330599ad6d",
    "LogicalResourceId": "LicenseKey",
    "PhysicalResourceId": "2019/05/21/[$LATEST]e2cc667849d44285b452af5fa31084b2",
    "Status": "SUCCESS",
    "Reason": "See the details in CloudWatch Log 2019/05/21/[$LATEST]e2cc667849d44285b452af5fa31084b2",
    "Data": {
        "trialkey": "xxxx-xxxx-xxxx-xxxx-xxxx" -- Our key gen is working
    }
}

然后我看到发送响应。但接下来的一行是: END RequestId: ba8542ed-66cf-4ada-9ae6-fd4f1920faee

在以前的版本中运行良好。我们看到,响应正文,然后发送响应: 2018-11-16T18:03:06.435Z dd879acf-e9c9-11e8-afaf-bfffb4a386b6 STATUS: 200

并且创建了资源。

标签: node.jsaws-lambdaamazon-cloudformation

解决方案


回答了自己的问题。安装了“cfn-response-promise”模块,这是我使用的 sendResponse 函数的异步/等待兼容替代方案。CF 堆栈完成且没有错误,并且在 lambda 运行后收到 200 的状态。


推荐阅读