

# CloudFormation 模板 Conditions 语法
<a name="conditions-section-structure"></a>

可选的 `Conditions` 部分包含一些声明，以定义在哪些情况下创建或配置实体。例如，您可以创建一个条件，然后将其与某个资源或输出关联，以便 CloudFormation 仅在该条件成立时创建该资源或输出。同样，您可以将条件与一个属性关联，以便 CloudFormation 仅在该条件为 true 时将该属性设置为特定的值。如果该条件为 false，则 CloudFormation 会将该属性设置为您指定的其他值。

当您需要重新使用模板在不同环境（如测试环境与生产环境）中创建资源时，可以使用条件。例如，在模板中，您可以添加 `EnvironmentType` 输入参数，它接受 `prod` 或 `test` 以作为输入。对于 `prod` 环境，您可以采用带特定功能的 EC2 实例；但对于 `test` 环境，您可以使用更少功能，以便节约资金。通过定义条件，您可以定义为每个环境类型创建哪些资源以及如何配置资源。

## 语法
<a name="conditions-section-structure-syntax"></a>

`Conditions` 部分包括键名称 `Conditions`。每个条件声明均包括一个逻辑 ID 和多个内置函数。

### JSON
<a name="conditions-section-structure-syntax.json"></a>

```
"Conditions": {
  "{{LogicalConditionName1}}": {
    "{{Intrinsic function}}": {{...}}[
  },

  "{{LogicalConditionName2}}": {
    "{{Intrinsic function}}": {{...}}
  }
}
```

### YAML
<a name="conditions-section-structure-syntax.yaml"></a>

```
Conditions:
  {{LogicalConditionName1}}:
    {{Intrinsic function}}:
      {{...}}

  {{LogicalConditionName2}}:
    {{Intrinsic function}}:
      {{...}}
```

## 条件的工作原理
<a name="conditions-section-structure-overview"></a>

要使用条件，请按照下列步骤操作：

1. **添加参数定义**：定义条件在模板 `Parameters` 部分中进行评估的输入。根据这些输入参数的值，条件评估结果为 true 或 false。请注意，伪参数是自动可用的，不需要在 `Parameters` 部分中进行明确定义。有关伪参数的更多信息，请参阅[使用伪参数获取 Amazon 值](pseudo-parameter-reference.md)。

1. **添加条件定义**：使用内置函数（例如 `Fn::If` 或 `Fn::Equals`）在 `Conditions` 部分中定义条件。这些条件将决定 CloudFormation 何时创建关联的资源。条件可以基于：
   + 输入或伪参数值
   + 其他条件
   + 映射值

   但是，您不能在条件中引用资源逻辑 ID 或其属性。

