2
3

More than 3 years have passed since last update.

DynamoDBストリームをトリガーにLambdaを実行しSNS通知する

Last updated at Posted at 2019-12-24

1.ストリームを有効にしたdynamoDBテーブルを作成する

テーブル名:dynamodbtesttable
パーティションキー:Username
ソートキー:Timestamp
ストリーム:有効、トリームに書き込まれる情報を項目の新しいイメージと古いイメージの両方(NEW_AND_OLD_IMAGES)にしました。

StreamViewType
StreamViewType テーブル内のデータが変更されるたびにストリームに書き込まれる情報を指定します。
KEYS_ONLY 変更された項目のキー属性のみ。
NEW_IMAGE 変更後に表示される項目全体。
OLD_IMAGE 変更前に表示されていた項目全体。
NEW_AND_OLD_IMAGES 項目の新しいイメージと古いイメージの両方。
aws dynamodb create-table \
    --table-name dynamodbtesttable \
    --attribute-definitions AttributeName=Username,AttributeType=S AttributeName=Timestamp,AttributeType=S \
    --key-schema AttributeName=Username,KeyType=HASH  AttributeName=Timestamp,KeyType=RANGE \
    --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
    --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES

出力された LatestStreamArn をメモしておく。

"LatestStreamArn": "arn:aws:dynamodb:ap-northeast-1:012345678912:table/dynamodbtesttable/stream/2019-12-23T05:35:44.887"

2.Lambda 実行ロールの作成

LambdatestRoleを作成します。

信頼関係

trust-relationship.json
{
   "Version": "2012-10-17",
   "Statement": [
     {
       "Effect": "Allow",
       "Principal": {
         "Service": "lambda.amazonaws.com"
       },
       "Action": "sts:AssumeRole"
     }
   ]
 }

ロール

aws iam create-role --role-name LambdatestRole \
    --path "/service-role/" \
    --assume-role-policy-document file://trust-relationship.json

ポリシー

role-policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "lambda:InvokeFunction",
            "Resource": "arn:aws:lambda:ap-northeast-1:123456789012:function:publishNewtest*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:ap-northeast-1:123456789012:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:DescribeStream",
                "dynamodb:GetRecords",
                "dynamodb:GetShardIterator",
                "dynamodb:ListStreams"
            ],
            "Resource": "arn:aws:dynamodb:ap-northeast-1:123456789012:table/dynamodbtesttable/stream/*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "sns:Publish"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

ロールにポリシーをアタッチ

aws iam put-role-policy --role-name LambdatestRole \
    --policy-name LambdatestRolePolicy \
    --policy-document file://role-policy.json

3.SNSトピックを作成する

トピック

aws sns create-topic --name snstestTopic

サブスクリプション

aws sns subscribe \
    --topic-arn arn:aws:sns:ap-northeast-1:123456789012:snstestTopic \
    --protocol email \
    --notification-endpoint example@example.com

E メールアドレスに届いた確認メッセージの [サブスクリプションを確認] リンクを選択して、サブスクリプションプロセスを完了します。

4.Lambda 関数の作成

コード

publishNewBark.js
'use strict';
var AWS = require("aws-sdk");
var sns = new AWS.SNS();

exports.handler = (event, context, callback) => {

    event.Records.forEach((record) => {
        console.log('Stream record: ', JSON.stringify(record, null, 2));

        if (record.eventName == 'INSERT') {
            var who = JSON.stringify(record.dynamodb.NewImage.Username.S);
            var when = JSON.stringify(record.dynamodb.NewImage.Timestamp.S);
            var what = JSON.stringify(record.dynamodb.NewImage.Message.S);
            var params = {
                Subject: 'A new bark from ' + who, 
                Message: 'test user ' + who + ' barked the following at ' + when + ':\n\n ' + what,
                TopicArn: 'arn:aws:sns:ap-northeast-1:accountID:snstestTopic'
            };
            sns.publish(params, function(err, data) {
                if (err) {
                    console.error("Unable to send message. Error JSON:", JSON.stringify(err, null, 2));
                } else {
                    console.log("Results from sending message: ", JSON.stringify(data, null, 2));
                }
            });
        }
    });
    callback(null, `Successfully processed ${event.Records.length} records.`);

zip

zip publishNewBark.zip publishNewBark.js

ロールARNを確認。
```
aws iam get-role --role-name LambdatestRole

"Arn": "arn:aws:iam::123456789012:role/service-role/LambdatestRole "
```

Lambda関数の作成

aws lambda create-function \
    --region ap-northeast-1 \
    --function-name publishNewBark \
    --zip-file fileb://publishNewBark.zip \
    --role arn:aws:iam::123456789012:role/service-role/LambdatestRole  \
    --handler publishNewBark.handler \
    --timeout 5 \
    --runtime nodejs10.x

テスト用のpayload.jsonを作成

payload.json
{
    "Records": [
        {
            "eventID": "7de3041dd709b024af6f29e4fa13d34c",
            "eventName": "INSERT",
            "eventVersion": "1.1",
            "eventSource": "aws:dynamodb",
            "awsRegion": "ap-northeast-1",
            "dynamodb": {
                "ApproximateCreationDateTime": 1479499740,
                "Keys": {
                    "Timestamp": {
                        "S": "2016-11-18:12:09:36"
                    },
                    "Username": {
                        "S": "naata"
                    }
                },
                "NewImage": {
                    "Timestamp": {
                        "S": "2016-11-18:12:09:36"
                    },
                    "Message": {
                        "S": "This is a bark from the test social network"
                    },
                    "Username": {
                        "S": "naata"
                    }
                },
                "SequenceNumber": "13021600000000001596893679",
                "SizeBytes": 112,
                "StreamViewType": "NEW_IMAGE"
            },
            "eventSourceARN": "arn:aws:dynamodb:ap-northeast-1:123456789012:table/dynamodbtesttable/stream/2019-12-23T05:35:44.887"
        }
    ]
}

テストする。

$ aws lambda invoke --function-name publishNewBark --payload file://payload.json output.txt
{
    "ExecutedVersion": "$LATEST",
    "StatusCode": 200
}

output.txtに出力された内容を確認する。

output.txt
"Successfully processed 1 records.

SNSメール通知されていることも確認。

5.本番テスト

dynamodbのArnを確認。

aws dynamodb describe-table --table-name dynamodbtesttable

 "LatestStreamArn": "arn:aws:dynamodb:ap-northeast-1:123456789012:table/dynamodbtesttable/stream/2019-12-23T05:35:44.887

イベントソースとAWS Lambda関数間のマッピングを作成

aws lambda create-event-source-mapping \
    --region ap-northeast-1 \
    --function-name publishNewBark \
    --event-source arn:aws:dynamodb:ap-northeast-1:268546037544:table/dynamodbtesttable/stream/2019-12-23T05:35:44.887 \
    --batch-size 1 \
    --starting-position TRIM_HORIZON

dynamodbテーブルに項目を追加。

aws dynamodb put-item \
    --table-name dynamodbtesttable \
    --item Username={S="Jane Doe"},Timestamp={S="2016-11-18:14:32:17"},Message={S="Testing...1...2...3"}

SNS通知されたことを確認。

おしまい。

2
3
0

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
3