CloudFormation の 組み込み関数について整理しよう

# !Base64

`!Base64` は、入力文字列の Base64 表現を返します。
この関数は通常、UserData プロパティを介して Amazon EC2 インスタンスにエンコードされたデータを渡すために使用されます。

次の例では、CloudFormationでユーザーデータを記述する場合、Base64エンコードされてなければいけないため、Base64を利用している。

```yaml
Resources:
  SampleLaunchTemplate:
    Type: AWS::EC2::LaunchTemplate
    Properties:
      LaunchTemplateName: sample-launch-template
      LaunchTemplateData:
        UserData:
          Fn::Base64: |
            #!/bin/bash
```

# !Cidr

`!Cidr` は CIDR アドレスブロックの配列を返します。

次の例では、10.0.0.0/16 の16ネットマスクの CIDR ブロックを VPC に割り当てる。
その VPC のサブネットを2つ作ってそれぞれのサブネットは 10.0.x.0/24 の24ネットマスクの CIDR ブロックを割り当てる。

```yaml
Resources:
  ExampleVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16

  ExampleSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: !Select [0, !Cidr [!GetAtt ExampleVPC.CidrBlock, 2, 8]]
      VpcId: !Ref ExampleVPC

  ExampleSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      CidrBlock: !Select [1, !Cidr [!GetAtt ExampleVPC.CidrBlock, 2, 8]]
      VpcId: !Ref ExampleVPC
```

# !FindInMap

`!FindInMap` は、`Mappings セクション`で宣言したキーに対応する値を返します。

次の例では、
us-east-1 にデプロイした場合は、"ami-0ff8a91507f77f867"
ap-northeast-1 にデプロイした場合は、"ami-06cd52961ce9f0d85"
が、EC2インスタンスの、ImageId として利用されます。

```yaml
Mappings: 
  RegionMap: 
    us-east-1: 
      HVM64: "ami-0ff8a91507f77f867"
      HVMG2: "ami-0a584ac55a7631c0c"
    ap-northeast-1: 
      HVM64: "ami-06cd52961ce9f0d85"
      HVMG2: "ami-053cdd503598e4a9d"

Resources: 
  myEC2Instance: 
    Type: "AWS::EC2::Instance"
    Properties: 
      ImageId: !FindInMap
        - RegionMap
        - !Ref 'AWS::Region'
        - HVM64
```

# !GetAtt

`!GetAtt` は、テンプレートのリソースから属性の値を返します。

次の例では、
論理名 myELB の ELB の DNS 名を返します。

```yaml
!GetAtt myELB.DNSName
```

# !GetAZs

`!GetAZs` は、指定したリージョンの AZ をアルファベット順にリストした配列を返します。

次の例では、AZ の 0, つまり、`ap-northeast-1a` が返されます。

```yaml
Resources: 
    mySubnet: 
      Type: "AWS::EC2::Subnet"
      Properties: 
        VpcId: 
          !Ref VPC
        CidrBlock: 10.0.0.0/24
        AvailabilityZone: 
          !Select: 
            - 0
            - !GetAZs: ""
```

# !ImportValue

`!ImportValue` は、別のスタックによってエクスポートされた出力の値を返します。

次の例では、
"template1" の Outputs セクションで、SubnetId をエクスポートし、
"template2" で、"template1" の SubnetId をインポートし指定しています。


```yaml:template1
Outputs:
    SubnetId:
    Value: !Ref SubnetId
    Export:
        Name: SubnetId
```

```yaml:template2
Resources: 
    EC2instance:
        Type: AWS::EC2::Instance
        Properties:
            SubnetId: !ImportValue SubnetId
```

# !Join

`!Join` は、一連の値を特定の区切り文字で区切って 1 つの値に追加します。
区切り文字が空の文字列の場合、一連の値は区切り文字を使用することなく連結されます。

次の例では、
`""` のように区切り文字が空ですので、
arn:aws:s3:::<BucketName>/*
のように返されます。

```yaml
Resource:
  - Fn::Join:
      - ""
      - - "arn:aws:s3:::"
        - !Ref BucketName
        - "/*"
```

# !Select

`!Select` は、インデックスによってオブジェクトのリストから 1 つのオブジェクトを返します。

次の例では、AZ のリストの中で、0番目の項目、つまり ap-northeast-1 が指定されます。

```yaml
Resources: 
    publicSubnet:
        Type: AWS::EC2::Subnet
        Properties:
            AvailabilityZone: !Select [ 0, !GetAZs  '' ]
```

# !Split

`Split` は文字列を文字列値のリストに分割し、結果の文字列のリストから要素を選択できるようにします。

次の例では、リージョン名を - を基準に分けてoutputの値として設定しています。

```yaml
Resources:
    MyVPC:
        Type: AWS::EC2::VPC
        Properties:
            CidrBlock: 10.0.0.0/16
			
Outputs:
    RegionPart:
        Value: !Select [1, !Split ["-", !Ref  "AWS::Region"]]
```

# !Sub

`!Sub` は特定した値の入力文字列にある変数の代わりになります。

次の例では、EC2インスタンスの Nameタグに、SystemName-dev という値が代入されます。

```yaml
Parameters:
    Env:
        Default: "dev"
        Type: String
    SystemName:
        Default: "SystemName"
        Type: String

Resources:
  EC2instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-00000000
      InstanceType: "t2.micro"
    Tags:
        - Key: Name
          Value: !Sub ${SystemName}-${Env}
```

# !Transform

`!Transform` は、スタックテンプレートの一部に対してカスタム処理を実行するためのマクロを指定します。

次の例では、`AWS::Include` 変換を呼び出し、テンプレートスニペットを取得する場所を `InputValue` パラメータに渡すように指定します。

```yaml
'Fn::Transform':
    Name: 'AWS::Include'
    Parameters: {Location: {Ref: InputValue}}
```

# Ref

`Ref` は、指定したパラメータまたはリソースの値を返します。

次の例では、EIP は、Ref で MyEC2Instance リソースのインスタンス ID を指定しています。

```yaml
Resources:
    MyEC2Instance:
        Type: AWS::EC2::Instance

    MyEIP:
      Type: AWS::EC2::EIP
      Properties:
        InstanceId: !Ref MyEC2Instance
```