AWS SAMにおけるタグの指定方法

February 17, 2021

AWS SAMで小さいサービスを作る機会があったので、地味に戸惑ったことを書き残しておく。

前置き

今更ですが一応、AWS SAMとはAWS Serverless Application Modelの略で、AWSでサーバーレスアプリケーションを開発するためのフレームワークである。というといまいち何だか分からないが、少しAWSを分かっている人に極力平たくその一側面を説明すると、CloudFormationの拡張ということになる。
CloudFormationと同じノリで、例えば AWS::Serverless::Function というリソースタイプを定義すると、LambdaFunctionおよびそれをトリガーするイベントソースとのマッピング、必要なIAMロールなどをまとめて作成してくれる。
ベースはCloudFormationなので、CloudFormationのテンプレートと同じ構文でその他のリソースも定義できる。

本題

例えばCloudFormationで AWS::Lambda::Function リソースにタグを指定したい場合は以下のように書く。

  BenriFunction:
    Type: AWS::Lambda::Function
    Properties:
      ....
      Tags:
        - Key: "service"
          Value: "benri-service"
        - Key: "environment"
          Value: "production"

であれば AWS::Serverless::Function でタグを指定したい場合、以下のようにしたくなるのが人情である。

  BenriFunction:
    Type: AWS::Serverless::Function
    Properties:
      ....
      Tags:
        - Key: "service"
          Value: "benri-service"
        - Key: "environment"
          Value: "production"

しかしこれは間違いで、デプロイ時にエラーとなってしまう。
ここではじめてドキュメントを見ると、SAMのほうは Tags のTypeはMapであると書いてある。
AWS::Serverless::Function - AWS Serverless Application Model

対してCloudFormationのほうは Tags のTypeはListである。
AWS::Lambda::Function - AWS CloudFormation

というわけで、AWS::Serverless::Function のほうは以下のように書く必要がある。

  BenriFunction:
    Type: AWS::Serverless::Function
    Properties:
      ....
      Tags:
        service: "benri-service"
        environment: "production"

これは AWS::Serverless 配下のリソースで共通の仕様のようだった。

先述の通りSAMはCloudFormationの拡張なので、同じテンプレートにまとめて従来のCloudFormationのリソース定義も書くことができる。すると複数のタグの指定方法が混在することになる。どうしてこんな仕様にしたんだろう。
並のヤムラーは息を吸うようにコピペする習性がある(偏見)ため、私と同じような間違いをおかす方が多いのではないでしょうか。お気をつけください。そしてちゃんとドキュメントは読みましょう(お前が)。

以上です。

@j_untanaka on Twitter

AWSAWS SAM