上次更新日期:2021 年 2 月 16 日
我想为在 Python 2.7/3.6/3.7 上运行的 AWS Lambda 函数更新 AWS CloudFormation cfn-response 模块。
解决方法注意:以下步骤仅适用于在 Python 2.7/3.6/3.7 上运行的 Lambda 函数。以下命令适用于 Linux 和 macOS 环境。Windows PowerShell 上的语法可能有所不同。
注意:如果您在运行 AWS 命令行界面 (AWS CLI) 命令时收到错误,请确保您运行的是最新版本的 AWS CLI。
1.要查找包含自定义资源的堆栈,请运行以下命令:
aws cloudformation list-stacks --region us-east-1 | grep -oE 'arn:+' | while read arn; do aws cloudformation list-stack-resources --stack-name $arn --region us-east-1 | grep -E '(Custom::)|(::CustomResource)' | awk '{print $2}' | while read resource; do if ]; then echo $arn; echo $resource; fi; done; done
您应会看到与以下示例输出类似的输出:
arn:aws:cloudformation:us-east-1:123456789012:stack/TestStack/3497b950-55f1-11eb-aad4-124a026c8667
"ResourceType": "AWS::CloudFormation::CustomResource",
2.要查找与自定义资源关联的 Lambda 函数,请运行以下命令以从堆栈模板中检查自定义资源的 ServiceToken 属性:
aws cloudformation get-template --stack-name TestStack | jq -r .TemplateBody
注意:步骤 2 中的命令通过使用 jq选项(来自 jq 网站)格式化响应来预览堆栈模板。
您应会看到与以下示例输出类似的输出:
Resources:
MyCustomResource:
Type: AWS::CloudFormation::CustomResource
Properties:
ServiceToken: !GetAtt MyFunction.Arn
Name: "John"
MyFunction:
Type: AWS::Lambda::Function
Properties:
Handler: index.handler
Role: !GetAtt MyRole.Arn
Runtime: python3.7
Code:
ZipFile: |
import cfnresponse
def handler(event, context):
responseData = {'Message': 'Hello {}!'.format(event)}
cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")
MyRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
ManagedPolicyArns:
- "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
Outputs:
Result:
Value: !GetAtt MyCustomResource.Message
注意:从步骤 2 输出中获得的模板是 Lambda 支持的自定义资源的最小模板示例。属性 ServiceToken: !GetAtt MyFunction.Arn 位于 MyCustomResource 部分。ServiceToken 属性的 !GetAtt MyFunction.Arn 解析的值是 Amazon Simple Notification Service (Amazon SNS) 主题的 Amazon 资源名称 (ARN) 或 Lambda 函数。
3.在步骤 2 的模板中,确定 Lambda 函数的定义位置。
如果您的 Lambda 函数与自定义资源位于同一堆栈中,请跳至步骤 4。例如,步骤 2 中的 Fn::GetAtt 函数显示 Lambda 函数与自定义资源在同一模板中定义。
如果 ServiceToken 属性指向硬编码的 ARN,则 Lambda 函数可能位于另一个堆栈中。如果 ServiceToken 属性是通过 Fn::Import 解析的,则使用 AWS CloudFormation 中的 list-exports API 来查找值。例如:
aws cloudformation list-exports --region us-east-1
{
"Exports":
}
然后,通过使用 list-tags 找到 AWS CloudFormation 堆栈 ARN,检查位于单独堆栈中的函数标签。例如:
aws lambda list-tags --resource arn:aws:lambda:us-east-1:123456789012:function:TestStack-MyFunction-5ZE2CQO8RAA9 | grep stack-id
您会收到类似如下内容的输出:
"aws:cloudformation:stack-id": "arn:aws:cloudformation:us-east-1:123456789012:stack/TestStack/3497b950-55f1-11eb-aad4-124a026c8667"
注意:您还可以在 AWS Lambda 控制台中找到函数标签。
4.要允许 AWS CloudFormation 在您的 Lambda 函数中加载最新的 cfn-response 模块,请更新 Lambda 函数的内联源代码。例如:
Code:
ZipFile: |
import cfnresponse
def handler(event, context):
responseData = {'Message': 'Hello {}!'.format(event)}
cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")
注意:请参阅步骤 2 以获取具有 Lambda 函数(含内联源代码)的示例模板。
现在,AWS CloudFormation 会将以下 cfn-response 模块代码示例加载到您的 Lambda 函数中。例如:
from botocore.vendored import requests
import json
SUCCESS = "SUCCESS"
FAILED = "FAILED"
def send(event, context, responseStatus, responseData, physicalResourceId=None, noEcho=False):
responseUrl = event
print(responseUrl)
responseBody = {}
responseBody = responseStatus
responseBody = 'See the details in CloudWatch Log Stream: ' + context.log_stream_name
responseBody = physicalResourceId or context.log_stream_name
responseBody = event
responseBody = event
responseBody = event
responseBody = noEcho
responseBody = responseData
注意:有关更多信息,请参阅 cfn-response 模块的“模块源代码”部分中的代码示例。
cfn-response 模块代码示例使用 Lambda 函数部署程序包中的 botocore.requests。
要将 cfn-response 模块更新为使用 urllib3 的最新版本,请更新 AWS CloudFormation 模板中的函数内联代码。通过向内联 Lambda 函数的代码添加注释来实现此操作。例如:
ZipFile: |
import cfnresponse
def handler(event, context):
+ # This comment was added to force an update on this function's code
responseData = {'Message': 'Hello {}!'.format(event)}
cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")
MyRole:
5.保存对包含 Lambda 函数的模板所做的任何更改。
6.更新堆栈。
在堆栈更新完成后,cfn-response 模块将被修改。
注意:如果您的函数代码位于 Amazon Simple Storage Service (Amazon S3) 存储桶或 Amazon Elastic Container Registry (Amazon ECR) 映像中,则必须自行更新模块以包含具有 urllib3 的版本。要获取 cfn-response 模块的最新版本的源代码,请参阅 cfn-response 模块。
注意:如果新的 Python 或 JavaScript 运行时引入了重大更改,则必须更新 cfn-response 模块。无需再次更新 ZipFile,只要更新函数的运行时属性,即可自动附加最新版本的 cfn-response 模块。