

# 配合使用 AWS Lambda 和 CloudFormation
<a name="services-cloudformation"></a>

在 AWS CloudFormation 模板中，您可以指定 Lambda 函数作为自定义资源的对象。使用自定义资源来处理参数、检索配置值，或者在堆栈生命周期事件期间调用其他 AWS 服务。

以下示例调用在模板中的其他位置定义的函数。

**Example – 自定义资源定义**  

```
Resources:
  primerinvoke:
    Type: [AWS::CloudFormation::CustomResource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cfn-customresource.html)
    Version: "1.0"
    Properties:
      ServiceToken: !GetAtt primer.Arn
      FunctionName: !Ref randomerror
```

服务令牌是在您创建、更新或删除堆栈时，CloudFormation 所调用函数的 Amazon 资源名称 (ARN)。您还可以按原样包含 `FunctionName` 传递到您函数的其他属性，例如 CloudFormation。

CloudFormation 通过包含回调 URL 的事件[异步](invocation-async.md)调用您的 Lambda 函数。

**Example – CloudFormation 消息事件**  

```
{
    "RequestType": "Create",
    "ServiceToken": "arn:aws:lambda:us-east-1:123456789012:function:lambda-error-processor-primer-14ROR2T3JKU66",
    "ResponseURL": "https://cloudformation-custom-resource-response-useast1.s3-us-east-1.amazonaws.com/arn%3Aaws%3Acloudformation%3Aus-east-1%3A123456789012%3Astack/lambda-error-processor/1134083a-2608-1e91-9897-022501a2c456%7Cprimerinvoke%7C5d478078-13e9-baf0-464a-7ef285ecc786?AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE&Expires=1555451971&Signature=28UijZePE5I4dvukKQqM%2F9Rf1o4%3D",
    "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/lambda-error-processor/1134083a-2608-1e91-9897-022501a2c456",
    "RequestId": "5d478078-13e9-baf0-464a-7ef285ecc786",
    "LogicalResourceId": "primerinvoke",
    "ResourceType": "AWS::CloudFormation::CustomResource",
    "ResourceProperties": {
        "ServiceToken": "arn:aws:lambda:us-east-1:123456789012:function:lambda-error-processor-primer-14ROR2T3JKU66",
        "FunctionName": "lambda-error-processor-randomerror-ZWUC391MQAJK"
    }
}
```

函数负责将指示成功还是失败的响应返回到回调 URL。有关完整响应语法，请参阅[自定义资源响应对象](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/crpg-ref-responses.html)。

**Example – CloudFormation 自定义资源响应**  

```
{
    "Status": "SUCCESS",
    "PhysicalResourceId": "2019/04/18/[$LATEST]b3d1bfc65f19ec610654e4d9b9de47a0",
    "StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/lambda-error-processor/1134083a-2608-1e91-9897-022501a2c456",
    "RequestId": "5d478078-13e9-baf0-464a-7ef285ecc786",
    "LogicalResourceId": "primerinvoke"
}
```

CloudFormation 提供称为 `cfn-response` 的库来处理响应的发送。如果您在模板中定义函数，则可以按名称请求库。随后，CloudFormation 将库添加到为函数创建的部署程序包。

如果自定义资源使用的函数附加了[弹性网络接口](configuration-vpc.md#configuration-vpc-enis)，请将以下资源添加到 VPC 策略，其中 **region** 是函数所在的区域（不带破折号）。例如，`us-east-1` 为 `useast1`。这将允许自定义资源响应将信号发送回 CloudFormation 堆栈的回调 URL。

```
arn:aws:s3:::cloudformation-custom-resource-response-region",
"arn:aws:s3:::cloudformation-custom-resource-response-region/*",
```

以下示例函数调用第二个函数。如果调用成功，则函数发送成功响应到 CloudFormation，并且堆栈更新继续。该模板使用 AWS Serverless Application Model 提供的 [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html) 资源类型。

**Example – 自定义资源函数**  

```
Transform: 'AWS::Serverless-2016-10-31'
Resources:
  primer:
    Type: [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html)
    Properties:
      Handler: index.handler
      Runtime: nodejs16.x
      InlineCode: |
        var aws = require('aws-sdk');
        var response = require('cfn-response');
        exports.handler = function(event, context) {
            // For Delete requests, immediately send a SUCCESS response.
            if (event.RequestType == "Delete") {
                response.send(event, context, "SUCCESS");
                return;
            }
            var responseStatus = "FAILED";
            var responseData = {};
            var functionName = event.ResourceProperties.FunctionName
            var lambda = new aws.Lambda();
            lambda.invoke({ FunctionName: functionName }, function(err, invokeResult) {
                if (err) {
                    responseData = {Error: "Invoke call failed"};
                    console.log(responseData.Error + ":\n", err);
                }
                else responseStatus = "SUCCESS";
                response.send(event, context, responseStatus, responseData);
            });
        };
      Description: Invoke a function to create a log stream.
      MemorySize: 128
      Timeout: 8
      Role: !GetAtt role.Arn
      Tracing: Active
```

如果模板中未定义自定义资源调用的函数，您可以从 AWS CloudFormation 用户指南中的 [cfn-response 模块](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-lambda-function-code-cfnresponsemodule.html)获取 `cfn-response` 的源代码。

有关自定义资源的更多信息，请参阅 *AWS CloudFormation 用户指南*中的[自定义资源](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources.html)。