

# CloudFormation 宏概述
<a name="template-macros-overview"></a>

使用宏处理模板有两个主要步骤：创建宏本身，然后使用宏来对模板执行处理。

要创建宏定义，您必须创建以下内容：
+ 一个执行模板处理的 Lambda 函数。此 Lambda 函数接受一个代码段或整个模板，以及您定义的任何其他参数。它返回已处理的模板代码段或整个模板作为响应。
+ [https://docs.amazonaws.cn/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-macro.html](https://docs.amazonaws.cn/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-macro.html) 类型的资源，使用户能够从 CloudFormation 模板内调用 Lambda 函数。此资源指定要为此宏调用的 Lambda函数的 ARN，以及辅助调试的其他可选属性。要在账户中创建此资源，请创建一个包含 `AWS::CloudFormation::Macro` 资源的模板，然后利用该模板创建具有自行管理权限的堆栈或堆栈集。Amazon CloudFormationStackSets 目前不支持通过引用 宏的模板创建或更新具有服务托管权限的堆栈集。

要使用宏，请在您的模板中引用宏：
+ 要处理模板的一段或部分，请在 `Fn::Transform` 函数中引用宏（位置是相对于要转换的模板内容而言的）。当使用 `Fn::Transform` 时，您还可以传递它需要的任何指定参数。
+ 要处理整个模板，请在模板的 [Transform](transform-section-structure.md) 部分中引用宏。

接下来，您通常会创建一个更改集，然后执行它。（处理宏可能会添加您可能不知道的多个资源。为确保您了解宏所引入的所有更改，我们强烈建议您使用更改集。） CloudFormation 将指定的模板内容以及任何其他指定参数一并传递给在宏资源中指定的 Lambda 函数。Lambda 函数返回已处理的模板内容，无论是代码段还是整个模板。

在调用模板中的所有宏之后，CloudFormation 会生成包含已处理模板内容的更改集。检查更改集后，执行它来应用更改。

![\[使用 Fn::Transform 内置函数或模板的 Transform 部分，将模板内容和关联参数传递给宏的底层 Lambda 函数，该函数返回处理的模板内容。\]](http://docs.amazonaws.cn/AWSCloudFormation/latest/UserGuide/images/template-macro-use.png)


## 如何直接创建堆栈
<a name="template-macros-change-sets"></a>

要使用引用宏的模板创建或更新堆栈，通常需要创建一个更改集，然后执行它。更改集描述 CloudFormation 将基于处理后的模板执行的操作。处理宏可添加您可能不知道的多个资源。为确保您已了解宏所引入的所有更改，我们强烈建议您使用更改集。在查看更改集后，您可以执行它来实际应用更改。

宏可以将 IAM 资源添加到您的模板中。对于这些资源，CloudFormation 要求您[确认其功能](control-access-with-iam.md#using-iam-capabilities)。由于 CloudFormation 无法在处理模板前了解所添加的资源，因此您可能需要在创建更改集时确认 IAM 功能，具体取决于引用的宏是否包含 IAM 资源。这样，当您运行该更改集时，CloudFormation 会具有创建 IAM 资源所需的功能。

要直接从处理的模板来创建或更新堆栈，而不事先查看更改集中提议的更改，可以在 `CreateStack` 或 `UpdateStack` 请求期间指定 `CAPABILITY_AUTO_EXPAND` 功能。仅当您知道宏在处理什么时，才应直接从包含宏的堆栈模板创建堆栈。您不能将更改集与堆栈集宏一起使用，必须直接更新堆栈集。

有关更多信息，请参阅《Amazon CloudFormation API 参考》** 中的 [https://docs.amazonaws.cn/AWSCloudFormation/latest/APIReference/API_CreateStack.html](https://docs.amazonaws.cn/AWSCloudFormation/latest/APIReference/API_CreateStack.html) 或 [https://docs.amazonaws.cn/AWSCloudFormation/latest/APIReference/API_UpdateStack.html](https://docs.amazonaws.cn/AWSCloudFormation/latest/APIReference/API_UpdateStack.html)。

**重要**  
如果堆栈集模板引用了一个或多个宏，则必须直接从处理过的模板创建堆栈集，而无需先查看更改集中生成的更改。处理宏可添加您可能不知道的多个资源。在通过直接引用宏的模板创建或更新堆栈集之前，请确保您知道宏执行的处理操作。

为减少从引用宏的模板启动堆栈的步骤数，可使用 `package` 和 `deploy` Amazon CLI 命令。有关更多信息，请参阅[使用 Amazon CLI 将本地构件上传到 S3 存储桶](using-cfn-cli-package.md)和[创建包含转换的堆栈](service_code_examples.md#deploy-sdk)。

## 注意事项
<a name="template-macros-considerations"></a>

使用宏时，请记住以下注意事项和限制：
+ 只有在提供 Lambda 的 Amazon Web Services 区域才支持宏。有关提供 Lambda 的区域的列表，请参阅 [Amazon Lambda 端点和配额](https://docs.amazonaws.cn/general/latest/gr/lambda-service.html)。
+ 任何已处理模板代码段都必须是有效的 JSON。
+ 任何已处理的模板代码段都必须通过创建堆栈、更新堆栈、创建堆栈集或更新堆栈集等操作的验证检查。
+ CloudFormation 会先解析宏，然后再处理模板。生成的模板必须是有效的 JSON，并且不得超出模板大小限制。
+ 由于 CloudFormation 处理模板中元素的顺序，宏无法在其返回给 CloudFormation 的已处理模板内容中包含模块。有关更多信息，请参阅 [宏评估顺序](template-macros-author.md#template-macros-order)。
+ 使用更新回滚功能时，CloudFormation 会使用原始模板的副本。即使包含的代码段发生更改，它也会回滚到原始模板。
+ 宏中不能嵌套宏，因为我们不会迭代处理宏。
+ 目前在宏中不支持 `Fn::ImportValue` 内部函数。
+ 模板中包含的内部函数会在任何宏之后被评估。因此，宏返回的已处理模板内容可以包括对内部函数的调用，并且像往常一样对其进行评估。
+ StackSets 目前不支持通过引用 CloudFormation 宏的模板，使用服务托管权限创建或更新堆栈集。

## 宏账户范围和权限
<a name="template-macros-permissions"></a>

您只能在创建宏的账户中将宏用作资源。宏的名称在给定账户中必须是唯一的。但是，您可以通过在底层 Lambda 函数上启用跨账户访问，然后创建宏定义以在多个账户中引用该函数，从而在多个账户中提供相同的功能。在下面的示例中，三个账户包含宏定义，每个宏定义都指向相同的 Lambda 函数。

![\[通过允许对 Lambda 函数进行跨账户访问，Amazon 能让您在引用该函数的多个账户中创建宏。\]](http://docs.amazonaws.cn/AWSCloudFormation/latest/UserGuide/images/template-macro-accounts.png)


要创建宏定义，用户必须具有在指定账户中创建堆栈或堆栈集的权限。

要使 CloudFormation 成功运行模板中包含的宏，用户必须对底层 Lambda 函数具有 `Invoke` 权限。为防止可能的权限升级，CloudFormation 会在运行宏时模拟用户。

有关更多信息，请参阅*《Amazon Lambda 开发人员指南》*中的[在 Amazon Lambda 中管理权限](https://docs.amazonaws.cn/lambda/latest/dg/lambda-permissions.html)和*《服务授权参考》*中的 [Amazon Lambda 操作、资源和条件键](https://docs.amazonaws.cn/service-authorization/latest/reference/list_awslambda.html)。