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:
上的文档
- 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. [...]
- 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 之外,因此将上述代码直接内联到现有函数中可能会更容易。
我正在尝试使用从 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:
- 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. [...]
- 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 之外,因此将上述代码直接内联到现有函数中可能会更容易。