- LocalStack上で動くAmazon SNSのトピックに対して、AWS SAM CLIで動くLambdaからpublishを行う方法をメモする。
構成
LocalStack準備
docker-compose.yml
version: "3.8"
networks:
container-link:
name: docker.internal
services:
localstack:
container_name: "${LOCALSTACK_DOCKER_NAME-localstack_main}"
image: localstack/localstack
ports:
- "127.0.0.1:53:53" # only required for Pro
- "127.0.0.1:53:53/udp" # only required for Pro
- "127.0.0.1:443:443" # only required for Pro
- "127.0.0.1:4510-4530:4510-4530" # only required for Pro
- "127.0.0.1:4566:4566"
- "127.0.0.1:4571:4571"
environment:
- SERVICES=${SERVICES- }
- DEBUG=${DEBUG- }
- DATA_DIR=${DATA_DIR- }
- LAMBDA_EXECUTOR=${LAMBDA_EXECUTOR- }
- LOCALSTACK_API_KEY=${LOCALSTACK_API_KEY- } # only required for Pro
- HOST_TMP_FOLDER=${TMPDIR:-/tmp/}localstack
- DOCKER_HOST=unix:///var/run/docker.sock
volumes:
- "${TMPDIR:-/tmp}/localstack:/tmp/localstack"
- "/var/run/docker.sock:/var/run/docker.sock"
networks:
- container-link
- 起動
docker-compose up
SNS準備
トピックの作成
aws sns create-topic --name test-topic --endpoint-url http://localhost:4566 --profile localstack
{
"TopicArn": "arn:aws:sns:ap-northeast-1:000000000000:test-topic"
}
トピックへのサブスクライブ
-
email
プロトコルとnotification-endpoint
の E メールアドレスを指定する。
aws sns subscribe --topic-arn arn:aws:sns:ap-northeast-1:000000000000:test-topic --protocol email --notification-endpoint test@example.com --endpoint-url http://localhost:4566 --profile localstack
{
"SubscriptionArn": "arn:aws:sns:ap-northeast-1:000000000000:test-topic:36e4e475-b360-4c7a-96f0-0690371e7566"
}
Lambda準備
- ひな形作成
sam init
※ランタイムはPython3.8を選択。
-
template.yml
- Hello World Exampleを利用する。
- /topic/subscribe(サブスクライブ用)と/topic/publish(パブリッシュ用)を設定するように以下修正
Events: PublishTopic: Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api Properties: Path: /topic/publish Method: post
requrements.txt
requests
boto3
※SNSアクセス用にboto3追加
- Lambda処理(
app.py
)修正
import json
from boto3.session import Session
# TopicARN
TOPIC_ARN = u'arn:aws:sns:ap-northeast-1:000000000000:test-topic'
# SNS 接続設定
session = Session(
aws_access_key_id='dummy',
aws_secret_access_key='dummy',
region_name='ap-northeast-1'
)
client = session.client(
service_name='sns',
endpoint_url='http://localstack:4566'
)
def lambda_handler(event, context):
# メッセージpublish
request = {
'TopicArn': TOPIC_ARN,
'Message': json.loads(event["body"])["msg"],
'Subject': json.loads(event["body"])["subject"]
}
response = client.publish(**request)
return {
"statusCode": 200,
"body": json.dumps({"MessageId":response["MessageId"]}),
}
動作確認
- ビルド
sam build
- 実行
sam local start-api --docker-network docker.internal
-
メッセージPublish
- リクエスト
POST /topic/publish HTTP/1.1 Host: localhost:3000 Content-Type: application/json Content-Length: 61 { "msg":"test message", "subject":"test subject" }
- レスポンス
{ "MessageId": "e08bba69-1ceb-4eef-9b88-19f74529bcbf" }