公式ドキュメントの CloudFormation テンプレートが動かない場合の対処法

Resources セクションは必須の項目。cfn-lint で構文エラーを特定。

困っていた内容

以下の AWS 公式のドキュメントに記載のサンプルテンプレートをコピー&ペーストして、テンプレートを作成しました。
Amazon CloudWatch テンプレートスニペット - AWS CloudFormation

  • Billing-Alart.yaml
SpendingAlarm:
  Type: AWS::CloudWatch::Alarm
  Properties:
    AlarmDescription:
      'Fn::Join':
        - ''
        - - Alarm if AWS spending is over $
          - Ref: AlarmThreshold
    Namespace: AWS/Billing
    MetricName: EstimatedCharges
    Dimensions:
    - Name: Currency
      Value: USD
    Statistic: Maximum
    Period: '21600'
    EvaluationPeriods: '1'
    Threshold:
      Ref: "AlarmThreshold"
    ComparisonOperator: GreaterThanThreshold
    AlarmActions:
    - Ref: "BillingAlarmNotification"
    InsufficientDataActions:
    - Ref: "BillingAlarmNotification"

しかし、CloudFormation にてテンプレートからスタック作成しようとするとエラーになります。
どのようにすれば、エラーが解消されますでしょうか。

どう対応すればいいの?

CloudFormation では、定められた形式でテンプレートを作成する必要があります。

特に、テンプレートの Resources セクションは必須の項目です。
スタック作成時に、Resources セクションがないと、以下のようなエラーメッセージが表示されます。

  • エラーメッセージ
Template format error: At least one Resources member must be defined.

以下のテンプレートのように、Resources セクションを含むことで、スタック作成は可能です。

  • YAML の場合
Resources:
  SpendingAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmDescription:
        'Fn::Join':
          - ''
          - - Alarm if AWS spending is over $
            - Ref: AlarmThreshold
      Namespace: AWS/Billing
      MetricName: EstimatedCharges
      Dimensions:
      - Name: Currency
        Value: USD
      Statistic: Maximum
      Period: '21600'
      EvaluationPeriods: '1'
      Threshold:
        Ref: "AlarmThreshold"
      ComparisonOperator: GreaterThanThreshold
      AlarmActions:
      - Ref: "BillingAlarmNotification"
      InsufficientDataActions:
      - Ref: "BillingAlarmNotification"
  • JSON の場合
{
  "Resources": {
    "SpendingAlarm": {
      "Type": "AWS::CloudWatch::Alarm",
      "Properties": {
        "AlarmDescription": {
          "Fn::Join": ["", [
            "Alarm if AWS spending is over $",
            {
              "Ref": "AlarmThreshold"
            }
          ]]
        },
        "Namespace": "AWS/Billing",
        "MetricName": "EstimatedCharges",
        "Dimensions": [{
          "Name": "Currency",
          "Value": "USD"
        }],
        "Statistic": "Maximum",
        "Period": "21600",
        "EvaluationPeriods": "1",
        "Threshold": {
          "Ref": "AlarmThreshold"
        },
        "ComparisonOperator": "GreaterThanThreshold",
        "AlarmActions": [{
          "Ref": "BillingAlarmNotification"
        }],
        "InsufficientDataActions": [{
          "Ref": "BillingAlarmNotification"
        }]
      }
    }
  }
}

公式ドキュメントのスタック作成に失敗したら

公式ドキュメントを利用してサンプルテンプレートを活用し、スタック作成するとエラーになって失敗する場合があります。
そのようなときは、cfn-lint を使うと、テンプレートのどこが構文間違いしているかを、いち早く気づくことができます。

Linter を使って CloudFormation の間違いに爆速で気づく | DevelopersIO

以下の様に、cfn-lint の引数にテンプレートのファイル名を指定して実行すると、構文解析後、間違いを特定してくれます。
この例の場合は、「Resources セクションがないこと」、「Resources セクションがないことで SpendingAlarm が無効であること」、「AlarmThreshold と BillingAlarmNotification がリソースもしくはパラメータ内で定義されていないこと」が原因による構文エラーを確認することができました。

$ cfn-lint Billing-Alart.yaml
E1001 Top level template section SpendingAlarm is not valid
Billing-Alart.yaml:1:1

E1001 Missing top level template section Resources
Billing-Alart.yaml:1:1

E1012 Ref AlarmThreshold not found as a resource or parameter
Billing-Alart.yaml:8:13

E1012 Ref AlarmThreshold not found as a resource or parameter
Billing-Alart.yaml:17:5

E1012 Ref BillingAlarmNotification not found as a resource or parameter
Billing-Alart.yaml:21:7

E1012 Ref BillingAlarmNotification not found as a resource or parameter
Billing-Alart.yaml:23:7

テンプレートのデバックに困った際は、是非、利用してみてください。

参考資料

テンプレートの分析 - AWS CloudFormation

テンプレートには、いくつかの主要なセクションが含まれています。Resources セクションは、唯一の必須セクションです。テンプレートの一部のセクションの順序は任意です。

cfn-lint を使った AWS CloudFormation テンプレートの Git pre-commit バリデーション | Amazon Web Services ブログ