LoginSignup
2

More than 5 years have passed since last update.

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

Posted at

背景

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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2