CDK(Python)でS3をトリガーにしてLambdaを発火する
もくじ
S3のバケットにObjectが入ったのをトリガーにしてLambdaを発火するー、
をPythonのCDKで実装してみます👍
アーキテクチャを描くとこんな感じです。
久々にブログにアーキテクチャを張り付けた😁これ描くの好き
そして初めにことわって置きたいのですが、cdkには上記をイメージして実装します。
実際にCDKから出力されるテンプレートは若干違うモノになります😅
前提
過去記事の分岐
では 作っていきましょう👻
といってもほぼほぼコードのサンプルになりますが😅
requirements.txt
使うリソースはlambdaとS3とlambdaのトリガーなので必要なのはcore
を除いて3つです。
aws-cdk.core==1.72.0
aws-cdk.aws_s3==1.72.0
aws-cdk.aws-lambda==1.72.0
aws_cdk.aws_lambda_event_sources==1.72.0
lambdaの実装
おまけですがlambdaはこんな感じで作っておきます
import json
import boto3
s3 = boto3.resource("s3")
def lambda_handler(event, context):
s3_record = event["Records"][0]["s3"]
object = s3.Object(s3_record["bucket"]["name"], s3_record["object"]["key"])
file_body = object.get()["Body"].read()
print(file_body)
return {}
Stackの実装
from aws_cdk import aws_lambda, aws_s3, core
from aws_cdk.aws_lambda_event_sources import S3EventSource
class LambdaTriggerS3Stack(core.Stack):
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
# S3
bucket = aws_s3.Bucket(
self,
"LambdaTriggerS3Bucket",
removal_policy=core.RemovalPolicy.DESTROY, # Stack削除と同時にバケットを削除する
)
# lambda
common_lambda_params = dict(
runtime=aws_lambda.Runtime.PYTHON_3_8,
handler="lambda_function.lambda_handler",
timeout=core.Duration.seconds(10),
memory_size=128,
)
lambda_ = aws_lambda.Function(
self,
"LambdaTriggerS3Lambda",
code=aws_lambda.Code.asset("lambdas/lambda_trigger_s3"),
**common_lambda_params,
)
# lambdaにtriggerを付与
lambda_.add_event_source(
S3EventSource(
bucket,
events=[aws_s3.EventType.OBJECT_CREATED_PUT],
# filterを設定する場合は、下記のコメントアウトを外す
# filters=[aws_s3.NotificationKeyFilter(prefix="カスタムプレフィックス/", suffix="拡張子")],
)
)
# lambdaの権限
bucket.grant_read(lambda_)
エントリーポイントに追記
app.py
に下記を追記します。
...省略...
from stacks.lambda_trigger_s3_stack import LambdaTriggerS3Stack
...省略...
LambdaTriggerS3Stack(app, "lambda-trigger-s3-stack", env=env)
...省略...
deploy
$ cdk deploy lambda-trigger-s3-stack
アップロードしてみる
バケット名を指定しなかったのでとんでもない名前(バケット名:lambda-trigger-s3-stack-lambdatriggers3bucket8c39-s20rkcnz27i5
)になりました(笑)
バケット名をコンソールや$ aws s3 ls | grep lambda-trigger-s3-stack
あたりで調べて、下記を参考にitemをアップロードしてみてください
$ echo hogehoge > item.txt
$ aws s3 cp item.txt s3://lambda-trigger-s3-stack-lambdatriggers3bucket8c39-s20rkcnz27i5/
CloudWatchのコンソールでログを確認すると、objectをきちんと取得して出力できていることが確認できました。
START RequestId: 850b642c-6c3e-43dd-8bce-2456b74eb617 Version: $LATEST
b'hogehoge\n'
END RequestId: 850b642c-6c3e-43dd-8bce-2456b74eb617
そして余談ですが、じつはlambdaがもう一つ自動でデプロイされていて、それがこんな感じ(↓)で発生したイベントのログを残してます。このへんが一番初めにことわったアーキテクチャとの違いです。
{
"RequestType": "Create",
...省略
"Events": [
"s3:ObjectCreated:Put"
],
...省略
}
まとめ
今回はcdkを使って、S3バケットにデータが入ったこと(ObjectCreated:Put)をトリガーにlambdaを発火するサンプルを作り、動作の確認をしました👍