

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

`Resources` 部分是 CloudFormation 模板中必需具备的一个顶级部分，用于声明您希望 CloudFormation 在堆栈中预置和配置的 AWS 资源。

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

`Resources` 部分使用以下语法：

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

```
"Resources" : {
    "LogicalResourceName1" : {
        "Type" : "AWS::ServiceName::ResourceType",
        "Properties" : {
            "PropertyName1" : "PropertyValue1",
            ...
        }
    },

    "LogicalResourceName2" : {
        "Type" : "AWS::ServiceName::ResourceType",
        "Properties" : {
            "PropertyName1" : "PropertyValue1",
            ...
        }
    }
}
```

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

```
Resources:
  LogicalResourceName1:
    Type: AWS::ServiceName::ResourceType
    Properties:
      PropertyName1: PropertyValue1
      ...

  LogicalResourceName2:
    Type: AWS::ServiceName::ResourceType
    Properties:
      PropertyName1: PropertyValue1
      ...
```

## 逻辑 ID（也称为*逻辑名称*）
<a name="resources-section-logical-id"></a>

在 CloudFormation 模板中，资源由其逻辑资源名称来标识。这些名称必须为字母数字字符（A-Za-z0-9），并且在模板中必须唯一。逻辑名称用于引用模板其他部分中的资源。

## 资源类型
<a name="resources-section-resource-type"></a>

每个资源必须有一个 `Type` 属性，用于定义 AWS 资源的类型。`Type` 属性的格式为 `AWS::ServiceName::ResourceType`。例如，Amazon S3 存储桶的 `Type` 属性为 `AWS::S3::Bucket`。

有关支持的资源类型的完整列表，请参阅 [AWS 资源和属性类型参考](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-template-resource-type-ref.html)。

## 资源属性
<a name="resources-section-resource-properties"></a>

资源属性是可以指定的附加选项，用于定义特定资源类型的详细配置。某些属性是必需的，而另一些属性则是可选的。有些属性具有默认值，因此指定这些属性是可选的。

有关每种资源类型支持的属性的详细信息，请参阅 [AWS 资源和属性类型参考](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-template-resource-type-ref.html)中的主题。

属性值可以是文本字符串、字符串列表、布尔值、动态引用、参数引用、伪引用或者函数返回的值。以下示例演示了如何声明不同的属性值类型：

### JSON
<a name="resource-properties-example.json"></a>

```
"Properties" : {
    "String" : "A string value",
    "Number" : 123,
    "LiteralList" : [ "first-value", "second-value" ],
    "Boolean" : true
}
```

### YAML
<a name="resource-properties-example.yaml"></a>

```
Properties:
  String: A string value 
  Number: 123
  LiteralList:
    - first-value
    - second-value
  Boolean: true
```

## 物理 ID
<a name="resources-section-physical-id"></a>

除了逻辑 ID 外，某些资源还有物理 ID，这是资源的实际分配名称，如 EC2 实例 ID 或 S3 存储桶名称。使用物理 ID 来标识 CloudFormation 模板外部的资源，但只能在创建了资源之后进行。例如，假设您为一个 EC2 实例资源指定 `MyEC2Instance` 的逻辑 ID。当 CloudFormation 创建实例时，CloudFormation 会自动生成物理 ID（如 `i-1234567890abcdef0`）并将其分配给该实例。您可以使用该物理 ID 来标识实例，可以使用 Amazon EC2 控制台查看其属性 (如 DNS 名称)。

对于 Amazon S3 存储桶和许多其他资源，如果您没有明确指定实体名称，CloudFormation 会自动为该资源生成唯一的实体名称。该实体名称基于 CloudFormation 堆栈的名称、在 CloudFormation 模板中指定的资源逻辑名称和唯一 ID 的组合。例如，假设您在名为 `MyStack` 的堆栈中有一个逻辑名称为 `MyBucket` 的 Amazon S3 存储桶，CloudFormation 可能会使用如下物理名称 `MyStack-MyBucket-abcdefghijk1` 来命名该存储桶。

对于支持自定义名称的资源，您可以分配自己的物理名称来帮助快速标识资源。例如，您可以将存储日志的 S3 存储桶命名为 `MyPerformanceLogs`。有关更多信息，请参阅[名称类型](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-name.html)。

