Chalice with DynamoDB
この記事の目的
この記事の目的は、AWS製のサーバーレスフレームワークChaliceとDynamoDBを組み合わせて利用する手順を個人的なメモとして記すことです。
以下の内容を含みます。
- Chalice, DynamoDBともにAWS上で利用します
- Chalice, DynamoDBLocalを用いてローカルマシンでも利用します(長くなるので次回投稿にします)
以下の内容はカバー出来なかったので今後の課題とします。
- ローカル環境でのIDEを利用したデバッグ
- DynamoDB構築のCDKなどの利用(今回はaws-cliコマンドで実行)
- ユニットテスト
前提事項
以下のインストールについては済んでいるものとします。
- Python3
- chalice
- aws-cli
- docker-compose
ちなみに、私の環境は以下のようになっています。(2022/1/24時点)
- Python 3.8.9 (Pipenv利用)
- chalice 1.26.4
- aws-cli 2.4.11
- docer-compose 2.1.1
- VSCode 1.63.2
- macOS Monterey 12.1
References
Chalice公式サイト https://aws.github.io/chalice/index.html
構築手順
Project作成
% chalice new-project chalice_demo
Your project has been generated in ./chalice_demo
AWSにデプロイする
デプロイ
% chalice deploy
Creating deployment package.
Creating IAM role: chalice_demo-dev
Creating lambda function: chalice_demo-dev
Creating Rest API
Resources deployed:
- Lambda ARN: arn:aws:lambda:ap-northeast-1:123456789012:function:chalice_demo-dev
- Rest API URL: https://abcdefghij.execute-api.<region>.amazonaws.com/api/
リソースを消す
% chalice delete
Deleting Rest API: abcdefghij
Deleting function: arn:aws:lambda:ap-northeast-1:123456789012:function:chalice_demo-dev
Deleting IAM role: chalice_demo-dev
以下のIAMロールとインラインのポリシーが作成される
- IAM Role chalice_demo-dev
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:*:logs:*:*:*"
}
]
}
DynamoDBのテーブルをAWS上に構築する
本来は、CDKなどで実施したいのですが、スタディーが足りないので、今回はaws-cliで作成しました。
詳細は、README.mdを参照ください。
DBアクセス処理を実装する
- config.jsonの変更
- policy-dev.jsonの追加
- chalicelib/database.pyを追加
- app.pyの変更
config.jsonが重要なので、そこから説明します。
詳しくは、こちらをご覧ください。
ここでのポイントは、環境変数DB_TABLE_NAMEにDynamoDBのテーブル名を設定するところと、autogen_policy(ソースからIAMロールを自動生成する機能)をFalseにしているところ。
{
"version": "2.0",
"app_name": "chalice_demo",
"stages": {
"dev": {
"api_gateway_stage": "api",
"environment_variables": {
"DB_TABLE_NAME": "Records"
},
"autogen_policy": false
}
}
}
上で、autogen_plicyをFalseにしているので、ポリシーを手動で定義する。
このファイルのネーミングルールは、policy-<ステージ名>.jsonとなる。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"dynamodb:PutItem",
"dynamodb:DeleteItem",
"dynamodb:UpdateItem",
"dynamodb:GetItem",
"dynamodb:Scan",
"dynamodb:Query"
],
"Resource": "*"
}
]
}
Pythonのソースコードは長いので、要所だけ記載します。
全体はGitHubを参照ください。
import os
import boto3
from boto3.dynamodb.conditions import Key,Attr
import uuid
def _get_database():
endpoint = os.environ.get('DB_ENDPOINT')
if endpoint:
print('*** DB_ENDPOINT指定あり ***')
print(endpoint)
return boto3.resource('dynamodb', endpoint_url=endpoint)
else:
print('*** DB_ENDPOINT指定なし ***')
return boto3.resource('dynamodb')
def get_record(record_id):
table = _get_database().Table(os.environ['DB_TABLE_NAME'])
response = table.get_item(Key={'id': record_id})
return response['Item']
app.pyにrecords/{record_id}のエンドポイントを追加する例です。
import os
from chalice import Chalice, NotFoundError, BadRequestError
from chalicelib import database
app = Chalice(app_name='chalice_demo')
@app.route('/records/{record_id}', methods=['GET'], cors=True)
def get_records(record_id):
record = database.get_record(record_id)
if record:
return record
else:
raise NotFoundError('Record not found.')
再度デプロイし動作確認します。
再度chalice deploy
を行い、エンドポイントを呼び出します。
# 結果は見やすく整形しています。
% curl https://abcdefghij.execute-api.<リージョン名>.amazonaws.com/api/records/id2
{
"result_time":"00:23:11",
"race":"3",
"section":"2",
"runner_name":"test-runner",
"team":"TeamA",
"description":"Memo2",
"id":"id2",
"sub":"LOCAL_USER"
}
まとめ
今回は、Chalice with DynamoDBということで、簡単な処理を実装してみました。
Chaliceで基本構成のAPI Gatewayは簡単に作成できますが、いろいろなリソースとの連携は、Chaliceだけだと限界がある気はします。
それもあってか、Chaliceは最近ではCDKとの連携もできるようです。
https://aws.github.io/chalice/tutorials/cdk.html
今回は採用していませんが、そのうちに、他のAWSサービスとの連携に使ってみたいと思います。
次回は、Chalice with DynamoDBのローカル実行について書きたいと思います。
Discussion