View a markdown version of this page

Amazon CloudFormation 语言扩展支持 - Amazon Serverless Application Model
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

Amazon CloudFormation 语言扩展支持

Amazon SAMCLI支持使用AWS::LanguageExtensions变换的模板,包括Fn::ForEachFn::LengthFn::ToJsonStringFn::FindInMapDefaultValue。有关这些构造的完整参考信息,请参阅《Amazon CloudFormation 用户指南》中的 t AWS::LanguageExtensions r ansform。

要在 Amazon SAM 模板中使用语言扩展名,请在之前的Transform部分AWS::LanguageExtensions中列出AWS::Serverless-2016-10-31

Transform: - AWS::LanguageExtensions - AWS::Serverless-2016-10-31

当在模板的Transform部分AWS::LanguageExtensions中 Amazon SAMCLI检测到并且您选择了本地处理时,它会在运行 Amazon SAM 转换之前在本地扩展语言扩展结构。这使sam buildsam packagesam deploysam syncsam validatesam local invokesam local start-api、和sam local start-lambda能够使用使用这些构造的模板。

默认情况下,本地处理处于关闭状态。禁用后, Amazon SAMCLI会将模板保持不变,并在部署时 Amazon CloudFormation 处理服务器端的AWS::LanguageExtensions转换。有关激活方法,请参阅启用语言扩展

启用后,扩展分两个阶段进行:

  1. 第 1 阶段(语言扩展)— 扩展Fn::ForEach循环,尽可能解析内部函数,并将模板转换为标准模板。 Amazon CloudFormation

  2. 第 2 阶段(Amazon SAM 转换)-扩展后的模板将像往常一样由 Amazon SAM 翻译器处理。

由于在服务器端 Amazon CloudFormation 处理了AWS::LanguageExtensions转换,因此保留了原始模板(Fn::ForEach完好无损)以供 Amazon CloudFormation 部署。

启用语言扩展

按命令选择AWS::LanguageExtensions进行本地处理。有三种等效的激活方法,按优先级顺序列出:

  1. CLIfla@@ g — 传递--language-extensions一次调用:

    sam build --language-extensions sam package --language-extensions ... sam deploy --language-extensions ...

    --no-language-extensions显式禁用,覆盖两者samconfig.toml以及下面描述的环境变量。

  2. samconfig.toml— 坚持每个项目的选择:

    [default.build.parameters] language_extensions = true [default.package.parameters] language_extensions = true [default.deploy.parameters] language_extensions = true [default.sync.parameters] language_extensions = true [default.local_invoke.parameters] language_extensions = true [default.local_start_api.parameters] language_extensions = true [default.local_start_lambda.parameters] language_extensions = true [default.validate.parameters] language_extensions = true

    一个samconfig.toml条目是作为命令的默认值加载的,因此它会像传递标志一样生效,因此胜过环境变量。

  3. 环境变量 — 设置为SAM_CLI_ENABLE_LANGUAGE_EXTENSIONS=1对当前 shell 启用:

    export SAM_CLI_ENABLE_LANGUAGE_EXTENSIONS=1 sam build sam local invoke MyFunction

    真值(不区分大小写)是1true和。yes其他任何内容,包括空字符串,都被视为关闭。只有当既没有CLI标记也没有samconfig.toml设置值时,才会参考环境变量。

重要

每个命令都需要自己激活。传递--language-extensionssam build不会传播到以后的版本 sam local invoke ——本地处理是由每个命令调用决定的。使用环境变量或samconfig.toml条目在命令之间启用,而无需重复该标志。

Fn:: ForEach

Fn::ForEach根据单个模板定义生成多个资源、条件或输出:

Transform: - AWS::LanguageExtensions - AWS::Serverless-2016-10-31 Parameters: ServiceNames: Type: CommaDelimitedList Default: "Users,Orders,Products" Resources: Fn::ForEach::Services: - Name - !Ref ServiceNames - ${Name}Function: Type: AWS::Serverless::Function Properties: Handler: index.handler Runtime: python3.12 CodeUri: ./services/${Name}

Run sam build ning 将其扩展为UsersFunctionOrdersFunctionProductsFunction、和,每个都从其各自的源目录构建。

动态构件属性

当可打包属性使用循环变量(例如./services/${Name})时, Amazon SAMCLI会生成一个将每个集合值映射到其 Amazon S3 的 Amazon CloudFormation Mappings部分。URI正Fn::ForEach文被重写为使用,Fn::FindInMap因此 Amazon CloudFormation 可以在部署时解析正确的工件。

已识别的工件属性与当今sam package重写的属性相同。这包括:

可识别的动态构件属性 Amazon SAM CLI
资源类型 属性

AWS::Serverless::Function

CodeUri, ImageUri

AWS::Serverless::LayerVersion

ContentUri

AWS::Serverless::Api

DefinitionUri

AWS::Serverless::HttpApi

DefinitionUri

AWS::Serverless::StateMachine

DefinitionUri

AWS::Serverless::GraphQLApi

SchemaUri, CodeUri

AWS::Serverless::Application

Location

