こんにちは、ゲームソリューショングループのsoraです。
今回は、Lambda(Go)でDynamoDBのデータ取得・登録(GET/POST)をしてみたことを書いていきます。
データは都道府県名・県庁所在地・地域をカラムとして持つもので、都道府県名を渡すことで県庁所在地と地域を取得でき、全ての値を与えることで登録もできるようにしていきます。
LambdaとDynamoDBの作成
今回はTerraformを使って作成します。
Terraformソースコード
まずは、AWS側で必要なサービスを作成します。
main.tf
terraform {
#AWSプロバイダーのバージョン指定
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.51.0"
}
}
}
#AWSプロバイダーの定義
provider aws {
region = "ap-northeast-1"
}
#Lambda用IAMロールの信頼関係の定義
data aws_iam_policy_document assume_role {
statement {
effect = "Allow"
principals {
type = "Service"
identifiers = ["lambda.amazonaws.com"]
}
actions = ["sts:AssumeRole"]
}
}
#Lambda用IAMロールの作成
resource aws_iam_role iam_for_lambda {
name = "Prefecture_Lambda_Role"
assume_role_policy = data.aws_iam_policy_document.assume_role.json
managed_policy_arns=["arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess"]
}
#Lambdaへの配置ファイルのzip化
data archive_file lambda {
type = "zip"
source_file = "dynamodbapi"
output_path = "handler.zip"
}
#Lambdaの作成
resource aws_lambda_function Prefecture_Lambda {
filename = "handler.zip"
function_name = "DynamoDBAPI_Lambda"
role = aws_iam_role.iam_for_lambda.arn
handler = "dynamodbapi"
source_code_hash = data.archive_file.lambda.output_base64sha256
runtime = "go1.x"
}
#DynamoDBの作成
resource aws_dynamodb_table prefecture_table {
name = "PrefecturesTable"
billing_mode = "PAY_PER_REQUEST"
hash_key = "PrefectureName"
range_key = "Region"
attribute {
name = "PrefectureName"
type = "S"
}
attribute {
name = "Region"
type = "S"
}
}
#初期データファイルの取得
locals {
csv_data = file("prefectual.csv")
dataset = csvdecode(local.csv_data)
}
#テーブルアイテムの登録
resource aws_dynamodb_table_item table_item {
for_each = { for record in local.dataset : record.prefecturename => record }
table_name = aws_dynamodb_table.prefecture_table.name
hash_key = aws_dynamodb_table.prefecture_table.hash_key
range_key = aws_dynamodb_table.prefecture_table.range_key
item = <<ITEM
{
"PrefectureName": {"S": "${each.value.prefecturename}"},
"PrefecturalCapital": {"S": "${each.value.prefecturalcapital}"},
"Region": {"S": "${each.value.region}"}
}
ITEM
}
DynamoDBへ初期値として登録するデータは、CSVファイルに記載してTerraform側でfor_eachを使って登録します。
prefectual.csv
prefecturename,prefecturalcapital,region
Hokkaido,Sapporo,Hokkaido
Tokyo,Tokyo,Kanto
Aichi,Nagoya,Chubu
Osaka,Osaka,Kansai
Hukuoka,Hakata,Kyushu
Lambdaで使用するコード(Go)
Goソースコード
GETメソッドで都道府県名を渡すことで県庁所在地と地域を取得でき、POSTメソッドでデータの登録ができる関数です。
aws-sdk-goを直接使う場合は複雑になるため、今回はguregu/dynamoを使用しています。
エラー処理は全然入れていないため、実際に使う場合は入れた方が良いです。
今回はAPI Gatewayまでは作りませんが、後に接続することを意識してAPIGatewayProxyRequestの形で受け取るようにしています。
dynamodb_connection.go
package main
import (
"fmt"
// Go用のLambdaプログラミングモデル
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/guregu/dynamo"
)
type Event struct {
PrefectureName string `json:"PrefectureName"`
Region string `json:"Region"`
PrefecturalCapital string `json:"PrefecturalCapital"`
}
// メソッドに応じて処理分岐
func DBOperateAPI(req events.APIGatewayProxyRequest) () {
db := dynamo.New(session.New(), &aws.Config{Region: aws.String("ap-northeast-1")})
table := db.Table("PrefecturesTable")
switch req.HTTPMethod {
case "GET":
prefecture_name := req.QueryStringParameters["PrefectureName"]
var results []Event
// ソートキーまで指定する場合は
// table.Get("PrefectureName", prefecture_name).Range("Region", dynamo.Equal, prefecture_region).One(&result)
// PrefectureNameが一致するものを全て取得
table.Get("PrefectureName", prefecture_name).All(&results)
fmt.Printf("%v\n", results)
case "POST":
prefecture_name := req.QueryStringParameters["PrefectureName"]
prefecture_region := req.QueryStringParameters["Region"]
prefecture_capital := req.QueryStringParameters["PrefecturalCapital"]
evt := Event{PrefectureName: prefecture_name, Region: prefecture_region, PrefecturalCapital: prefecture_capital}
table.Put(evt).Run()
}
}
func main() {
lambda.Start(DBOperateAPI)
}
デプロイ
コードの準備ができたため、実行していきます。
作成したGoファイルのビルド
GoファイルをLambdaに持っていく前に、ビルドをする必要があります。
$ go mod tidy
$ GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o dynamodbapi
ビルドが終わったら、dynamodbapiという名前のファイルができています。
Terraform実行
作成したTerraformのコードを実行して構築します。
$ terraform init
$ terraform apply
正常に構築できていることが確認できます。
DynamoDBに初期値として登録したデータも登録されています。
Lambdaでのテスト
構築できたのでLambdaでテストしていきます。
テストイベントのJSONは、APIGatewayProxyRequestの形式に合わせて設定します。
まず検索から実行します。
{
"HTTPMethod": "GET",
"QueryStringParameters": {
"PrefectureName": "Hokkaido"
}
}
printfで表示させているため、ログ出力に取得した結果が表示されています。
次に登録を実行します。
{
"HTTPMethod": "POST",
"QueryStringParameters": {
"PrefectureName": "Gifu",
"Region": "Chubu",
"PrefecturalCapital": "Gifu"
}
}
DynamoDBを見ると、POSTで渡したデータが登録されています。
参考記事
気楽にDynamoDBを使おう
API Gateway から Lambda にパラメータを渡す
最後に
今回は、Lambda(Go)でDynamoDBへのデータ取得・登録(GET/POST)してみたことを記事にしました。
どなたかの参考になると幸いです。