2021-11-27
AWSLambda(Golang)×DynamoDBのローカル開発環境を整える
# 目的
AWS LambdaでバックエンドAPIを構築しているとき、関数の挙動を確認したいときは都度devにデプロイしていました。流石にローカルでの開発環境を整えたいと思ったのですがGoでの使い方の情報が少なかったので個人メモとしてまとめてみました。
今回はAPI GatewayがトリガーのLambda関数になります。
→serverless invoke local -f <function>で十分らしいです
# 全体の流れ
以下のJavascript filesのところを今回はGolangにしてやってみます。
引用: https://qiita.com/noralife/items/e36621ddd0e5b8ff4447#%E6%A7%8B%E6%88%90
大まかな流れは以下です。
1. DynamoDB Localをインストール&セットアップ
2. Serverless offlineをインストール &セットアップ
# DynamoDB Localをインストール&セットアップ
## パッケージインストール
$ npm install --save-dev serverless-dynamodb-local
## serverless.ymlにプラグインを追記
```serverless.yml
plugins:
- serverless-dynamodb-local
```
## JDKがなければここでインストール
dynamodb-localのためにはJavaが必要でしたので、ローカルpcにJavaを入れていない方はインストールします。
インストールの仕方は、mac osだと、以下が参考になります。
https://qiita.com/suke_masa/items/f9af0fb84ad9447ae961
## dynamo db localをインストール
serverless.ymlのあるディレクトリにて、
```sh
$ sls dynamodb install
```
## カスタム定義
```serverless.yml
custom:
dynamodb:
stages:
- dev
start:
port: 8000
inMemory: true
migrate: true
seed: true
seed:
development:
sources:
- table: テーブル名
```
この状態で、
```sh
sls dynamodb start
```
でdynamodbがローカルで立ち上がります。
http://localhost:8000/shell
にアクセスすると管理画面に移れる。
シェル例
```
var params = {
TableName: 'pr_enqueteform_dev',
};
dynamodb.scan(params, function(err, data) {
if (err) ppJson(err);
else ppJson(data);
});
```
# Serverless offlineをインストール &セットアップ
次にローカルでapi gatewayを試すためにServerless offlineをインストールしていきます。
## パッケージインストール
```sh
$ npm install --save-dev serverless-offline
```
## serverless.ymlにプラグインを追加
```serverless.yml
plugins:
- serverless-dynamodb-local
- serverless-offline ### 追記
```
## カスタム定義
```serverless.yml
custom:
serverless-offline:
useDocker: true
```
この状態で
```sh
$ npx sls offline
```
でローカルで起動できます。
※Makefileにて、
```sh
$ make local-test
```
を打つことでビルド〜offline起動までやってくれるようにしています。
例:
```sh
$ npx sls offline
Serverless: Deprecation warning: CLI options definitions were upgraded with <中略>
┌───────────────────────────────────────────────────────────────────────────────────────┐
│ │
│ POST | http://localhost:3000/dev/submit │
│ POST | http://localhost:3000/2015-03-31/functions/EnqueteformReceiver/invocations │
│ │
└───────────────────────────────────────────────────────────────────────────────────────┘
offline: [HTTP] server ready: http://localhost:3000 🚀
offline:
offline: Enter "rp" to replay the last request
offline: POST /dev/submit (λ: EnqueteformReceiver)
```
上記みたいな感じになっていたら立ち上がっています🎉
# offlineとdynamodb-localを疎通させる
localでofflineを使ってlambda apiを叩いてログを出力してみると、
handlerのeventsの中の、
events.APIGatewayProxyRequest.RequestContext.APIID
が "offlineContext_apiId"
となっていました。
そこで、この部分で判断して、localのdynamodbクライアントを生成するか本番用のdynamodbクライアントを生成するかを条件分岐させることにします。
localのdynamodbクライアントの生成方法は以下でやります。
```go
func (c *DynamoDBClient) OfflineDynamoDBClient(region string, tableName string) *DynamoDBClient {
sess := session.Must(session.NewSession())
config := aws.Config{
Region: aws.String(region),
Endpoint: aws.String("http://host.docker.internal:8000"),
DisableSSL: aws.Bool(true),
Credentials: credentials.NewStaticCredentials("dummy", "dummy", "dummy"),
}
dynamodbClient := DynamoDBClient{
tableName: tableName,
dynamo: dynamodb.New(sess, &config),
}
return &dynamodbClient
}
```
※もっとよい判定方法がありそうな感じです。
# 試してみる
ローカルでコードを編集した後、一度ビルドしなければローカルの方にも反映されませんので、
```sh
$ make clean
$ make build
$ npx sls offline
```
とします。
## curlで疎通してみる
sls offlineしたターミナルとは別のタブにて、
```sh
curl http://localhost:3000/dev/submit -X POST -H "Content-Type: application/json" -d '{"category":"hogecategory","email":"sample@gmail.com","address":"東京都", "hoge":{"id":"1001","text":"hogehoge"}}'
```
sls offlineしたターミナルのタブにてログが出てくる。
```sh
START RequestId: d09*7296d-***-1c72-545b-5**c58d99034 Version: $LATEST
<中略>
END RequestId: d09729?6d-b4e2-1c72-5*45b-5e**ec58d99034
REPORT RequestId: d09?7296d-*b4e2-1c72-545b-5c5*d99034 Init Duration: 189.68 ms Duration: 5513.25 ms Billed Duration: 5514 ms Memory Size: 3008 MB Max Memory Used: 34 MB
```
実際にローカルのdynamoDBにデータを挿入する関数であれば、
http://localhost:8000/shell
をみてみると挿入されていることが確認できます!
# 参考
Serverless Framework での AWS Lambda + Go ローカル開発事情
serverless framework + TypeScript +DynamoDB のローカル環境