AWS
lambda
ServerlessFramework
serverlss

serverless frameworkでDynamoDBとLambdaのイベントを関連付ける

More than 1 year has passed since last update.


背景

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です。


serverless.yml

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にロールを割り当ててます。


serverless.yml

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が追いついて無いのかな?の印象です。