1. **将条件与资源或输出关联**：使用 `Condition` 键和条件的逻辑 ID 在资源或输出中引用条件。或者，也可以在模板的其他部分（例如属性值）中使用 `Fn::If` 以根据条件设置值。有关更多信息，请参阅 [使用 `Condition` 密钥](#using-conditions-in-templates)。

在创建或更新堆栈时，CloudFormation 会评估条件。CloudFormation 创建与成立的条件关联的实体，并忽略与不成立的条件关联的实体。在每个堆栈更新期间，CloudFormation 还会在修改任何资源之前重新评估这些条件。与 true 条件关联的实体将会更新，与 false 条件关联的实体将会删除。

**重要**  
堆栈更新期间，您无法更新条件本身。您只能在包含添加、修改或删除资源的更改时更新条件。

## 条件内部函数
<a name="conditions-section-structure-functions"></a>

您可以使用以下内部函数定义条件：
+ [https://docs.amazonaws.cn/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-and](https://docs.amazonaws.cn/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-and)
+ [https://docs.amazonaws.cn/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-equals](https://docs.amazonaws.cn/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-equals)
+ [https://docs.amazonaws.cn/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-foreach.html](https://docs.amazonaws.cn/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-foreach.html)
+ [https://docs.amazonaws.cn/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-if](https://docs.amazonaws.cn/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-if)
+ [https://docs.amazonaws.cn/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-not](https://docs.amazonaws.cn/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-not)
+ [https://docs.amazonaws.cn/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-or](https://docs.amazonaws.cn/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-conditions.html#intrinsic-function-reference-conditions-or)

**注意**  
仅在模板的 `Resources` 和 `Outputs` 部分中的元数据属性、更新策略属性和属性值中支持 `Fn::If`。

## 使用 `Condition` 密钥
<a name="using-conditions-in-templates"></a>

定义条件后，您可以使用 `Condition` 密钥将其应用于模板中的多个位置，例如 `Resources` 和 `Outputs`。`Condition` 密钥引用条件的逻辑名称并返回指定条件的评估结果。

**Topics**
+ [将条件与资源关联](#associate-conditions-with-resources)
+ [将条件与输出关联](#associate-conditions-with-outputs)
+ [其他条件中的引用条件](#reference-conditions-in-other-conditions)
+ [使用 `Fn::If` 有条件地返回属性值](#conditional-return-property-values-using-fn-if)

### 将条件与资源关联
<a name="associate-conditions-with-resources"></a>

要有条件地创建资源，请添加 `Condition` 密钥，并将条件的逻辑 ID 作为属性添加到该资源中。仅当 条件评估为 true 时，CloudFormation 才会创建 资源。

#### JSON
<a name="associate-conditions-with-resources.json"></a>

```
"NewVolume" : {
  "Type" : "AWS::EC2::Volume",
  "Condition" : "IsProduction",
  "Properties" : {
     "Size" : "100",
     "AvailabilityZone" : { "Fn::GetAtt" : [ "EC2Instance", "AvailabilityZone" ]}
  }
}
```

#### YAML
<a name="associate-conditions-with-resources.yaml"></a>

```
NewVolume:
  Type: AWS::EC2::Volume
  Condition: IsProduction
  Properties:
    Size: 100
    AvailabilityZone: !GetAtt EC2Instance.AvailabilityZone
```

### 将条件与输出关联
<a name="associate-conditions-with-outputs"></a>

您还可以将条件与输出关联。仅当关联条件的评估结果为 true 时，CloudFormation 才会创建输出。

#### JSON
<a name="associate-conditions-with-outputs.json"></a>

```
"Outputs" : {
  "VolumeId" : {
    "Condition" : "IsProduction",
    "Value" : { "Ref" : "NewVolume" }
  }
}
```

#### YAML
<a name="associate-conditions-with-outputs.yaml"></a>

```
Outputs:
  VolumeId:
    Condition: IsProduction
    Value: !Ref NewVolume
```

### 其他条件中的引用条件
<a name="reference-conditions-in-other-conditions"></a>

在 `Conditions` 部分中定义条件时，可以使用 `Condition` 密钥引用其他条件。这使您能够通过组合多个条件来创建更复杂的条件逻辑。

在以下示例中，仅当 `IsProduction` 和 `IsProdAndFeatureEnabled` 条件的评估结果为 true 时，`IsFeatureEnabled` 条件才会评估为 true。

#### JSON
<a name="reference-conditions-in-other-conditions.json"></a>

```
"Conditions": {
  "IsProduction" : {"Fn::Equals" : [{"Ref" : "Environment"}, "prod"]},
  "IsFeatureEnabled" : { "Fn::Equals" : [{"Ref" : "FeatureFlag"}, "enabled"]},
  "IsProdAndFeatureEnabled" : {
    "Fn::And" : [
      {"Condition" : "IsProduction"},
      {"Condition" : "IsFeatureEnabled"}
    ]
  }
}
```

#### YAML
<a name="reference-conditions-in-other-conditions.yaml"></a>

```
Conditions:
  IsProduction:
    !Equals [!Ref Environment, "prod"]
  IsFeatureEnabled:
    !Equals [!Ref FeatureFlag, "enabled"]
  IsProdAndFeatureEnabled: !And
    - !Condition IsProduction
    - !Condition IsFeatureEnabled
```

### 使用 `Fn::If` 有条件地返回属性值
<a name="conditional-return-property-values-using-fn-if"></a>

要进行更精细的控制，您可以使用 `Fn::If` 内置函数有条件地返回资源或输出中的两个属性值之一。该函数会对条件进行评估，如果条件为 true，则返回一个值；如果条件为 false，则返回另一个值。

#### 条件属性值
<a name="using-fn-if-for-conditional-values"></a>

以下示例演示了如何根据环境条件设置 EC2 实例类型。如果 `IsProduction` 条件的评估结果为 true，则实例类型设置为 `c5.xlarge`。否则，该值将设置为 `t3.small`。

##### JSON
<a name="using-fn-if-for-conditional-values.json"></a>

```
"Properties" : {
  "InstanceType" : {
    "Fn::If" : [
      "IsProduction",
      "c5.xlarge",
      "t3.small"
    ]
  }
}
```

##### YAML
<a name="using-fn-if-for-conditional-values.yaml"></a>

```
Properties:
  InstanceType: !If
    - IsProduction
    - c5.xlarge
    - t3.small
```

#### 条件属性移除
<a name="using-fn-if-with-novalue"></a>

您也可以使用 `AWS::NoValue` 伪参数名称】作为返回值，在条件为 false 时移除对应的属性。

##### JSON
<a name="using-fn-if-with-novalue.json"></a>

```
"DBSnapshotIdentifier" : {
  "Fn::If" : [
    "UseDBSnapshot",
    {"Ref" : "DBSnapshotName"},
    {"Ref" : "AWS::NoValue"}
  ]
}
```

##### YAML
<a name="using-fn-if-with-novalue.yaml"></a>

```
DBSnapshotIdentifier: !If
  - UseDBSnapshot
  - !Ref DBSnapshotName
  - !Ref "AWS::NoValue"
```

## 示例
<a name="conditions-section-structure-examples"></a>

**Topics**
+ [基于环境创建资源](#environment-based-resource-creation)
+ [多条件资源预置](#multi-condition-resource-provisioning)

### 基于环境创建资源
<a name="environment-based-resource-creation"></a>

以下示例将预置一个 EC2 实例，并且仅当环境类型为 `prod` 时，才会有条件地创建和附加新的 EBS 卷。如果环境是 `test`，示例则只会创建不带额外卷的 EC2 实例。

#### JSON
<a name="conditions-section-example-resource-creation.json"></a>

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

#### YAML
<a name="conditions-section-example-resource-creation.yaml"></a>

```
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  EnvType:
    Description: Environment type
    Default: test
    Type: String
    AllowedValues:
      - prod
      - test
    ConstraintDescription: must specify prod or test
Conditions:
  IsProduction: !Equals
    - !Ref EnvType
    - prod
Resources:
  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-1234567890abcdef0
      InstanceType: c5.xlarge
  MountPoint:
    Type: AWS::EC2::VolumeAttachment
    Condition: IsProduction
    Properties:
      InstanceId: !Ref EC2Instance
      VolumeId: !Ref NewVolume
      Device: /dev/sdh
  NewVolume:
    Type: AWS::EC2::Volume
    Condition: IsProduction
    Properties:
      Size: 100
      AvailabilityZone: !GetAtt
        - EC2Instance
        - AvailabilityZone
```

### 多条件资源预置
<a name="multi-condition-resource-provisioning"></a>

如果提供了存储桶名称，则以下示例会有条件地创建 S3 存储桶，并且仅当环境设置为 `prod` 时，才会附加存储桶策略。如果未提供存储桶名称或环境为 `test`，则不会创建任何资源。

#### JSON
<a name="conditions-section-example-multi-condition.json"></a>

```
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Parameters": {
        "EnvType": {
            "Type": "String",
            "AllowedValues": [
                "prod",
                "test"
            ]
        },
        "BucketName": {
            "Default": "",
            "Type": "String"
        }
    },
    "Conditions": {
        "IsProduction": {
            "Fn::Equals": [
                {
                    "Ref": "EnvType"
                },
                "prod"
            ]
        },
        "CreateBucket": {
            "Fn::Not": [
                {
                    "Fn::Equals": [
                        {
                            "Ref": "BucketName"
                        },
                        ""
                    ]
                }
            ]
        },
        "CreateBucketPolicy": {
            "Fn::And": [
                {
                    "Condition": "IsProduction"
                },
                {
                    "Condition": "CreateBucket"
                }
            ]
        }
    },
    "Resources": {
        "Bucket": {
            "Type": "AWS::S3::Bucket",
            "Condition": "CreateBucket",
            "Properties": {
                "BucketName": {
                    "Ref": "BucketName"
                }
            }
        },
        "Policy": {
            "Type": "AWS::S3::BucketPolicy",
            "Condition": "CreateBucketPolicy",
            "Properties": {
                "Bucket": {
                    "Ref": "Bucket"
                },
                "PolicyDocument": { ... }
            }
        }
    }
}
```

#### YAML
<a name="conditions-section-example-multi-condition.yaml"></a>

```
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  EnvType:
    Type: String
    AllowedValues:
      - prod
      - test
  BucketName:
    Default: ''
    Type: String
Conditions:
  IsProduction: !Equals
    - !Ref EnvType
    - prod
  CreateBucket: !Not
    - !Equals
      - !Ref BucketName
      - ''
  CreateBucketPolicy: !And
    - !Condition IsProduction
    - !Condition CreateBucket
Resources:
  Bucket:
    Type: AWS::S3::Bucket
    Condition: CreateBucket
    Properties:
      BucketName: !Ref BucketName
  Policy:
    Type: AWS::S3::BucketPolicy
    Condition: CreateBucketPolicy
    Properties:
      Bucket: !Ref Bucket
      PolicyDocument: ...
```

在此示例中，`CreateBucketPolicy` 条件演示了如何使用 `Condition` 密钥引用其他条件。只有当 `IsProduction` 和 `CreateBucket` 条件的评估结果都为 true 时，才会创建策略。

**注意**  
有关使用条件的更复杂的示例，请参阅《*Amazon CloudFormation模板参考指南*》中的[Condition 属性](https://docs.amazonaws.cn/AWSCloudFormation/latest/TemplateReference/aws-attribute-condition.html)主题。