【AWS SAM】複数テンプレートで値をエクスポートして共有する「クロススタック参照」の書き方

対象読者: AWS SAMを利用したサーバーレスアプリケーションのデプロイを行ったことがある人

複数のSAMテンプレートで値を共有して利用しよう、という話です。

CloudFormationのクロススタック機能を使っているだけなので、書き方も一緒です。

例えばDynamoDBテーブル名、レイヤー名、S3バケット名などが複数テンプレートで共有したい値になるかと思います。

手順は以下の流れになります。

1. 共有したい値をリソースを作成する側のテンプレートでOutPutで記載する。

2. 共有される側のテンプレートでInportValueを用いて利用する。

※注意点: LayerのARNを共有しようとすると、レイヤーの更新が行えなくなるのでLayerを複数テンプレートで共有したい場合はレイヤー名のみ共有し、バージョンは手入力するなどの対応が必要になります。

それでは、手順について詳しく説明していきます。

【複数テンプレートで値を共有】前提条件

AとBのSAMテンプレートを用意すると仮定します。

A: DynamoDBテーブルをデプロイする

B: LambdaでDynamoDBテーブルにアクセスするのでIAMの権限が欲しい

1. 【複数テンプレートで値を共有】共有したい値をOutPutに記載してSAMデプロイを行う

まず、Aのテンプレート。template.yamlの記載方法を紹介します。

Mappingsにて、環境変数にテーブル名を設定している場合を考えます。

共有したい値はDynamoDBのテーブル名とします。

※簡易的に表示するため、DynamoDBのリソースを宣言する部分等、関係無い部分は省いています。

Parameters:
 Environment:
   Type: String
   AllowedValues:
     - dev

Mappings:
 EnvironmentMap:
   dev:
     TableName: UserMasterTable

OutPuts:
  MasterTable:
    Description: "User info stored table"
    Value: !FindInMap [EnvironmentMap, !Ref Environment, TableName]
    Export:
      Name: UserMasterTableName    

さて、ここまで出来たらあとは値を使いたい側のテンプレートでインポートを行うだけです。

同リージョン内のテンプレートであれば、他の設定は必要なくインポート可能です。

2. 【複数テンプレートで値を共有】共有したい値を !ImportValue で記載する

Bのインポートする側のテンプレートを記載します。

!ImportValueという関数を使うことで、同一アカウント同一リージョン内でExportされた他テンプレートの値を使うことが出来ます。

先ほどエクスポートで指定した"Name"の部分を入力してあげましょう。

!ImportValue UserMasterTableName

このように記載してあげれば、Aのテンプレートで指定したDynamoDBのテーブル名を取得することが可能です。

さて、IAMポリシーのリソース部分に記載するには以下のようになります。ついでに !Join 関数の書き方も見てしまいましょう。

  LambdaRole:
   Type: AWS::IAM::Role
   Properties:
     AssumeRolePolicyDocument:
       Version: "2012-10-17"
       Statement:
         - Effect: Allow
           Action: sts:AssumeRole
           Principal:
             Service:
               - lambda.amazonaws.com
     Policies:
       - PolicyName: DynamoTableAccess
         PolicyDocument:
           Version: 2012-10-17
           Statement:
             - Effect: Allow
               Action:
                 - dynamodb:GetItem
               Resource:
                 - !Join 
                   - ""
                   - - !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/"
                     - !ImportValue UserMasterTableName

最後の部分がImportしている部分ですね。

!Joinの書き方が少し面倒くさいので、確認してください。

特に、インデントがズレるとエラーになってしまうので、注意しましょう。私は何度もJoinのインデントでエラーを起こしました。

!Subを用いてリージョンやアカウントIDを取得することもできます。

これらを用いて、ARNの文字列を生成しているわけです。

まとめ

値をエクスポートすることで、多数のテンプレートで使っている値を全てのテンプレートで変更する必要がなくなります。

今回の場合だと、「DynamoDBのテーブル名を変更したい!」となったときに、一つのテンプレートだけ変えればいいので楽ですね。

今回はこの辺りで終わりにしたいと思います。

為になったら、スキしてください。

この記事が気に入ったらサポートをしてみませんか?