条件函数 - Amazon CloudFormation
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

这是新的《Amazon CloudFormation 模板参考指南》。请更新您的书签和链接。有关开始使用 CloudFormation 的帮助,请参阅《Amazon CloudFormation 用户指南》https://docs.amazonaws.cn/AWSCloudFormation/latest/UserGuide/Welcome.html

条件函数

您可以使用内置函数(如 Fn::IfFn::Equals)按条件逻辑创建和配置堆栈资源。这些条件会在堆栈创建或更新过程中进行评估。定义所有条件后,您可以在模板的 ResourcesOutputs 部分将它们与资源或资源属性关联起来。

对于复杂场景,您可以使用 Fn::AndFn::Or 函数组合多个条件,也可以使用 Fn::Not 函数对条件值取反。您还可以嵌套条件,以创建更复杂的条件逻辑。

如果您是首次在模板中使用条件,建议您先查看《Amazon CloudFormation 用户指南》中有关 CloudFormation 模板条件语法的内容。

注意

必须在模板的 Conditions 部分中定义所有条件(Fn::If 条件除外)。您可以在 ResourcesOutputs 部分的 Metadata 属性、UpdatePolicy 属性和属性值中使用 Fn::If 条件。

Fn::And

如果所有指定条件计算为 true,则返回 true,如果任意条件计算为 false,则返回 falseFn::And 用作 AND 运算符。您最少可以包含两个条件,最多可以包含 10 个条件。

声明

JSON

"Fn::And": [{condition}, {...}]

YAML

完整函数名称的语法:

Fn::And: [condition]

短格式的语法:

!And [condition]

参数

condition

计算为 truefalse 的条件。

Fn::And 用法示例

当引用的安全组名称等于 MyAndCondition 并且 sg-mysggroup 计算为 true 时,下面的 SomeOtherCondition 计算为 true:

JSON

"MyAndCondition": { "Fn::And": [ {"Fn::Equals": ["sg-mysggroup", {"Ref": "ASecurityGroup"}]}, {"Condition": "SomeOtherCondition"} ] }

YAML

MyAndCondition: !And - !Equals ["sg-mysggroup", !Ref ASecurityGroup] - !Condition SomeOtherCondition

Fn::Equals

比较两个值是否相等。如果两个值相等,则返回 true,如果不等,则返回 false

声明

JSON

"Fn::Equals" : ["value_1", "value_2"]

YAML

完整函数名称的语法:

Fn::Equals: [value_1, value_2]

短格式的语法:

!Equals [value_1, value_2]

参数

value

您想要比较的字符串值。

Fn::Equals 用法示例

如果 IsProduction 参数的值等于 EnvironmentType,则下面的 prod 条件计算为 true:

JSON

"IsProduction" : { "Fn::Equals": [ {"Ref": "EnvironmentType"}, "prod" ] }

YAML

IsProduction: !Equals [!Ref EnvironmentType, prod]

Fn::If

如果指定的条件计算为 true,则返回一个值,如果指定的条件计算为 false,则返回另一个值。当前,CloudFormation 在模板 Resources 部分和 Outputs 部分的 Metadata 属性、UpdatePolicy 属性和属性值中支持 Fn::If 内置函数。您可以使用 AWS::NoValue 伪参数作为返回值来删除相应的属性。

声明

YAML

完整函数名称的语法:

Fn::If: [condition_name, value_if_true, value_if_false]

短格式的语法:

!If [condition_name, value_if_true, value_if_false]

参数

condition_name

条件部分中对条件的引用。使用条件名称引用它。

value_if_true

当指定的条件计算为 true 时要返回的值。

value_if_false

当指定的条件计算为 false 时要返回的值。

Fn::If 用法示例

有条件地选择资源

