背景
serverlessを使い始めてますが、API Gatewayとの連携は簡単に書けます…が、DynamoDB Streamをトリガーにしたい場合はどのように書けばよいか…悩んだ末に、やっと解決しました。
問題
何が問題かといいますと…
- DynamoDB StreamのARNは最後に日付のタイムスタンプがついている
- マッピング定義は日付のタイムスタンプが付いたARNをフルで指定しなければならない
です。ネットで調べてみての解決策は、
- enentsではFn::GetAttが使えない
- 後でAWS Consoleで修正する
- sererless.ymlに後でDynamoDB StreamのARNの追加してdeployする
でした。しかし、何度もdeployしたりステージを変更した場合は、「デグレードするな…」と考えました。
解決策
結局は、functionにてevent定義することを止めました…
リソース定義の中で、AWS::Lambda::EventSourceMappingリソースを以下の様に書きます。
※serverlssのバージョンは1.6.0です。
StreamEventMapping:
Type: AWS::Lambda::EventSourceMapping
Properties:
BatchSize: 20
EventSourceArn:
Fn::GetAtt: [TableResourceName, StreamArn]
FunctionName:
Fn::GetAtt: [SensorDashagreeLambdaFunction, Arn]
StartingPosition: TRIM_HORIZON
Enabled: false
とこんな感じになります。ポイントとしては、
- DynamoDB StreamのARNは、Fn::GetAtt: [リソース名(テーブル名では無い), StreamArn]でARNを得る
- FunctionNameはserverlessが生成した該当のfunctionのリソース名を入れる
FunctionNameはトリッキーなことをしてますが、serverlessを一回流して、「.serverless」ディレクトリにかかれているCloudFormationのテンプレートを見て入れてます。命名規則があるみたいで、何度流しても名前が固定でしたので、良しとしています。
しかし、標準のロールには入れれるかどうか分かりません。別途ロールリソースを以下の様に作って、該当Functionにロールを割り当ててます。
RoleResource:
Type: AWS::IAM::Policy
Properties:
-
Effect: Allow
Action:
- dynamodb:DescribeStream
- dynamodb:ListStream
- dynamodb:GetRecords
- dynamodb:GetShardIterator
Resource:
- Fn::GetAtt: [TableResourceName, StreamArn]
serverlessが出力されるテンプレートとAWSのCloudFormationのマニュアルを見ながら何とかここまでできました…
DynamoDB Streamとlambdaの連携は、まだ始まったばかりでserverlessが追いついて無いのかな?の印象です。