Пользовательская лямбда-функция AWS CloudFormation застряла в состоянии создания

Я пытаюсь использовать значение, возвращаемое лямбда-функцией через. Пользовательские ресурсы CloudFormation; однако, когда я пытаюсь, пользовательский ресурс CloudFormation бесконечно зависает в состоянии ожидания.

Следующий код лямбда-узла, который я пытаюсь и

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, я пытаюсь работать с лямбда

"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
        ]
      }
    }

person Naveen Vijay    schedule 29.03.2016    source источник


Ответы (2)


Вы на правильном пути, но CloudFormation API требует, чтобы вы поместили ваш result объект как тело в кодировке JSON в предварительно подписанный ResponseURL, указанный в событии запроса. См. Документацию по Пользовательским ресурсам:

  1. Пользовательский поставщик ресурсов обрабатывает запрос AWS CloudFormation и возвращает на предварительно подписанный URL-адрес ответ УСПЕШНО или НЕВЕРНО. [...] AWS CloudFormation ожидает и ожидает ответа в предварительно подписанном URL-адресе. [...]
  2. После получения ответа SUCCESS AWS CloudFormation продолжает операцию стека. Если возвращается ОТКАЗ или нет ответа, операция завершается ошибкой.

В вашем примере вы можете заменить строку 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 для содержимого модуля cfn-response, который реализует эту логику ответа в автономной функции. Однако имейте в виду, что на модуль cfn-response можно напрямую ссылаться только при _ 7_ параметр предоставляет код Javascript, встроенный в _ 8_ (не более 4096 символов). Поскольку в вашем примере вы загружаете свою лямбда-функцию вне CloudFormation, вероятно, будет проще встроить приведенный выше код непосредственно в существующую функцию.

person wjordan    schedule 30.03.2016
comment
Ваши комментарии о cfn-response в лямбде сбивают с толку. Он может просто включить модель в свою лямбду в соответствии с моим кодом. Какой смысл копировать и вставлять? - person stevepkr84; 01.04.2016
comment
В примере кода свойство ServiceToken указывает на существующий ARN (arn:aws:lambda:*), что означает, что функция Lambda устанавливается не через ресурс AWS::Lambda:Function, а другими способами. Модуль cfn-response предоставляется только при использовании свойства ZipFile ресурса CloudFormation (это часть реализации ресурса CloudFormation). Поскольку модуль не доступен автоматически, он должен предоставить его сам, либо добавив исходный код модуля cfn-response.js в свой zip-архив, либо встроив его непосредственно в существующую функцию. - person wjordan; 01.04.2016

Все, что я вижу в вашем коде, - это вызовы методов контекста для сигнала о завершении, но вам нужно конкретно общаться с CloudFormation (аналогично cfn-signal)

См. Раздел cfn-response здесь: 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 () вызывает для вас контекстные методы.

person stevepkr84    schedule 30.03.2016