話題の記事

【アップデート】AWS CloudFormationでYAML形式をサポートしました

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ウィスキー、シガー、パイプをこよなく愛する大栗です。

全国1億3000万人のCloudFormation職人の皆様!先程CloudFormation始まって以来の大きなアップデートが来ました。そうです、YAMLでCloudFormationテンプレートが書けるようになりました。よくJSONは『人間が書くものじゃない』と言われますが、人間が書けるYAMLで記述できるようになりました!

AWS CloudFormation Introduces YAML Template Support and Cross Stack References

AWS CloudFormation Update – YAML, Cross-Stack References, Simplified Substitution | AWS Blog

JSON形式の内容

先日のブログ(CloudFormationで再起動が必要なソフトウェアをインストールする)の内容を元にYAML形式に書き換えてみます。

元の内容は以下の様になっています。なお、KeyPairNameは環境に合わせて書き換えてください。

template.json

{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "Linux Stack",
  "Resources" : {
    "Server01": {
      "Type": "AWS::EC2::Instance",
      "CreationPolicy" : {
        "ResourceSignal": {
          "Timeout": "PT30M"
        }
      },
      "Properties": {
        "ImageId": "ami-0f19db6e",
        "InstanceType": "c4.large",
        "KeyName": "KeyPairName",
        "UserData": { "Fn::Base64": { "Fn::Join": [ "", [
          "<script>", "\n",
          "cfn-init.exe -v -c install -s ", { "Ref": "AWS::StackId" }, " -r Server01 -c sample --region ", { "Ref": "AWS::Region" }, "\n",
          "", "\n",
          "</script>"
        ]]}}
      },
      "Metadata" : {
        "AWS::CloudFormation::Init" : {
          "configSets" : {
            "sample" : [
              "KB3134758",
              "vscode",
              "finalize"
            ]
          },
          "KB3134758" : {
            "files" : {
              "c:\\cm\\Win8.1AndW2K12R2-KB3134758-x64.msu" : {
                "source" : "https://download.microsoft.com/download/2/C/6/2C6E1B4A-EBE5-48A6-B225-2D2058A9CEFB/Win8.1AndW2K12R2-KB3134758-x64.msu"
              }
            },
            "commands" : {
              "wait" : {
                "command" : "wusa.exe c:\\cm\\Win8.1AndW2K12R2-KB3134758-x64.msu /quiet /forcerestart",
                "cwd" : "C:\\cm"
                "waitAfterCompletion": "forever"
              }
            }
          },
          "vscode" : {
            "commands" : {
              "a-set-execution-policy": {
                "command": "powershell.exe -command Set-ExecutionPolicy RemoteSigned -Force"
              },
              "b-find-package-provider": {
                "command": "powershell.exe -command Find-PackageProvider -ForceBootstrap"
              },
              "c-find-package": {
                "command": "powershell.exe -command Find-Package -ForceBootstrap -Name VisualStudioCode -Provider chocolatey"
              },
              "d-install-package": {
                "command": "powershell.exe -command Install-Package -Name VisualStudioCode -Force"
              }
            }
          },
          "finalize" : {
            "commands" : {
              "a-write-status" : {
                "command" : { "Fn::Join": [ "", [
                  "cfn-signal",
                  " --exit-code 0",
                  " --region \"", { "Ref": "AWS::Region" }, "\"",
                  " --resource Server01",
                  " --stack \"", { "Ref": "AWS::StackName"}, "\""
                ]]}
              }
            }
          }
        }
      }
    }
  }
}

単純にYAML化する

JSONをYAMLにすると言うことでCloudFormationテンプレートをYAMLで書いてみる【remarshal】を参考にremarshalでYAML化してみます。

$ cat ./01.json | json2yaml > ./02.yaml

YAMLへ変換すると以下のようになります。

02.yaml

AWSTemplateFormatVersion: 2010-09-09
Description: Linux Stack
Resources:
  Server01:
    CreationPolicy:
      ResourceSignal:
        Timeout: PT30M
    Metadata:
      AWS::CloudFormation::Init:
        KB3134758:
          commands:
            wait:
              command: wusa.exe c:\cm\Win8.1AndW2K12R2-KB3134758-x64.msu /quiet /forcerestart
              cwd: C:\cm
              waitAfterCompletion: forever
          files:
            c:\cm\Win8.1AndW2K12R2-KB3134758-x64.msu:
              source: https://download.microsoft.com/download/2/C/6/2C6E1B4A-EBE5-48A6-B225-2D2058A9CEFB/Win8.1AndW2K12R2-KB3134758-x64.msu
        configSets:
          sample:
          - KB3134758
          - vscode
          - finalize
        finalize:
          commands:
            a-write-status:
              command:
                Fn::Join:
                - ""
                - - cfn-signal
                  - ' --exit-code 0'
                  - ' --region "'
                  - Ref: AWS::Region
                  - '"'
                  - ' --resource Server01'
                  - ' --stack "'
                  - Ref: AWS::StackName
                  - '"'
        vscode:
          commands:
            a-set-execution-policy:
              command: powershell.exe -command Set-ExecutionPolicy RemoteSigned -Force
            b-find-package-provider:
              command: powershell.exe -command Find-PackageProvider -ForceBootstrap
            c-find-package:
              command: powershell.exe -command Find-Package -ForceBootstrap -Name
                VisualStudioCode -Provider chocolatey
            d-install-package:
              command: powershell.exe -command Install-Package -Name VisualStudioCode
                -Force
    Properties:
      ImageId: ami-0f19db6e
      InstanceType: c4.large
      KeyName: KeyPairName
      UserData:
        Fn::Base64:
          Fn::Join:
          - ""
          - - <script>
            - |2+
            - 'cfn-init.exe -v -c install -s '
            - Ref: AWS::StackId
            - ' -r Server01 -c sample --region '
            - Ref: AWS::Region
            - |2+
            - ""
            - |2+
            - </script>
    Type: AWS::EC2::Instance

