AWS CloudFormation
User Guide (API Version 2010-05-15)
AWS 服务或AWS文档中描述的功能,可能因地区/位置而异。请点击 Amazon AWS 入门,可查看中国地区的具体差异

AWS Lambda 函数代码

CodeAWS::Lambda::Function 资源的一个属性,可用来指定 AWS Lambda 函数的源代码。源代码可位于模板或 S3 存储桶内的文件中。(仅限 nodejs4.3nodejs6.10python2.7python3.6 运行时环境) 可以在模板中提供源代码作为内联文本。

注意

要更新源代码位于 S3 存储桶中的 Lambda 函数,您必须通过更新 S3BucketS3KeyS3ObjectVersion 属性触发更新。单独更新源代码不会更新函数。

语法

JSON

{ "S3Bucket" : String, "S3Key" : String, "S3ObjectVersion" : String, "ZipFile" : String }

YAML

S3Bucket: String S3Key: String S3ObjectVersion: String ZipFile: String

属性

S3Bucket

包含 Lambda 函数源代码的 S3 存储桶的名称。S3 存储桶必须与堆栈位于同一区域。

注意

cfn-response 模块对于存储在 S3 存储桶中的源代码不可用。要发送响应,您必须编写自己的函数。

Required: Conditional 同时指定 S3BucketS3Key 属性,或指定 ZipFile 属性。

Type: String

S3Key

包含您的源代码的 .zip 文件的位置和名称。如果指定此属性,则还必须指定 S3Bucket 属性。

Required: Conditional 您必须同时指定 S3BucketS3Key 属性,或指定 ZipFile 属性。

Type: String

S3ObjectVersion

如果启用了 S3 版本控制,则为包含源代码的 .zip 文件的版本 ID。只有在您指定了 S3BucketS3Key 属性时,才可以指定此属性。

Required: No

Type: String

ZipFile

对于 nodejs4.3nodejs6.10python2.7python3.6 运行时环境,这是您的 Lambda 函数的源代码。您无法为其他运行时环境使用此属性。

您最多可指定 4096 个字符。必须在源代码中的某些特殊字符(如问号 (")、换行符 (\n)、制表符 (\t) 等)前添加反斜杠 (\)。有关特殊字符的列表,请参阅 http://json.org/

如果您指定了与 AWS CloudFormation 自定义资源交互的函数,就无需编写自己的函数来发送响应到调用函数的自定义资源。AWS CloudFormation 提供了简化发送响应的响应模块。有关更多信息,请参阅 cfn-response 模块

Required: Conditional 您必须同时指定 S3BucketS3Key 属性,或指定 ZipFile 属性。

Type: String

cfn-response 模块

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

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

注意

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

加载 cfn-response 模块

对于 nodejs4.3nodejs6.10 运行时环境,可使用 require() 函数加载 cfn-response 模块。例如,以下代码示例创建一个名为 responsecfn-response 对象:

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

对于 python2.7python3.6 环境,使用 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 日志流的名称。

示例

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 示例中 (该示例适用于 2.7 和 3.6 版本),内联 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")

模块源代码

以下是 nodejs4.3nodejs6.10 运行时环境的响应模块源代码。请查看这些内容,以理解此模块的功能并帮助您实现自己的响应函数。

/* 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) { 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, 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(); }

以下为 python3.6 环境的响应模块源代码:

# 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): 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['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))

以下为 python2.7 环境的响应模块源代码:

# 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): 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['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)