AWS::Lambda::Function

Code, Code.ImageUri

AWS::Lambda::LayerVersion

Content

AWS::ApiGateway::RestApi

BodyS3Location

AWS::ApiGatewayV2::Api

BodyS3Location

AWS::AppSync::GraphQLSchema

DefinitionS3Location

AWS::AppSync::Resolver

RequestMappingTemplateS3Location, ResponseMappingTemplateS3Location, CodeS3Location

AWS::AppSync::FunctionConfiguration

RequestMappingTemplateS3Location, ResponseMappingTemplateS3Location, CodeS3Location

AWS::StepFunctions::StateMachine

DefinitionS3Location

AWS::ElasticBeanstalk::ApplicationVersion

SourceBundle

AWS::Glue::Job

Command.ScriptLocation

AWS::CloudFormation::Stack

TemplateURL

AWS::CloudFormation::StackSet

TemplateURL

AWS::CloudFormation::ModuleVersion

ModulePackage

AWS::CloudFormation::ResourceVersion

SchemaHandlerPackage

对于点状属性(例如,Command.ScriptLocationon AWS::Glue::JobCode.ImageUri onAWS::Lambda::Function),将在资源上的嵌套位置读取和写入该值。生成的映射名称仅使用属性路径的叶段。

当属性采用循环模板化时,映射名称为SAM<LeafProperty><LoopName>(例如,SAMCodeUriServices或)。SAMScriptLocationJobs

重要

Customer-authored 映射不应以这些SAM*前缀开头,而是保留给的。 Amazon SAMCLI请参阅限制

例如,之后sam package

Mappings: SAMCodeUriServices: Users: CodeUri: s3://my-bucket/abc123 Orders: CodeUri: s3://my-bucket/def456 Products: CodeUri: s3://my-bucket/ghi789 Resources: Fn::ForEach::Services: - Name - !Ref ServiceNames - ${Name}Function: Type: AWS::Serverless::Function Properties: Handler: index.handler Runtime: python3.12 CodeUri: !FindInMap [SAMCodeUriServices, !Ref Name, CodeUri]

每个 ForEach 机构有多种资源

单个Fn::ForEach主体每次迭代可以发射多个资源。每个资源都是为每个集合值生成的:

Resources: Fn::ForEach::Tables: - TableName - [Users, Orders, Products] - ${TableName}Table: Type: AWS::DynamoDB::Table Properties: TableName: !Sub "${AWS::StackName}-${TableName}" # ... ${TableName}StreamProcessor: Type: AWS::Serverless::Function Properties: CodeUri: stream-processors/${TableName}/ Events: DDBStream: Type: DynamoDB Properties: Stream: !GetAtt - !Sub "${TableName}Table" - StreamArn

映射名称冲突解决方案

当同一个Fn::ForEach主体中的两个资源声明相同的动态构件属性(例如,一个Api和一个StateMachine用途DefinitionUri)时,会 Amazon SAMCLI附加一个取自资源 Logical-ID 模板静态部分的后缀,以保持映射名称的唯一性:

使用碰撞后缀映射名称的示例
资源模板 属性 映射名称

${Svc}Api

DefinitionUri

SAMDefinitionUriServicesApi

${Svc}StateMachine

DefinitionUri

SAMDefinitionUriServicesStateMachine

如果没有碰撞,则使用基本名称(例如SAMDefinitionUriServices)。

Parameter-based 集合

如果Fn::ForEach集合是参数引用(例如!Ref ServiceNames),而循环体使用动态构件属性(例如CodeUri: ./services/${Name}),则 Amazon SAMCLI需要集合值来生成中所动态构件属性述的SAM*映射。它在处理模板时会解析它们,来自:

  1. --parameter-overrides传递给 Amazon SAMCLI命令。

  2. 模板中参数的Default值。

重要

由于SAM*映射是在打包时生成的,因此无论何时更改参数值(例如,添加新服务时),都必须重新打包,这样 Mappings 就会包含新值的条目。这仅适用于参数驱动动态构件循环;其他参数覆盖可以像往常一样在部署时更改。

# Package with the values you intend to deploy with sam package --language-extensions --parameter-overrides ServiceNames="Users,Orders,Products" # Deploy with the same values sam deploy --language-extensions --parameter-overrides ServiceNames="Users,Orders,Products"

嵌套堆栈

Fn::ForEach支持嵌套堆栈模板 (AWS::CloudFormation::Stack)。将父堆栈的Parameters属性 Amazon SAMCLI传递给子模板扩展,因此引用父级提供的参数的子Fn::ForEach集合可以正确解析。

# parent.yaml Resources: ChildStack: Type: AWS::CloudFormation::Stack Properties: TemplateURL: ./child.yaml Parameters: ServiceNames: "Users,Orders,Products"

嵌套 Fn:: ForEach

最多支持 5 个嵌套级别,符合 Amazon CloudFormation 限制:

Resources: Fn::ForEach::Envs: - Env - [Dev, Staging, Prod] - Fn::ForEach::Services: - Svc - [Users, Orders] - ${Env}${Svc}Function: Type: AWS::Serverless::Function Properties: CodeUri: ./services/${Svc} Environment: Variables: STAGE: ${Env}