## 引用资源
<a name="using-cross-resource-references"></a>

您经常会需要根据一个资源的名称或属性来设置另一个资源的属性。例如，您可以创建一个使用 EC2 安全组的 EC2 实例，或由 S3 存储桶支持的 CloudFront 分配。所有这些资源都可在同一 CloudFormation 模板中创建。

CloudFormation 提供了内置函数，您可以使用这些函数来引用其他资源及其属性。这些函数让您可以在资源之间创建依赖关系，并将一个资源的值传递到另一个资源。

### `Ref` 函数
<a name="resource-properties-ref"></a>

`Ref` 函数通常用于检索在同一 CloudFormation 模板中定义的资源的标识属性。具体返回的值取决于资源的类型。对于大多数资源，该函数会返回资源的实体名称。不过对于某些资源类型，该函数可能会返回其他的值，例如 `AWS::EC2::EIP` 资源的 IP 地址或 Amazon SNS 主题的 Amazon 资源名称（ARN）。

以下示例演示了如何在属性中使用 `Ref` 函数。在以下的每个示例中，`Ref` 函数都将返回模板中其他部分声明的 `LogicalResourceName` 资源的实际名称。YAML 示例中的 `!Ref` 语法示例只是编写 `Ref` 函数的较简单方法。

#### JSON
<a name="resource-properties-ref-example.json"></a>

```
"Properties" : {
    "PropertyName" : { "Ref" : "LogicalResourceName" }
}
```

#### YAML
<a name="resource-properties-ref-example.yaml"></a>

```
Properties:
  PropertyName1:
    Ref: LogicalResourceName
  PropertyName2: !Ref LogicalResourceName
```

有关使用 `Ref` 函数的更多详细信息，请参阅 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-ref.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-ref.html)。

### `Fn::GetAtt` 函数
<a name="resource-properties-getatt"></a>

如果参数或为资源返回的值正是您需要的，则 `Ref` 函数会非常实用。不过，您可能需要资源的其他属性。例如，如果您想创建一个具有 S3 起始地址的 CloudFront 分配，就需要使用 DNS 样式的地址来指定存储桶的位置。很多资源都具有附加属性，您可以在模板中使用这些属性的值。要获取这些属性，请使用 `Fn::GetAtt` 函数。

以下示例演示了如何在属性中使用 `GetAtt` 函数。`Fn::GetAtt` 函数有两个参数，分别是资源的逻辑名称和要检索的属性名称。YAML 示例中的 `!GetAtt` 语法示例只是编写 `GetAtt` 函数的较简单方法。

#### JSON
<a name="resource-properties-getatt-example.json"></a>

```
"Properties" : {
    "PropertyName" : {
        "Fn::GetAtt" : [ "LogicalResourceName", "AttributeName" ]
    }
}
```

#### YAML
<a name="resource-properties-getatt-example.yaml"></a>

```
Properties:
  PropertyName1:
    Fn::GetAtt:
      - LogicalResourceName
      - AttributeName
  PropertyName2: !GetAtt LogicalResourceName.AttributeName
```

有关使用 `GetAtt` 函数的更多详细信息，请参阅 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-getatt.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/intrinsic-function-reference-getatt.html)。

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

以下示例演示了如何声明资源以及 CloudFormation 模板会如何引用在同一模板中定义的其他资源以及现有的 AWS 资源。

