localstackについて理解する（lambda版）


# ローカルスタックとは

localstcak とは，AWS のクラウドサービスをローカル環境でエミュレートするためのツールです．

例えば，AWS を使用したサービスを開発している際に，AWS を使用した api などのテストを行いたい時があります．その時に，実際に AWS のサービスを使用するとコストがかかってしまうため，ローカル環境で AWS のサービスをエミュレートすることで，コストを抑えることができます．

:::note info
mock とやっていることは同じなので，コスト削減以外にもテストを行う際は使うと便利です！！
:::

# ローカルスタックの構成

ローカルスタックは，数多くの AWS サービスをエミュレートすることができます．
今回は lambda に関してやっていこうと思います．

:::note info
s3 のみを使う場合では minio を使う方が便利かも知れません．
:::

まずはこのドキュメントを参考にして，作っていきます．
環境は docker を使って構築します．

https://docs.localstack.cloud/user-guide/aws/lambda/

# ローカルで動く lambda 関数の作成

## コードファイルの作成

まずは local で動く lambda 関数を作成します．
今回はテストを想定しているので，モックとしてレスポンスさえくれば良いという感じにします．
この関数はドキュメントにあったものですが，内容としては 2 つの数字を受け取って，その積を返す関数です．

```javascript
exports.handler = async (event) => {
  let body = JSON.parse(event.body);
  const product = body.num1 * body.num2;
  const response = {
    statusCode: 200,
    body:
      "The product of " + body.num1 + " and " + body.num2 + " is " + product,
  };
  return response;
};
```

これは javascript で書かれた lambda 関数ですが，もちろん他の言語でも書くことができます．しかし，実際に開発で使っている言語と関係がないので javascript でいいと思います．

## zip ファイルに圧縮

以下のコマンドで zip ファイルに圧縮します．

```bash
zip function.zip index.js
```

# localstack で lambda の起動

## docker-compose.yml の作成

docker-compose を使って localstack を起動します．

```yaml
version: "3.8"
services:
  localstack:
    container_name: "localstack"
    image: localstack/localstack
    hostname: localstack
    ports:
      - "4566:4566"
    environment:
      - SERVICES=lambda
      - DOCKER_HOST=unix:///var/run/docker.sock
      - HOST_TMP_FOLDER=${TMPDIR}
      - HOSTNAME_EXTERNAL=localstack
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    networks:
      - backend_network
networks:
  backend_network:
volumes:
  sample-data:
```

docker-compose.yml というファイルを作成して，以下のコマンドで localstack を起動します．

```bash
docker-compose up
```

これで localstack が起動します．

:::note warn
これは localstack を起動しただけで，lambda 関数は起動していないことに注意してください．localstack というサーバーに lambda 関数をデプロイする必要があります．
:::

## lambda 関数のデプロイ

以下のコマンドで lambda 関数をデプロイします．

```bash
aws --endpoint-url=http://localhost:4566 lambda create-function \
	--function-name lambda-function-name \
	--runtime nodejs12.x \
	--zip-file fileb://function.zip \
	--handler index.handler \
	--role arn:aws:iam::000000000000:role/lambda-role
```

function-nambe は自分で指定してください．lambda 関数は先ほど作成した zip ファイルを読み込んでいます．
iam の部分はこのままにしておきましょう．変更するとエラーが出ることがあります．

これで localstack に lambda 関数がデプロイされました．

# lambda 関数の実行

以下のコマンドで lambda 関数を実行(invoke)します．

```bash
curl -X POST \
    'http://localstack:4566.lambda-url.us-east-1.localhost.localstack.cloud:4566/' \
    -H 'Content-Type: application/json' \
    -d '{"num1": "10", "num2": "10"}'
```

# エラー集

## aws の region を指定してください

lambda 関数をデプロイする際に，aws の region を指定してくださいとエラーが出ることがあります．
どうやら，localstack は us-east-1 をデフォルトで使っているようなので，あわしてあげると良いです．

## aws-local との違い

ドキュメントは aws-local を使っています．
これは python のライブラリで region などを環境ごとに指定することができるそうです．

aws コマンドを指定する場合は，aws の region などを指定するようにしてください．

もし，makefile などで指定している場合は，以下のようにしてください．

```bash
set -a; source .env.local; set +a; aws --endpoint-url=http://localhost:4566 lambda create-function \
		--function-name lambda-function-name \
		--runtime nodejs12.x \
		--zip-file fileb://function.zip \
		--handler index.handler \
		--role arn:aws:iam::000000000000:role/lambda-role
```