以下示例在 Amazon EC2 资源定义中使用了一个 Fn::If 函数,用于确定将哪个安全组资源与实例关联。如果 CreateNewSecurityGroup 的评估结果为 true,则 CloudFormation 会使用 NewSecurityGroup(在模板的其他位置创建的安全组)的引用值来指定 SecurityGroupIds 属性;如果 CreateNewSecurityGroup 为 false,则 CloudFormation 会使用 ExistingSecurityGroupId(引用现有安全组的参数)的引用值。

JSON
"Resources": { "EC2Instance": { "Type": "AWS::EC2::Instance", "Properties": { "ImageId": "ami-0abcdef1234567890", "InstanceType": "t3.micro", "SecurityGroupIds": { "Fn::If": [ "CreateNewSecurityGroup", [{"Ref": "NewSecurityGroup"}], [{"Ref": "ExistingSecurityGroupId"}] ] }] } } }
YAML
Resources: EC2Instance: Type: AWS::EC2::Instance Properties: ImageId: ami-0abcdef1234567890 InstanceType: t3.micro SecurityGroupIds: !If - CreateNewSecurityGroup - [!Ref NewSecurityGroup] - [!Ref ExistingSecurityGroupId]

条件输出

在模板的 Output 部分中,您可以使用 Fn::If 函数按条件输出信息。在以下代码段中,如果 CreateNewSecurityGroup 条件的计算结果为 true,则 CloudFormation 输出 NewSecurityGroup 资源的安全组 ID。如果条件为 false,则 CloudFormation 输出 ExistingSecurityGroup 资源的安全组 ID。

JSON
"Outputs" : { "SecurityGroupId" : { "Description" : "Group ID of the security group used.", "Value" : { "Fn::If" : [ "CreateNewSecurityGroup", {"Ref" : "NewSecurityGroup"}, {"Ref" : "ExistingSecurityGroupId"} ] } } }
YAML
Outputs: SecurityGroupId: Description: Group ID of the security group used. Value: !If [CreateNewSecurityGroup, !Ref NewSecurityGroup, !Ref ExistingSecurityGroupId]

条件数组值

以下示例使用 Fn::If 根据条件提供不同的数组值。如果 MoreThan2AZs 条件的评估结果为 true,则使用三个公共子网。否则,仅使用两个公共子网。

JSON
"Subnets": { "Fn::If": [ "MoreThan2AZs", [ {"Fn::ImportValue": "PublicSubnet01"}, {"Fn::ImportValue": "PublicSubnet02"}, {"Fn::ImportValue": "PublicSubnet03"} ], [ {"Fn::ImportValue": "PublicSubnet01"}, {"Fn::ImportValue": "PublicSubnet02"} ] ] }
YAML
Subnets: Fn::If: - MoreThan2AZs - - Fn::ImportValue: PublicSubnet01 - Fn::ImportValue: PublicSubnet02 - Fn::ImportValue: PublicSubnet03 - - Fn::ImportValue: PublicSubnet01 - Fn::ImportValue: PublicSubnet02

条件属性和属性值

下面的示例在 AWS::NoValue 函数中使用 Fn::If 伪参数。仅当提供了快照 ID 时,该条件才对 Amazon RDS 数据库实例使用快照。如果 UseDBSnapshot 条件计算为 true,则 CloudFormation 对 DBSnapshotIdentifier 属性使用 DBSnapshotName 参数值。如果条件计算为 false,则 CloudFormation 删除 DBSnapshotIdentifier 属性。

此外,它还在 Amazon RDS 数据库实例的 AllocatedStorage 属性中使用了一个 Fn::If 函数。如果 IsProduction 的评估结果为 true,则存储大小将设置为 100;否则,该值将设置为 20