ForEach 在输出中

Fn::ForEach区块也会在该Outputs部分内展开,因此你可以为每个集合值发出一个输出:

Outputs: Fn::ForEach::FunctionArns: - Name - [alpha, beta] - ${Name}FunctionArn: Value: !GetAtt - !Sub "${Name}Function" - Arn

条件和 DependsOn

发出的资源Fn::ForEach可以携带,Condition并且可以DependsOn像任何其他资源一样携带。条件或依赖关系会复制到每个生成的资源上:

Conditions: IsProd: !Equals [!Ref Environment, prod] Resources: SharedTable: Type: AWS::DynamoDB::Table # ... Fn::ForEach::Functions: - Name - [api, worker] - ${Name}Function: Type: AWS::Serverless::Function Condition: IsProd DependsOn: SharedTable Properties: Handler: main.handler CodeUri: functions/${Name}/

&amp;{标识符} 语法

&{identifier}语法从替换值中去除非字母数字字符,这对于从 IP 地址等值生成有效的逻辑 ID 非常有用:

Fn::ForEach::Hosts: - IP - ["10.0.0.1", "10.0.0.2"] - Host&{IP}: Type: AWS::EC2::Instance # Expands to Host10001, Host10002

支持的内部函数

在扩展过程中,以下内部函数将在本地解析:

在语言扩展扩展期间本地解析的内部函数
函数 说明

Fn::ForEach

循环扩展。

Fn::Length

返回列表元素的数量。

Fn::ToJsonString

将值转换为字符JSON串。

Fn::FindInMap

地图查询,包括可选的DefaultValue

Fn::If

条件值选择。

Fn::Sub

字符串替换。

Fn::Join

字符串连接。

Fn::Split

字符串拆分。

Fn::Select

列表元素选择。

Fn::Base64

Base64 编码。

Fn::Equals, Fn::And, Fn::Or, Fn::Not

状况评估。

Ref

参数和伪参数引用。

需要部署资源(Fn::GetAttFn::ImportValueFn::GetAZs)的函数会被保留, Amazon CloudFormation 以便在部署时解析。

验证错误

在 Amazon SAM 转换运行之前,会在本地捕获以下模板问题:

扩展语言时出现验证错误
原因 错误消息

Fn::ForEach值格式不正确 — 不是列表、不完全包含 3 个元素或具有非字符串循环标识符。

Fn::ForEach::<key> layout is incorrect(提高为InvalidTemplateException)。

嵌套了超过 5 Fn::ForEach 个级别。

Fn::ForEach nesting depth of <N> exceeds the maximum allowed depth of 5. CloudFormation supports up to 5 nested Fn::ForEach loops.

集合解析为空列表(例如,带的CommaDelimitedList参数Default: "")。

没有错误 — 循环被静默跳过,并且不会发出任何资源。

集合!Ref中的指向模板中未声明的参数。

没有错误 — 未解析的引用保留在模板中。在部署时, Amazon CloudFormation 将在服务器端解决这个问题。

限制

  • 集合必须是可解析 build/package 的。 Fn::ForEach使用Fn::GetAttFn::ImportValue、或 SSM/Secrets Manager 动态引用的集合无法在本地展开。请--parameter-overrides改用带的参数。

  • 动态构件映射在打包时已修复。Fn::ForEach集合是参数引用并且循环主体使用动态构件属性(例如CodeUri: ./services/${Name})时,生成的SAM*映射仅包含在打包时解析的参数值的条目。如果您在部署时更改--parameter-overrides该参数而不重新打包,则新值将没有映射条目,部署将失败。这不适用于不用于驱动动态构件的参数Fn::ForEach

  • DeletionPolicy并在扩展过程中UpdateReplacePolicy经过验证和解决。它们支持参数Ref,但不支持其他内部函数。

  • 嵌套限制。最多Fn::ForEach可以嵌套 5 个级别,与 Amazon CloudFormation 服务器端的限制相匹配。

  • 保留的映射名称。以以下任一名称开头的映射名称是为保留的 Amazon SAMCLI — 请勿使用这些前缀创作自己的映射:

    • SAMCodeUriSAMImageUriSAMContentUriSAMDefinitionUriSAMSchemaUriSAMBodyS3LocationSAMDefinitionS3LocationSAMTemplateURLSAMCodeSAMContentsam package 为动态构件属性发出。参见动态构件属性表格。

    • SAMLayers— 由Fn::ForEach生成的函数获取自动生成的依赖层引用(Lambda 将构建分层到嵌套堆栈中)sam build时发出。 Amazon SAMCLI此前缀没有相应的用户创作属性;它是自动添加的。

遥测

当使用--language-extensions(或 Amazon SAMCLI其等效环境变量)调用命令并且模板声明转换时,会发出CFNLanguageExtensions遥测事件。AWS::LanguageExtensions该事件每次调用都会触发一次,并且不会传输任何模板内容。本地处理处于关闭状态(默认)时,不会触发任何事件。