LoginSignup
1
0

More than 1 year has passed since last update.

Chalice with DynamoDB

Last updated at Posted at 2022-01-24

この記事の目的

この記事の目的は、AWS製のサーバーレスフレームワークChaliceとDynamoDBを組み合わせて利用する手順を個人的なメモとして記すことです。

以下の内容を含みます。

  • Chalice, DynamoDBともにAWS上で利用します
  • Chalice, DynamoDBLocalを用いてローカルマシンでも利用します(長くなるので次回投稿にします)

以下の内容はカバー出来なかったので今後の課題とします。

  • ローカル環境でのIDEを利用したデバッグ
  • DynamoDB構築のCDKなどの利用(今回はaws-cliコマンドで実行)
  • ユニットテスト

前提事項

以下のインストールについては済んでいるものとします。

  • Python3
  • chalice
  • aws-cli
  • docker-compose
ちなみに、私の環境は以下のようになっています。(2022/1/24時点) - Python 3.9.7 (pyenv利用) - 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にしているところ。

config.json
{
  "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となる。

policy-dev.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を参照ください。

chalicelib/database.py
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.query(KeyConditionExpression=Key('id').eq(record_id))
    items = response['Items']
    return items[0] if items else None

app.pyにrecords/{record_id}のエンドポイントを追加する例です。

app.py
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のローカル実行について書きたいと思います。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0