**Topics**
+ [使用自定义名称声明单个资源](#resources-section-structure-examples-single-resource)
+ [使用 `Ref` 函数引用其他资源](#resources-section-structure-examples-ref)
+ [使用 `Fn::GetAtt` 函数引用资源属性](#resources-section-structure-examples-getatt)

### 使用自定义名称声明单个资源
<a name="resources-section-structure-examples-single-resource"></a>

以下示例声明了 `AWS::S3::Bucket` 类型的单个资源，逻辑名称为 `MyBucket`。`BucketName` 属性设置为 *amzn-s3-demo-bucket*，因此应替换为您的 S3 存储桶所需的名称。

如果您使用此资源声明创建堆栈，CloudFormation 将使用默认设置创建 Amazon S3 存储桶。对于 Amazon EC2 实例或自动扩缩组等其他资源，CloudFormation 需要更多信息。

#### JSON
<a name="resources-section-structure-examples-single-resource.json"></a>

```
{
    "Resources": {
        "MyBucket": {
            "Type": "AWS::S3::Bucket",
            "Properties": {
                "BucketName": "amzn-s3-demo-bucket"
            }
        }
    }
}
```

#### YAML
<a name="resources-section-structure-examples-single-resource.yaml"></a>

```
Resources:
  MyBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: amzn-s3-demo-bucket
```

### 使用 `Ref` 函数引用其他资源
<a name="resources-section-structure-examples-ref"></a>

以下示例演示的资源声明定义了一个 EC2 实例和安全组。`Ec2Instance` 资源使用 `Ref` 函数引用 `InstanceSecurityGroup` 资源，以作为其 `SecurityGroupIds` 属性的一部分。此外还包括未在模板中声明的一个现有安全组 (`sg-12a4c434`)。您可以使用文字字符串来指代现有 AWS 资源。

#### JSON
<a name="resources-section-structure-examples-ref.json"></a>

```
{
    "Resources": {
        "Ec2Instance": {
            "Type": "AWS::EC2::Instance",
            "Properties": {
                "SecurityGroupIds": [
                    {
                        "Ref": "InstanceSecurityGroup"
                    },
                    "sg-12a4c434"
                ],
                "KeyName": "MyKey",
                "ImageId": "ami-1234567890abcdef0"
            }
        },
        "InstanceSecurityGroup": {
            "Type": "AWS::EC2::SecurityGroup",
            "Properties": {
                "GroupDescription": "Enable SSH access via port 22",
                "SecurityGroupIngress": [
                    {
                        "IpProtocol": "tcp",
                        "FromPort": 22,
                        "ToPort": 22,
                        "CidrIp": "0.0.0.0/0"
                    }
                ]
            }
        }
    }
}
```

#### YAML
<a name="resources-section-structure-examples-ref.yaml"></a>

```
Resources:
  Ec2Instance:
    Type: AWS::EC2::Instance
    Properties:
      SecurityGroupIds:
        - !Ref InstanceSecurityGroup
        - sg-12a4c434
      KeyName: MyKey
      ImageId: ami-1234567890abcdef0
  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Enable SSH access via port 22
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
```

### 使用 `Fn::GetAtt` 函数引用资源属性
<a name="resources-section-structure-examples-getatt"></a>

以下示例演示的资源声明定义了一个 CloudFront 分配资源和一个 S3 存储桶。`MyDistribution` 资源指定了 `MyBucket` 资源的 DNS 名称，后者使用 `Fn::GetAtt` 函数来获取存储桶的 `DomainName` 属性。`Fn::GetAtt` 函数会在一个数组中列出这两个参数。对于采用多个参数的函数，可以使用数组来指定其参数。

#### JSON
<a name="resources-section-structure-examples-getatt.json"></a>

```
{
  "Resources": {
    "MyBucket": {
      "Type": "AWS::S3::Bucket"
    },
    "MyDistribution": {
      "Type": "AWS::CloudFront::Distribution",
      "Properties": {
        "DistributionConfig": {
          "Origins": [
            {
              "DomainName": {
                "Fn::GetAtt": [
                  "MyBucket",
                  "DomainName"
                ]
              },
              "Id": "MyS3Origin",
              "S3OriginConfig": {}
            }
          ],
          "Enabled": "true",
          "DefaultCacheBehavior": {
            "TargetOriginId": "MyS3Origin",
            "ForwardedValues": {
              "QueryString": "false"
            },
            "ViewerProtocolPolicy": "allow-all"
          }
        }
      }
    }
  }
}
```

#### YAML
<a name="resources-section-structure-examples-getatt.yaml"></a>

```
Resources:
  MyBucket:
    Type: AWS::S3::Bucket
  MyDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Origins:
          - DomainName: !GetAtt 
              - MyBucket
              - DomainName
            Id: MyS3Origin
            S3OriginConfig: {}
        Enabled: 'true'
        DefaultCacheBehavior:
          TargetOriginId: MyS3Origin
          ForwardedValues:
            QueryString: 'false'
          ViewerProtocolPolicy: allow-all
```