

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

# 条件函数
<a name="intrinsic-function-reference-conditions"></a>

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

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

如果您是首次在模板中使用条件，建议您先查看《*Amazon CloudFormation 用户指南*》中有关 [CloudFormation 模板条件语法](https://docs.amazonaws.cn/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html)的内容。

**注意**  
必须在模板的 `Conditions` 部分中定义所有条件（`Fn::If` 条件除外）。您可以在 `Resources` 和 `Outputs` 部分的 `Metadata` 属性、`UpdatePolicy` 属性和属性值中使用 `Fn::If` 条件。

**Topics**
+ [`Fn::And`](#intrinsic-function-reference-conditions-and)
+ [`Fn::Equals`](#intrinsic-function-reference-conditions-equals)
+ [`Fn::If`](#intrinsic-function-reference-conditions-if)
+ [`Fn::Not`](#intrinsic-function-reference-conditions-not)
+ [`Fn::Or`](#intrinsic-function-reference-conditions-or)
+ [支持的函数](#w2aac24c20c25)
+ [示例模板](#conditions-sample-templates)

## `Fn::And`
<a name="intrinsic-function-reference-conditions-and"></a>

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

### 声明
<a name="intrinsic-function-reference-conditions-and-syntax"></a>

#### JSON
<a name="intrinsic-function-reference-conditions-and-syntax.json"></a>

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

#### YAML
<a name="intrinsic-function-reference-conditions-and-syntax.yaml"></a>

完整函数名称的语法：

```
Fn::And: [condition]
```

短格式的语法：

```
!And [condition]
```

### 参数
<a name="w2aac24c20c13b7"></a>

condition  <a name="fn-and-condition"></a>
计算为 `true` 或 `false` 的条件。

### `Fn::And` 用法示例
<a name="w2aac24c20c13b9"></a>

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

#### JSON
<a name="intrinsic-function-reference-conditions-and-example.json"></a>

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

#### YAML
<a name="intrinsic-function-reference-conditions-and-example.yaml"></a>

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

## `Fn::Equals`
<a name="intrinsic-function-reference-conditions-equals"></a>

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

### 声明
<a name="intrinsic-function-reference-conditions-equals-syntax"></a>

#### JSON
<a name="intrinsic-function-reference-conditions-equals-syntax.json"></a>

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

#### YAML
<a name="intrinsic-function-reference-conditions-equals-syntax.yaml"></a>

完整函数名称的语法：

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

短格式的语法：

```
!Equals [value_1, value_2]
```

### 参数
<a name="w2aac24c20c15b7"></a>

value  
您想要比较的字符串值。

### `Fn::Equals` 用法示例
<a name="w2aac24c20c15b9"></a>

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

#### JSON
<a name="intrinsic-function-reference-conditions-equals-example.json"></a>

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

#### YAML
<a name="intrinsic-function-reference-conditions-equals-example.yaml"></a>

```
IsProduction:
  !Equals [!Ref EnvironmentType, prod]
```

## `Fn::If`
<a name="intrinsic-function-reference-conditions-if"></a>

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

### 声明
<a name="intrinsic-function-reference-conditions-if-syntax"></a>

#### JSON
<a name="intrinsic-function-reference-conditions-if-syntax.json"></a>

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

#### YAML
<a name="intrinsic-function-reference-conditions-if-syntax.yaml"></a>

完整函数名称的语法：

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

短格式的语法：

```
!If [condition_name, value_if_true, value_if_false]
```

### 参数
<a name="w2aac24c20c19b7"></a>

condition\$1name  <a name="condition_name"></a>
条件部分中对条件的引用。使用条件名称引用它。

value\$1if\$1true  <a name="value_if_true"></a>
当指定的条件计算为 true 时要返回的值。

value\$1if\$1false  <a name="value_if_false"></a>
当指定的条件计算为 `false` 时要返回的值。

### `Fn::If` 用法示例
<a name="w2aac24c20c19b9"></a>

**Topics**
+ [有条件地选择资源](#w2aac24c20c19b9b5)
+ [条件输出](#w2aac24c20c19b9b7)
+ [条件数组值](#w2aac24c20c19b9b9)
+ [条件属性和属性值](#w2aac24c20c19b9c11)
+ [条件更新策略](#w2aac24c20c19b9c13)

#### 有条件地选择资源
<a name="w2aac24c20c19b9b5"></a>

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

##### JSON
<a name="intrinsic-function-reference-conditions-if-example1.json"></a>

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

##### YAML
<a name="intrinsic-function-reference-conditions-if-example1.yaml"></a>

```
Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-0abcdef1234567890
      InstanceType: t3.micro
      SecurityGroupIds: !If
        - CreateNewSecurityGroup
        - [!Ref NewSecurityGroup]
        - [!Ref ExistingSecurityGroupId]
```

#### 条件输出
<a name="w2aac24c20c19b9b7"></a>

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

##### JSON
<a name="intrinsic-function-reference-conditions-if-example2.json"></a>

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

##### YAML
<a name="intrinsic-function-reference-conditions-if-example2.yaml"></a>

```
Outputs:
  SecurityGroupId: 
    Description: Group ID of the security group used.
    Value: !If [CreateNewSecurityGroup, !Ref NewSecurityGroup, !Ref ExistingSecurityGroupId]
```

#### 条件数组值
<a name="w2aac24c20c19b9b9"></a>

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

##### JSON
<a name="intrinsic-function-reference-conditions-if-example-arrays.json"></a>

```
"Subnets": {
  "Fn::If": [
    "MoreThan2AZs",
    [
      {"Fn::ImportValue": "PublicSubnet01"},
      {"Fn::ImportValue": "PublicSubnet02"},
      {"Fn::ImportValue": "PublicSubnet03"}
    ],
    [
      {"Fn::ImportValue": "PublicSubnet01"},
      {"Fn::ImportValue": "PublicSubnet02"}
    ]
  ]
}
```

##### YAML
<a name="intrinsic-function-reference-conditions-if-example-arrays.yaml"></a>

```
Subnets:
  Fn::If:
    - MoreThan2AZs
    - - Fn::ImportValue: PublicSubnet01
      - Fn::ImportValue: PublicSubnet02
      - Fn::ImportValue: PublicSubnet03
    - - Fn::ImportValue: PublicSubnet01
      - Fn::ImportValue: PublicSubnet02
```

#### 条件属性和属性值
<a name="w2aac24c20c19b9c11"></a>

下面的示例在 `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
<a name="intrinsic-function-reference-conditions-if-example3.json"></a>

```
"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
<a name="intrinsic-function-reference-conditions-if-example3.yaml"></a>

```
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"]
```

#### 条件更新策略
<a name="w2aac24c20c19b9c13"></a>

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

##### JSON
<a name="intrinsic-function-reference-conditions-if-example4.json"></a>

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

##### YAML
<a name="intrinsic-function-reference-conditions-if-example4.yaml"></a>

```
UpdatePolicy: !If
  - RollingUpdates
  - AutoScalingRollingUpdate:
      MaxBatchSize: 2
      MinInstancesInService: 2
      PauseTime: PT0M30S
  - !Ref "AWS::NoValue"
```

## `Fn::Not`
<a name="intrinsic-function-reference-conditions-not"></a>

对计算为 `true` 的条件返回 `false`，对计算为 `false` 的条件返回 `true`。`Fn::Not` 用作 NOT 运算符。

### 声明
<a name="intrinsic-function-reference-conditions-not-syntax"></a>

#### JSON
<a name="intrinsic-function-reference-conditions-not-syntax.json"></a>

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

#### YAML
<a name="intrinsic-function-reference-conditions-not-syntax.yaml"></a>

完整函数名称的语法：

```
Fn::Not: [condition]
```

短格式的语法：

```
!Not [condition]
```

### 参数
<a name="w2aac24c20c21b7"></a>

condition  <a name="condition"></a>
计算为 `Fn::Equals` 或 `true` 的条件 (如 `false`)。

### `Fn::Not` 用法示例
<a name="w2aac24c20c21b9"></a>

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

#### JSON
<a name="intrinsic-function-reference-conditions-not-example.json"></a>

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

#### YAML
<a name="intrinsic-function-reference-conditions-not-example.yaml"></a>

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

## `Fn::Or`
<a name="intrinsic-function-reference-conditions-or"></a>

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

### 声明
<a name="intrinsic-function-reference-conditions-or-syntax"></a>

#### JSON
<a name="intrinsic-function-reference-conditions-or-syntax.json"></a>

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

#### YAML
<a name="intrinsic-function-reference-conditions-or-syntax.yaml"></a>

完整函数名称的语法：

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

短格式的语法：

```
!Or [condition, ...]
```

### 参数
<a name="w2aac24c20c23b7"></a>

condition  
计算为 `true` 或 `false` 的条件。

### `Fn::Or` 用法示例
<a name="w2aac24c20c23b9"></a>

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

#### JSON
<a name="intrinsic-function-reference-conditions-or-example.json"></a>

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

#### YAML
<a name="intrinsic-function-reference-conditions-or-example.yaml"></a>

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

## 支持的函数
<a name="w2aac24c20c25"></a>

您可以在 `Fn::If` 条件中使用以下函数：
+ `Fn::Base64`
+ `Fn::FindInMap`
+ `Fn::GetAtt`
+ `Fn::GetAZs`
+ `Fn::If`
+ `Fn::Join`
+ `Fn::Select`
+ `Fn::Sub`
+ `Ref`

您可在所有其他条件函数中使用以下函数，如 `Fn::Equals` 和 `Fn::Or`：
+ `Fn::FindInMap`
+ `Ref`
+ 其他条件函数

## 示例模板
<a name="conditions-sample-templates"></a>

### 按条件为生产、开发或测试堆栈创建资源
<a name="w2aac24c20c27b3"></a>

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

您可以为 `prod` 参数指定 `dev`、`test` 或 `EnvType`。对于每种环境类型，模板都指定一个不同的实例类型。实例类型范围可以从大型计算优化实例类型到小型通用实例类型。为了按条件指定实例类型，该模板在模板的 `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 卷。`MountPoint` 和 `NewVolume` 资源与 `CreateProdResources` 条件相关联，目的是仅当条件计算为 true 时才创建资源。

**Example 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" ]}
      }
    }
  }
}
```

**Example 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` 属性](aws-attribute-condition.md) 主题。