AWS Serverless Application Model 入門ハンズオンシリーズ - log4ketancho の第3弾です。
前回の記事では、AWS SAM を使って Lambda Function をプログラマブルに構築する方法について紹介しました。今回は、
- SAM を用いて DynamoDB のテーブルを構築する
- Lambda から DynamoDB にデータストアする
について手順を解説していきます。
DynamoDB テーブルを構築
まず DynamoDB テーブルを構築します。記載の方法は CloudFormation と同じで、Resources
以下に設定情報を記載していきます。下記のようなテーブルを構築します。
- プライマリーキーは
name
という文字列型のカラム - Read / Write ユニットともに2
Resources: SamSampleLambda: (省略. 前回と同じです.) SamSampleDynamoTable: Type: AWS::Serverless::SimpleTable Properties: PrimaryKey: Name: name Type: String ProvisionedThroughput: ReadCapacityUnits: 2 WriteCapacityUnits: 2
テンプレートを変更したので、package
コマンドと deploy
コマンドを実行します。コマンドを再掲しておきます。
$ aws cloudformation package \ --template-file template.yaml \ --s3-bucket ketancho-sam-sample \ --output-template-file packaged-template.yaml \ --profile sam-sample
$ aws cloudformation deploy \ --template-file packaged-template.yaml \ --stack-name sam-sample-stack \ --capabilities CAPABILITY_IAM \ --profile sam-sample
ここまでで、DynamoDB のテーブルが構築できるはずです。マネージメントコンソールで確認してみましょう。
うまく構築できているでしょうか?DynamoDBのテーブル名の最後にランダムな文字列が付いていることを覚えておいてください。
Lambda から DynamoDB にデータストアする
前回の記事で作成した、外部APIを叩く Lambda 関数を改修し、APIで取得した値をテーブルに格納するようにしてみます。
Lambda Function の作成
データ格納は boto3
という AWS の Python SDK を用いて行います。boto3
は Lambda 標準でインストールされているライブラリになりますので、前回のような pip install
は不要です。その他、JSON 形式のデータを作成するために json
パッケージ、浮動小数点を扱うために decimal
パッケージを用いて、下記のような Lambda Function を作成します。
# -*- coding: utf-8 -*- import requests import boto3 import json import decimal def lambda_handler(event, context): bf_res = requests.get("https://api.bitflyer.jp/v1/ticker?product_code=BTC_JPY") _insert_dynamo(bf_res.json()["ltp"]) def _insert_dynamo(price): dynamo = boto3.resource('dynamodb').Table("**テーブル名**") json_str = ''' { "name": "btc", "price": %f } ''' % (price) item = json.loads(json_str, parse_float=decimal.Decimal) dynamo.put_item(Item = item) return {"status": "OK"}
注意しないといけないのが、テーブル名は構築時(deploy
時)に決定するので、このプログラム作成時点では確定していない点です。このような CloudFormation Stack 構築時に決まるリソースIDを扱うには、Lambda の環境変数(Environment
> Variables
)機能と CloudFormation の Ref
関数を用います。
Lambda の環境変数を使ってハードコーディングを避ける
環境に応じて変わる値を、Lambda のプログラムにハードコーディングしないようにするためには、Lambda の環境変数機能を用います。SAMの最初の記事でも少しだけ紹介したのですが、下記のように Environment
> Variables
に値を書くことで、環境変数を設定することができます。
Globals: Function: Runtime: python3.6 Timeout: 15 MemorySize: 256 Environment: Variables: TABLE_NAME: "table_name"
ここでは、Globals
セクションに設定していますが、Lambda Function ごとに定義することも可能です。
ここで設定した環境変数を Lambda Function の中で参照するには、下記のように os
パッケージを利用します。
# -*- coding: utf-8 -*- import os import requests import boto3 import json import decimal def lambda_handler(event, context): bf_res = requests.get("https://api.bitflyer.jp/v1/ticker?product_code=BTC_JPY") _insert_dynamo(bf_res.json()["ltp"]) def _insert_dynamo(price): dynamo = boto3.resource('dynamodb').Table(os.environ['TABLE_NAME']) json_str = ''' { "name": "btc", "price": %f } ''' % (price) item = json.loads(json_str, parse_float=decimal.Decimal) dynamo.put_item(Item = item) return {"status": "OK"}
Ref 関数を用いて CFn Stack 構築時に決まる値を取得する
環境変数に埋め込む値(ここでは DynamoDB のテーブル名)は、Stack 構築時に決まります。このような値を参照するには、CloudFormation の Ref
関数を用います。
Globals: Function: Runtime: python3.6 Timeout: 15 MemorySize: 256 Environment: Variables: TABLE_NAME: !Ref SamSampleDynamoTable #★変更箇所 Resources: SamSampleLambda: (省略. 前回と同じです.) SamSampleDynamoTable: Type: AWS::Serverless::SimpleTable Properties: PrimaryKey: Name: name Type: String ProvisionedThroughput: ReadCapacityUnits: 2 WriteCapacityUnits: 2
Resources
セクションで定義したリソース名を Ref
関数で参照することで、動的に決まる値を取得することができます。
CloudFormation には便利な関数がたくさん用意されています。関数を用いることで、環境に依存しない、再利用しやすいテンプレートを作ることができます。Cfn 関数のうち代表的なものの利用方法は、下記の本で解説させていただきました。もしよろしければご覧いただけると幸いです。
Amazon Web Services 業務システム設計・移行ガイド (Informatics&IDEA)
- 作者: 佐々木拓郎,林晋一郎,瀬戸島敏宏,宮川亮,金澤圭
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2018/01/20
- メディア: 単行本
- この商品を含むブログ (1件) を見る
以上で、Lambda から DynamoDB への接続を、SAM で構築することができました。不明点、うまくいかない点がございましたら、ご連絡いただければと思います。
まとめと今後
DynamoDB のテーブル構築と、Lambda - DynamoDB 間の連携ができるようになりました。次回は、API Gateway を用いて Rest API を SAM でプログラマブルに構築する方法についてまとめられればと考えています。
この記事は、AWS Serveless Application Model 入門シリーズの第3弾です。