JSON
"MyDatabase" : { "Type" : "AWS::RDS::DBInstance", "Properties": { "DBInstanceClass": "db.t3.micro", "AllocatedStorage": { "Fn::If": [ "IsProduction", 100, 20 ] }, "Engine" : "MySQL", "EngineVersion" : "5.5", "MasterUsername" : { "Ref" : "DBUser" }, "MasterUserPassword" : { "Ref" : "DBPassword" }, "DBParameterGroupName" : { "Ref" : "MyRDSParamGroup" }, "DBSnapshotIdentifier" : { "Fn::If" : [ "UseDBSnapshot", {"Ref" : "DBSnapshotName"}, {"Ref" : "AWS::NoValue"} ] } } }
YAML
MyDatabase: Type: AWS::RDS::DBInstance Properties: DBInstanceClass: db.t3.micro AllocatedStorage: !If [IsProduction, 100, 20] Engine: MySQL EngineVersion: 5.5 MasterUsername: !Ref DBUser MasterUserPassword: !Ref DBPassword DBParameterGroupName: !Ref MyRDSParamGroup DBSnapshotIdentifier: !If [UseDBSnapshot, !Ref DBSnapshotName, !Ref "AWS::NoValue"]

条件更新策略

以下代码段仅当 RollingUpdates 条件计算为 true 时,才提供 Auto Scaling 更新策略。如果条件计算结果为 false,则 CloudFormation 删除 AutoScalingRollingUpdate 更新策略。

JSON
"UpdatePolicy": { "Fn::If": [ "RollingUpdates", { "AutoScalingRollingUpdate": { "MaxBatchSize": 2, "MinInstancesInService": 2, "PauseTime": "PT0M30S" } }, { "Ref": "AWS::NoValue" } ] }
YAML
UpdatePolicy: !If - RollingUpdates - AutoScalingRollingUpdate: MaxBatchSize: 2 MinInstancesInService: 2 PauseTime: PT0M30S - !Ref "AWS::NoValue"

Fn::Not

对计算为 true 的条件返回 false,对计算为 false 的条件返回 trueFn::Not 用作 NOT 运算符。

声明

JSON

"Fn::Not": [{condition}]

YAML

完整函数名称的语法:

Fn::Not: [condition]

短格式的语法:

!Not [condition]

参数

condition

计算为 Fn::Equalstrue 的条件 (如 false)。

Fn::Not 用法示例

如果 EnvironmentType 参数的值不等于 prod,则下面的 EnvCondition 条件计算为 true:

JSON

"MyNotCondition" : { "Fn::Not" : [{ "Fn::Equals" : [ {"Ref" : "EnvironmentType"}, "prod" ] }] }

YAML

MyNotCondition: !Not [!Equals [!Ref EnvironmentType, prod]]

Fn::Or

如果任意一个指定条件计算为 true,则返回 true,如果所有条件都计算为 false,则返回 falseFn::Or 用作 OR 运算符。您最少可以包含两个条件,最多可以包含 10 个条件。

声明

JSON

"Fn::Or": [{condition}, {...}]

YAML

完整函数名称的语法:

Fn::Or: [condition, ...]

短格式的语法:

!Or [condition, ...]

参数

condition

计算为 truefalse 的条件。

Fn::Or 用法示例

如果引用的安全组名称等于 MyOrCondition 或者 sg-mysggroup 计算为 true,则下面的 SomeOtherCondition 计算为 true:

JSON

"MyOrCondition" : { "Fn::Or" : [ {"Fn::Equals" : ["sg-mysggroup", {"Ref" : "ASecurityGroup"}]}, {"Condition" : "SomeOtherCondition"} ] }

YAML

MyOrCondition: !Or [!Equals [sg-mysggroup, !Ref ASecurityGroup], Condition: SomeOtherCondition]

支持的函数

您可以在 Fn::If 条件中使用以下函数:

  • Fn::Base64

  • Fn::FindInMap

  • Fn::GetAtt

  • Fn::GetAZs

  • Fn::If

  • Fn::Join

  • Fn::Select

  • Fn::Sub

  • Ref

您可在所有其他条件函数中使用以下函数,如 Fn::EqualsFn::Or

  • Fn::FindInMap

  • Ref

  • 其他条件函数

示例模板

按条件为生产、开发或测试堆栈创建资源

