cfn-response 模块 - AWS CloudFormation
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

cfn-response 模块

如果使用 ZipFile 属性指定函数的源代码并且该函数与 AWS CloudFormation 自定义资源进行交互,您可以加载 cfn-response 模块以将响应发送到这些资源。该模块包含一个 send 方法,它通过 Amazon S3 预签名 URL (ResponseURL) 将响应对象发送到自定义资源。

在执行 send 方法后,Lambda 函数将终止,因此,将忽略在该方法之后写入的任何内容。

注意

只有当您使用 cfn-response 属性编写您的源代码时,ZipFile 模块可用。它对于存储在 Amazon S3 存储桶中的源代码不可用。对于 存储桶中的代码,您必须编写自己的函数来发送响应。

加载 cfn-response 模块

对于 Node.js 函数,使用 require() 函数来加载 cfn-response 模块。例如,以下代码示例创建一个名为 cfn-responseresponse 对象:

var response = require('cfn-response');

对于 Python,使用 import 语句来加载 cfnresponse 模块,如下例所示:

注意

使用这个确切的导入语句。如果您使用导入语句的其他变体,AWS CloudFormation 不会包含响应模块。

import cfnresponse

send 方法参数

您可以将以下参数用于 send 方法。

event

自定义资源请求中的字段。

context

一个 Lambda 函数特定的对象,可用于指定何时函数和任何回调完成执行,或从 Lambda 执行环境中访问信息。有关更多信息,请参阅 AWS Lambda Developer Guide 中的编程模型 (Node.js)

responseStatus

函数是否成功完成。使用 cfnresponse 模块常量指定状态:SUCCESS 表示执行成功;FAILED 表示执行失败。

responseData

自定义资源响应对象Data 字段。数据为名称-值对列表。

physicalResourceId

可选。调用此函数的自定义资源的唯一标识符。默认情况下,该模块使用与 Lambda 函数关联的 Amazon CloudWatch Logs 日志流的名称。

noEcho

可选。指示在使用 Fn::GetAtt 函数检索自定义资源的输出时是否遮蔽它。如果设置为 true,则所有返回值均用星号 (*****) 遮蔽。默认情况下,此值为 false

有关使用 NoEcho 来遮蔽敏感信息的更多信息,请参阅请勿将凭证嵌入您的模板最佳实践。

示例

Node.js

在下面的 Node.js 示例中,内联 Lambda 函数获取输入值并将其乘以 5。内联函数对于较小的函数尤为有用,因为它们让您能够在模板中直接指定源代码,而不必先创建包再将包上传到 Amazon S3 存储桶中。函数使用 cfn-response send 方法将结果发回给调用此函数的自定义资源。

JSON

"ZipFile": { "Fn::Join": ["", [ "var response = require('cfn-response');", "exports.handler = function(event, context) {", " var input = parseInt(event.ResourceProperties.Input);", " var responseData = {Value: input * 5};", " response.send(event, context, response.SUCCESS, responseData);", "};" ]]}

YAML

ZipFile: > var response = require('cfn-response'); exports.handler = function(event, context) { var input = parseInt(event.ResourceProperties.Input); var responseData = {Value: input * 5}; response.send(event, context, response.SUCCESS, responseData); };

Python

在下面的 Python 示例中,内联 Lambda 函数采用一个整数值并将它乘以 5。

JSON

"ZipFile" : { "Fn::Join" : ["\n", [ "import json", "import cfnresponse", "def handler(event, context):", " responseValue = int(event['ResourceProperties']['Input']) * 5", " responseData = {}", " responseData['Data'] = responseValue", " cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, \"CustomResourcePhysicalID\")" ]]}

YAML

ZipFile: | import json import cfnresponse def handler(event, context): responseValue = int(event['ResourceProperties']['Input']) * 5 responseData = {} responseData['Data'] = responseValue cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")

模块源代码

以下是 Node.js 函数的响应模块源代码。请查看这些内容,以理解此模块的功能并帮助您实现自己的响应函数。

/* Copyright 2015 Amazon Web Services, Inc. or its affiliates. All Rights Reserved. This file is licensed to you under the AWS Customer Agreement (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at http://aws.amazon.com/agreement/ . This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions and limitations under the License. */ exports.SUCCESS = "SUCCESS"; exports.FAILED = "FAILED"; exports.send = function(event, context, responseStatus, responseData, physicalResourceId, noEcho) { var responseBody = JSON.stringify({ Status: responseStatus, Reason: "See the details in CloudWatch Log Stream: " + context.logStreamName, PhysicalResourceId: physicalResourceId || context.logStreamName, StackId: event.StackId, RequestId: event.RequestId, LogicalResourceId: event.LogicalResourceId, NoEcho: noEcho || false, 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 } }; 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(); }

以下是 Python 3 函数的响应模块源代码。

# Copyright 2016 Amazon Web Services, Inc. or its affiliates. All Rights Reserved. # This file is licensed to you under the AWS Customer Agreement (the "License"). # You may not use this file except in compliance with the License. # A copy of the License is located at http://aws.amazon.com/agreement/ . # This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied. # See the License for the specific language governing permissions and limitations under the License. from botocore.vendored import requests import json SUCCESS = "SUCCESS" FAILED = "FAILED" def send(event, context, responseStatus, responseData, physicalResourceId=None, noEcho=False): responseUrl = event['ResponseURL'] print(responseUrl) responseBody = {} responseBody['Status'] = responseStatus responseBody['Reason'] = 'See the details in CloudWatch Log Stream: ' + context.log_stream_name responseBody['PhysicalResourceId'] = physicalResourceId or context.log_stream_name responseBody['StackId'] = event['StackId'] responseBody['RequestId'] = event['RequestId'] responseBody['LogicalResourceId'] = event['LogicalResourceId'] responseBody['NoEcho'] = noEcho responseBody['Data'] = responseData json_responseBody = json.dumps(responseBody) print("Response body:\n" + json_responseBody) headers = { 'content-type' : '', 'content-length' : str(len(json_responseBody)) } try: response = requests.put(responseUrl, data=json_responseBody, headers=headers) print("Status code: " + response.reason) except Exception as e: print("send(..) failed executing requests.put(..): " + str(e))

以下是 Python 2 函数的响应模块源代码。

# Copyright 2016 Amazon Web Services, Inc. or its affiliates. All Rights Reserved. # This file is licensed to you under the AWS Customer Agreement (the "License"). # You may not use this file except in compliance with the License. # A copy of the License is located at http://aws.amazon.com/agreement/ . # This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied. # See the License for the specific language governing permissions and limitations under the License. from botocore.vendored import requests import json SUCCESS = "SUCCESS" FAILED = "FAILED" def send(event, context, responseStatus, responseData, physicalResourceId=None, noEcho=False): responseUrl = event['ResponseURL'] print responseUrl responseBody = {} responseBody['Status'] = responseStatus responseBody['Reason'] = 'See the details in CloudWatch Log Stream: ' + context.log_stream_name responseBody['PhysicalResourceId'] = physicalResourceId or context.log_stream_name responseBody['StackId'] = event['StackId'] responseBody['RequestId'] = event['RequestId'] responseBody['LogicalResourceId'] = event['LogicalResourceId'] responseBody['NoEcho'] = noEcho responseBody['Data'] = responseData json_responseBody = json.dumps(responseBody) print "Response body:\n" + json_responseBody headers = { 'content-type' : '', 'content-length' : str(len(json_responseBody)) } try: response = requests.put(responseUrl, data=json_responseBody, headers=headers) print "Status code: " + response.reason except Exception as e: print "send(..) failed executing requests.put(..): " + str(e)