CDK(Python)で複数stackでリソースを共有する
cdkで複数stackを使い、こっちのstackで作ったリソースを別のstackで使いたい!
というシチュエーションがあったのですが、どうしようか悩んだ挙げ句1個の巨大なStackにしてしまった、という経験があったので「さて、どうやったらstackを分けられるのかな?」と実装してみました。
調べてて分かったことは、いくつか方法があるぽいですね。
今回の構成はこんな感じです👍
以前の記事で作ったlambda-trigger-s3-stack
を再利用して、そのBucketにPUTするlambdaを作ろうと思います👍
前提
cdkのシリーズの続き。
公式のドキュメントはこのあたり、
https://docs.aws.amazon.com/cdk/latest/guide/stack_how_to_create_multiple_stacks.html
では 作っていきましょう👻
requirements.txt
今回は使うリソースは以前のstacklambda-trigger-s3-stack
と同じなので、requirements.txt
に追加する行はありません、詳細は過去記事を参照くださいませ🙇
以前のstackのstackファイルへの追記
# ...省略
class LambdaTriggerS3Stack(core.Stack):
def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
# ...省略
self.bucket = bucket
__init__
の末尾に作成したbucketをインスタンス変数に登録します。
今回のstackファイル
ほぼほぼいつもと一緒ですが、違う点は__init__
の引数にput_bucket: aws_s3.Bucket
を持っていることです。
ここに他で作ったS3Bucketのリソース情報を受け取って内部に反映させる感じですね👍
後はlambdaからS3にアクセスするために、環境変数へバケット名を入れている点ですかね
from aws_cdk import aws_lambda, aws_s3, core
class SameResourceStack(core.Stack):
def __init__(self, scope: core.Construct, id: str, put_bucket: aws_s3.Bucket, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
# lambda
lambda_ = aws_lambda.Function(
self,
"SameResourceLambda",
code=aws_lambda.Code.asset("lambdas/same_resource"),
runtime=aws_lambda.Runtime.PYTHON_3_8,
handler="lambda_function.lambda_handler",
environment={"PUT_BUCKET_NAME": put_bucket.bucket_name},
)
# lambdaの権限
put_bucket.grant_write(lambda_)
lambdaの実装
いつものおまけです(笑)
import json
import os
from datetime import datetime
import boto3
s3 = boto3.resource("s3")
def lambda_handler(event, context):
bucket_name = os.getenv("PUT_BUCKET_NAME")
key = f"{datetime.now()}.json"
object = s3.Object(bucket_name, key)
object.put(Body=json.dumps(event))
return {}
エントリーポイントへ修正と追記
まず修正点ですが、LambdaTriggerS3Stack
のインスタンスを変数で取得できるようにします。
次に追記分は今回のスタックを追加し、引数でbucket
を渡します。
最終的なコードはこんな感じ(↓)
...省略...
from stacks.same_resource import SameResourceStack
...省略...
lambda_trigger_s3_stack = LambdaTriggerS3Stack(app, "lambda-trigger-s3-stack", env=env)
SameResourceStack(app, "same-resources-stack", put_bucket=lambda_trigger_s3_stack.bucket, env=env)
...省略...
デプロイ🚀
GoGo-🎉
$ cdk deploy lambda-trigger-s3-stack
$ cdk deploy same-resources-stack
確認
今回作ったlambdaの名前を取得します。
コンソールから取得するなり、こんな(↓)感じで取得するなりとってきます。
$ aws lambda list-functions | grep same-resources-stack
今回はこんな名前same-resources-stack-SameResourceLambda6084D48C-A27UUTX5LQMM
でした😅
そして、もう一つ。S3のBucket名を取得します。こんな(↓)感じ
$ aws s3 ls | grep lambda-trigger-s3-stack
名前はlambda-trigger-s3-stack-lambdatriggers3bucket8c39-s20rkcnz27i5
でした。
可読性向上のため変数に放り込みます。
$ LAMBDA_NAME=same-resources-stack-SameResourceLambda6084D48C-A27UUTX5LQMM
$ BUCKET_NAME=lambda-trigger-s3-stack-lambdatriggers3bucket8c39-s20rkcnz27i5
Lambdaを動かしてみる。
$ aws lambda invoke --function-name $LAMBDA_NAME --payload '{"hoge_key": "hogehoge_data"}' response.json
{
"StatusCode": 200,
"ExecutedVersion": "$LATEST"
}
# 一応レスポンスの確認
$ cat response.json
{}
Bucketにobjectが入ったことを確認する。
$ aws s3 ls s3://$BUCKET_NAME
2020-11-17 22:53:25 29 2020-11-17 13:53:23.850327.json
なにやら2020-11-17 13:53:23.850327.json
というobjectがいますね😉
そして、、、あ、やらかしましたね私😰
key名にスペース入ってる。。。のがちょっとやな感じ、、、ダブルクォーテーション入れとけばいいかな🤔
$ aws s3 cp "s3://$BUCKET_NAME/2020-11-17 13:53:23.850327.json" -
{"hoge_key": "hogehoge_data"}
まぁとりあえず、Lambdaで入れたeventの内容がobjectとしてきちんと入ったのが確認できました👍
destroy💣
今回作ったstackを削除しておきましょう😉
まずバケットが空でないと削除できないので空にします。
$ aws s3 rm s3://$BUCKET_NAME --recursive
# 空っぽになったことを確認する
$ aws s3 ls s3://$BUCKET_NAME
複数stackをまとめて削除
$ cdk destroy --all
まとめ
cdkで複数stackを使い片方のstackで他方のリソースを使うということを実装してみました。
そしてcdk上から動作の確認をしました👍