本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
Amazon CloudFormation 语言扩展支持
Amazon SAMCLI支持使用AWS::LanguageExtensions变换的模板,包括Fn::ForEachFn::Length、Fn::ToJsonString、Fn::FindInMap和DefaultValue。有关这些构造的完整参考信息,请参阅《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 build得sam package、sam deploy、sam sync、sam validate、sam local invoke、sam local start-api、和sam local start-lambda能够使用使用这些构造的模板。
默认情况下,本地处理处于关闭状态。禁用后, Amazon SAMCLI会将模板保持不变,并在部署时 Amazon CloudFormation 处理服务器端的AWS::LanguageExtensions转换。有关激活方法,请参阅启用语言扩展。
启用后,扩展分两个阶段进行:
-
第 1 阶段(语言扩展)— 扩展
Fn::ForEach循环,尽可能解析内部函数,并将模板转换为标准模板。 Amazon CloudFormation -
第 2 阶段(Amazon SAM 转换)-扩展后的模板将像往常一样由 Amazon SAM 翻译器处理。
由于在服务器端 Amazon CloudFormation 处理了AWS::LanguageExtensions转换,因此保留了原始模板(Fn::ForEach完好无损)以供 Amazon CloudFormation 部署。
启用语言扩展
按命令选择AWS::LanguageExtensions进行本地处理。有三种等效的激活方法,按优先级顺序列出:
-
CLIfla@@ g — 传递
--language-extensions一次调用:sam build --language-extensions sam package --language-extensions ... sam deploy --language-extensions ...--no-language-extensions显式禁用,覆盖两者samconfig.toml以及下面描述的环境变量。 -
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条目是作为命令的默认值加载的,因此它会像传递标志一样生效,因此胜过环境变量。 -
环境变量 — 设置为
SAM_CLI_ENABLE_LANGUAGE_EXTENSIONS=1对当前 shell 启用:export SAM_CLI_ENABLE_LANGUAGE_EXTENSIONS=1 sam build sam local invoke MyFunction真值(不区分大小写)是
1、true和。yes其他任何内容,包括空字符串,都被视为关闭。只有当既没有CLI标记也没有samconfig.toml设置值时,才会参考环境变量。
重要
每个命令都需要自己激活。传递--language-extensions给sam 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重写的属性相同。这包括:
| 资源类型 | 属性 |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
对于点状属性(例如,Command.ScriptLocationon AWS::Glue::Job 或 Code.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 模板静态部分的后缀,以保持映射名称的唯一性:
| 资源模板 | 属性 | 映射名称 |
|---|---|---|
|
|
|
|
|
|
如果没有碰撞,则使用基本名称(例如SAMDefinitionUriServices)。
Parameter-based 集合
如果Fn::ForEach集合是参数引用(例如!Ref ServiceNames),而循环体使用动态构件属性(例如CodeUri: ./services/${Name}),则 Amazon SAMCLI需要集合值来生成中所动态构件属性述的SAM*映射。它在处理模板时会解析它们,来自:
-
--parameter-overrides传递给 Amazon SAMCLI命令。 -
模板中参数的
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}/
&{标识符} 语法
该&{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
支持的内部函数
在扩展过程中,以下内部函数将在本地解析:
| 函数 | 说明 |
|---|---|
|
循环扩展。 |
|
返回列表元素的数量。 |
|
将值转换为字符JSON串。 |
|
地图查询,包括可选的 |
|
条件值选择。 |
|
字符串替换。 |
|
字符串连接。 |
|
字符串拆分。 |
|
列表元素选择。 |
|
Base64 编码。 |
|
状况评估。 |
|
参数和伪参数引用。 |
需要部署资源(Fn::GetAtt、Fn::ImportValue、Fn::GetAZs)的函数会被保留, Amazon CloudFormation 以便在部署时解析。
验证错误
在 Amazon SAM 转换运行之前,会在本地捕获以下模板问题:
| 原因 | 错误消息 |
|---|---|
该 |
|
嵌套了超过 5 |
|
集合解析为空列表(例如,带的 |
没有错误 — 循环被静默跳过,并且不会发出任何资源。 |
集合 |
没有错误 — 未解析的引用保留在模板中。在部署时, 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 — 请勿使用这些前缀创作自己的映射:
-
SAMCodeUri、SAMImageUri、SAMContentUri、SAMDefinitionUri、SAMSchemaUri、SAMBodyS3Location、SAMDefinitionS3Location、SAMTemplateURL、SAMCode、SAMContent—sam package为动态构件属性发出。参见动态构件属性表格。 -
SAMLayers— 由Fn::ForEach生成的函数获取自动生成的依赖层引用(Lambda 将构建分层到嵌套堆栈中)sam build时发出。 Amazon SAMCLI此前缀没有相应的用户创作属性;它是自动添加的。
-
遥测
当使用--language-extensions(或 Amazon SAMCLI其等效环境变量)调用命令并且模板声明转换时,会发出CFNLanguageExtensions遥测事件。AWS::LanguageExtensions该事件每次调用都会触发一次,并且不会传输任何模板内容。本地处理处于关闭状态(默认)时,不会触发任何事件。