このように普通にCloudFormation Stackを起動できます。

CloudFormation_Management_Console

起動したEC2インスタンスもVisual Studio Codeがインストールされます。

b

YAMLを整形する

remarshal(json2yaml)を使用すると簡単にYAML化できますが、a-write-statusの内容やUserDataが分かりにくくなっています。ここの内容を書き換えます。 YAML形式のサポートと共に文字列置換が簡単になっていますのでFn::Sub関数で書き換えてみます。YAML形式では"Fn::Sub": Stringという表記を!Sub Stringという形式でも記述できます。

!Sub Stringで書き換える

元は以下の内容となっています。

UserData:
  Fn::Base64:
    Fn::Join:
    - ""
    - - <script>
      - |2+
      - 'cfn-init.exe -v -c install -s '
      - Ref: AWS::StackId
      - ' -r Server01 -c sample --region '
      - Ref: AWS::Region
      - |2+
      - ""
      - |2+
      - </script>

!Sub Stringを使って書き換えると、以下のようにスッキリします。

UserData:
  Fn::Base64: !Sub |
    <script>
    cfn-init.exe -v -c install -s ${AWS::StackId} -r Server01 -c sample --region ${AWS::Region}

    </script>

a-write-statusも同様に書き換えましょう。元の内容は以下になります。

a-write-status:
  command:
    Fn::Join:
    - ""
    - - cfn-signal
      - ' --exit-code 0'
      - ' --region "'
      - Ref: AWS::Region
      - '"'
      - ' --resource Server01'
      - ' --stack "'
      - Ref: AWS::StackName
      - '"'

!Sub Stringを使って書き換えると、1行で既述できます。

a-write-status:
  command: !Sub |
      cfn-signal --exit-code 0 --region "${AWS::Region}" --resource Server01 --stack "${AWS::StackName}"

YAML形式の最終型

remarshal(json2yaml)を使用すると項目の順番がソートされてしまうので、JSON形式と同様の順番に入れ替えると最終的に以下のようになります。

AWSTemplateFormatVersion: 2010-09-09
Description: Linux Stack
Resources:
  Server01:
    Type: AWS::EC2::Instance
    CreationPolicy:
      ResourceSignal:
        Timeout: PT30M
    Properties:
      ImageId: ami-0f19db6e
      InstanceType: c4.large
      KeyName: KeyPairName
      UserData:
        Fn::Base64: !Sub |
          <script>
          cfn-init.exe -v -c install -s ${AWS::StackId} -r Server01 -c sample --region ${AWS::Region}

          </script>
    Metadata:
      AWS::CloudFormation::Init:
        configSets:
          sample:
          - KB3134758
          - vscode
          - finalize
        KB3134758:
          files:
            c:\cm\Win8.1AndW2K12R2-KB3134758-x64.msu:
              source: https://download.microsoft.com/download/2/C/6/2C6E1B4A-EBE5-48A6-B225-2D2058A9CEFB/Win8.1AndW2K12R2-KB3134758-x64.msu
          commands:
            wait:
              command: wusa.exe c:\cm\Win8.1AndW2K12R2-KB3134758-x64.msu /quiet /forcerestart
              cwd: C:\cm
              waitAfterCompletion: forever
        vscode:
          commands:
            a-set-execution-policy:
              command: powershell.exe -command Set-ExecutionPolicy RemoteSigned -Force
            b-find-package-provider:
              command: powershell.exe -command Find-PackageProvider -ForceBootstrap
            c-find-package:
              command: powershell.exe -command Find-Package -ForceBootstrap -Name VisualStudioCode -Provider chocolatey
            d-install-package:
              command: powershell.exe -command Install-Package -Name VisualStudioCode -Force

        finalize:
          commands:
            a-write-status:
              command: !Sub |
                  cfn-signal --exit-code 0 --region "${AWS::Region}" --resource Server01 --stack "${AWS::StackName}"

さいごに

全てのCloudFormation職人が待ち望んでいたYAML対応がされました。またCloudFormationで一番面倒なのがUserDataMetadataでのコマンドやスクリプトの記述でした。JSONの場合は元のスクリプトをエスケープして記述する必要があり、変数の埋め込みも大変でした。Fn::Sub!Sub Stringを使用するとコマンドやスクリプトが簡単に記述できるので、テンプレートの作成が捗りますね!