在某些情况下,您可能需要创建类似但略有不同的堆栈。例如,您可能有一个用于生产应用程序的模板。您需要创建相同的生产堆栈来用于开发或测试。但是,对于开发和测试,您可能不需要生产级堆栈中包含的所有额外容量。您可以使用环境类型输入参数按条件创建特定于生产、开发或测试的堆栈资源,如以下示例所示:

您可以为 prod 参数指定 devtestEnvType。对于每种环境类型,模板都指定一个不同的实例类型。实例类型范围可以从大型计算优化实例类型到小型通用实例类型。为了按条件指定实例类型,该模板在模板的 Conditions 部分定义两个条件:CreateProdResources,如果 EnvType 参数值等于 prod,则计算为 true;CreateDevResources,如果该参数值等于 dev,则计算为 true。

InstanceType 属性中,该模板嵌套了两个 Fn::If 内部函数来确定使用哪个实例类型。如果 CreateProdResources 条件为 true,则实例类型为 c5.xlarge。如果条件为 false,则计算 CreateDevResources 条件。如果 CreateDevResources 条件为 true,则实例类型为 t3.medium,否则实例类型为 t3.small

除实例类型之外,生产环境还向实例创建并附加一个 Amazon EC2 卷。MountPointNewVolume 资源与 CreateProdResources 条件相关联,目的是仅当条件计算为 true 时才创建资源。

例 JSON
{ "AWSTemplateFormatVersion" : "2010-09-09", "Parameters" : { "EnvType" : { "Description" : "Environment type.", "Default" : "test", "Type" : "String", "AllowedValues" : ["prod", "dev", "test"], "ConstraintDescription" : "must specify prod, dev, or test." } }, "Conditions" : { "CreateProdResources" : {"Fn::Equals" : [{"Ref" : "EnvType"}, "prod"]}, "CreateDevResources" : {"Fn::Equals" : [{"Ref" : "EnvType"}, "dev"]} }, "Resources" : { "EC2Instance" : { "Type" : "AWS::EC2::Instance", "Properties" : { "ImageId" : "ami-1234567890abcdef0", "InstanceType" : { "Fn::If" : [ "CreateProdResources", "c5.xlarge", {"Fn::If" : [ "CreateDevResources", "t3.medium", "t3.small" ]} ]} } }, "MountPoint" : { "Type" : "AWS::EC2::VolumeAttachment", "Condition" : "CreateProdResources", "Properties" : { "InstanceId" : { "Ref" : "EC2Instance" }, "VolumeId" : { "Ref" : "NewVolume" }, "Device" : "/dev/sdh" } }, "NewVolume" : { "Type" : "AWS::EC2::Volume", "Condition" : "CreateProdResources", "Properties" : { "Size" : "100", "AvailabilityZone" : { "Fn::GetAtt" : [ "EC2Instance", "AvailabilityZone" ]} } } } }
例 YAML
AWSTemplateFormatVersion: "2010-09-09" Parameters: EnvType: Description: Environment type. Default: test Type: String AllowedValues: [prod, dev, test] ConstraintDescription: must specify prod, dev, or test. Conditions: CreateProdResources: !Equals [!Ref EnvType, prod] CreateDevResources: !Equals [!Ref EnvType, "dev"] Resources: EC2Instance: Type: AWS::EC2::Instance Properties: ImageId: ami-1234567890abcdef0 InstanceType: !If [CreateProdResources, c5.xlarge, !If [CreateDevResources, t3.medium, t3.small]] MountPoint: Type: AWS::EC2::VolumeAttachment Condition: CreateProdResources Properties: InstanceId: !Ref EC2Instance VolumeId: !Ref NewVolume Device: /dev/sdh NewVolume: Type: AWS::EC2::Volume Condition: CreateProdResources Properties: Size: 100 AvailabilityZone: !GetAtt EC2Instance.AvailabilityZone
注意

有关使用条件创建资源的更复杂示例,请参阅 Condition 属性 主题。