この記事について
AWS CDKv2でCRUD操作ができるAPIを作る
今回はPythonを使う
プロジェクト初期化
CLIのインストール
CLI自体はnodeのものを使う(ので導入済みならスキップ)
npm install -g aws-cdk
cdk --version
バージョンが表示されればOK
CDK Toolkitのデプロイ
初回のみCDKを利用する際に必要となるファイル群のデプロイが必要
→これもやったことがあるならスキップ
cdk bootstrap aws://${ACCOUNT}/${REGION}
以下のように表示されればOK
✅ Environment aws://${ACCOUNT}/${REGION} bootstrapped.
※異なるアカウント、リージョンでCDKを利用する場合はまたこの作業が必要になる
プロジェクト初期化
適当なディレクトリで↓を実行
cdk init app --language python
こんな感じでプロジェクトが初期化される
モジュールのインストール
venvを使って仮想環境にモジュールをインストールする
python3 -m venv .venv
source .venv/bin/activate
これで仮想環境が立ち上がる
次にインストールするモジュールのリスト(requirements.txt)を更新
aws-cdk-lib==2.29.1
constructs>=10.0.0,<11.0.0
aws_cdk.aws_lambda_python_alpha
そうしたらpipインストールする
pip install -r requirements.txt
実装
CDKのコードを書く
from aws_cdk import (
RemovalPolicy,
Stack,
aws_dynamodb as dynamodb,
aws_iam as iam,
aws_lambda,
aws_lambda_python_alpha,
aws_logs as logs,
aws_apigateway as apigateway
)
from constructs import Construct
class TodoappPyStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
# DynamoDB
todos_table = dynamodb.Table(
self,
'TodosTable',
table_name='todoapp-py-todos-table',
partition_key=dynamodb.Attribute(
name='id',
type=dynamodb.AttributeType.STRING
),
removal_policy=RemovalPolicy.DESTROY)
# Lambda
todo_function = aws_lambda_python_alpha.PythonFunction(
self,
'TodoFunction',
runtime=aws_lambda.Runtime.PYTHON_3_9,
entry='src',
index='main.py',
handler='handler',
function_name='todoapp-py-function',
environment={
'TODOS_TABLE_NAME': todos_table.table_name
},
)
# LambdaにDynamoDBのCRUD操作権限を付与
todo_function.add_to_role_policy(iam.PolicyStatement(
effect=iam.Effect.ALLOW,
actions=[
'dynamodb:Scan',
'dynamodb:PutItem',
'dynamodb:UpdateItem',
'dynamodb:DeleteItem',
],
resources=[todos_table.table_arn]
))
# LogGroup
logs.LogGroup(self,
'TodoFunctionLogs',
log_group_name='/aws/lambda/' + todo_function.function_name,
removal_policy=RemovalPolicy.DESTROY)
# API Gateway
api = apigateway.RestApi(self,
'TodoAPI',
rest_api_name='todoapp-py-api',
default_cors_preflight_options=apigateway.CorsOptions(
allow_origins=apigateway.Cors.ALL_ORIGINS,
allow_methods=apigateway.Cors.ALL_METHODS,
allow_headers=apigateway.Cors.DEFAULT_HEADERS,
status_code=200
))
integration = apigateway.LambdaIntegration(todo_function)
# /todos
todos_resource = api.root.add_resource('todos')
todos_resource.add_method('GET', integration=integration)
todos_resource.add_method('POST', integration=integration)
# /todos/{id}
todo_id_resource = todos_resource.add_resource('{id}')
todo_id_resource.add_method('PUT', integration=integration)
todo_id_resource.add_method('DELETE', integration=integration)
前回TypeScriptで実装した時とほぼいっしょ
Lambdaを定義している箇所は少々ややこしいので↓に抜き出して補足する
aws_lambda_python_alphaについて
todo_function = aws_lambda_python_alpha.PythonFunction(
self,
'TodoFunction',
runtime=aws_lambda.Runtime.PYTHON_3_9,
entry='src',
index='main.py',
handler='handler',
function_name='todoapp-py-function',
environment={
'TODOS_TABLE_NAME': todos_table.table_name
},
)
-
entry
- Lambdaのソースコードがあるディレクトリを指定する
-
index
- Lambdaのエントリーポイントとなるファイル名を指定する
-
handler
- Lambdaのエントリーポイントとなる関数名を指定する
端的に言うと、↑のように書いた場合はここをLambdaのエントリーポイントとして、
ここを参照してモジュールをインストールしアップロードしてくれる
※ドキュメントも参照
Lambdaのコード実装
こちらのサンプルコードを参照
ルーティングをFlaskで、API Gatewayとの結合をawsgiで実装した
デプロイ
↓を実行
cdk deploy TodoappPyStack
動作確認
↓を実行
export ENDPOINT="API Gatewayのエンドポイント"
bash tests/test.bash
感想
CDKのコードは概ねTypeScriptで実装した時と同じ感覚で書けた
唯一Lambdaは割と勝手が違っていたので少々躓いた
※aws_lambda_nodejsとaws_lambda_python_alphaの差分
- エントリーポイントの書き方
- Lambdaのコードで使うモジュールの指定
- nodejs...CDKのプロジェクトのpackage.jsonに書けばOK
- python...別途Lambdaのコードのディレクトリにrequirements.txtを書く必要がある
また、TypeScriptに比べて資料が少ないように感じたので、CDK全く触ったことない人が始めるには公式ドキュメントとにらめっこしないといけないので大変そう
※技術ブログではなく何事も常に一次資料にあたるのが本来あるべき姿というのは置いておくとして
とはいえ、(至極当然のことではあるけど)PythonのCDK固有の難点みたいなものは特に感じられなかったので、Pythonをよく使っているチームなら採用しても全く問題ないと思う
次はC#かGolangでやってみる予定