AWSのAPI Gateway + LambdaをSAM CLIを使ってGolangで試してみた

今までGCPを触ってきましたが、最近AWSを使う機会が多くなってきたので、[SAM CLI](https://github.com/awslabs/aws-sam-cli)を使ってローカルで動かしてデプロイまで試してみました

# 前提条件

- macOS Mojave (10.14.1)
- pyenv 1.2.7
- python 2.7.14
- pip 9.0.1
- sam 0.6.2

# SAM CLIとは

> AWS SAM に基づくツールであり、サーバーレスアプリケーションを Lambda ランタイムにアップロードする前にローカルで開発、テスト、および分析するための環境を提供します。

詳細は[こちら](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/test-sam-cli.html)

# SAM CLIのインストール

SAM CLIをインストールする前にDockerをインストールする必要があります
Dockerのインストールは[こちら](https://www.docker.com/)

DockerをインストールしたらpipでSAM CLIをインストールします
今回はpyenvでpython 2.7.14を使いました

```sh
# Install PyEnv (https://github.com/pyenv/pyenv#installation)
$ brew update
$ brew install pyenv

# Initialize pyenv using bash_profile
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n  eval "$(pyenv init -)"\nfi' >> ~/.bash_profile
# or using zshrc
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
$ echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n  eval "$(pyenv init -)"\nfi' >> ~/.zshrc

# restart the shell
$ exec "$SHELL"

# Install Python 2.7
$ pyenv install 2.7.14
$ pyenv local 2.7.14

# Install the CLI
$ pip install aws-sam-cli

# Verify your installation worked
$ sam –-version
SAM CLI, version 0.6.2
```

# アプリケーションの雛形を作成

`sam init` コマンドでアプリケーションの雛形を作成できます

```sh
$ sam init -r go1.x
$ tree sam-app
sam-app
├── Makefile
├── README.md
├── hello-world
│   ├── main.go
│   └── main_test.go
└── template.yaml
```

# ローカルで実行

パッケージをインストールして `go build` したら `sam local start-api` コマンドでローカルで実行できます
Makefileが予め用意されているので、Goのビルドは `make build` で行います

```sh
$ dep init
$ make build
GOOS=linux GOARCH=amd64 go build -o hello-world/hello-world ./hello-world
$ sam local start-api
2018-11-12 22:56:23 Mounting HelloWorldFunction at http://127.0.0.1:3000/hello [GET]
2018-11-12 22:56:23 You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template
2018-11-12 22:56:23  * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)
```

この状態でcurlをたたくと、レスポンスが返ってきます

```sh
$ curl 127.0.0.1:3000/hello
Hello, <IP_ADDRESS>
```

# デプロイ

デプロイもSAM CLIで行います

```
$ # s3バケットを作成
$ aws s3 mb s3://sam-deploy-<YOUR_ACCOUNT_ID> --region ap-northeast-1
make_bucket: sam-deploy-<YOUR_ACCOUNT_ID>
$ # Packaging
$ sam package \
    --template-file template.yaml \
    --output-template-file serverless-output.yaml \
    --s3-bucket sam-deploy-<YOUR_ACCOUNT_ID>
Uploading to 9543f7f01a265998376958f78ccb4f3c  4336441 / 4336441.0  (100.00%)
Successfully packaged artifacts and wrote output template to file serverless-output.yaml.
Execute the following command to deploy the packaged template
aws cloudformation deploy --template-file /path/to/serverless-output.yaml --stack-name <YOUR STACK NAME>
$ # Deploying
$ sam deploy \
    --template-file serverless-output.yaml \
    --stack-name <YOUR STACK NAME> \
    --capabilities CAPABILITY_IAM

Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - <YOUR STACK NAME>
```

これでデプロイは完了です、AWSのコンソール画面から確認すると、デプロイしたLambda関数とAPI Gatewayが確認できます
curlを叩いてもレスポンスが正常に返ってきます

```sh
$ curl https://<YOUR_URL>.execute-api.ap-northeast-1.amazonaws.com/Prod/hello
Hello, <IP_ADDRESS>
```

# まとめ

SAM CLIを使うと、ローカルで簡単にLambda関数の開発、テストが行えるので便利です
また、まだ試してないですがAPI Gatewayだけでなく、S3、DynamoDBイベントに対応する関数の実装とテストもできるようです、この辺は試してみたら書きたいと思います