ローカル（Mac）で Step Function / Lambda / DynamoDB を動かす

# これなに？
- ローカル環境（Mac）でAWS Step Function / Lambda / DynamoDB を動かす手順をまとめます
- 以下の記事を参考にしています
    - https://dev.classmethod.jp/articles/stepfunctionslocal-localstack/
    - 2021/06/06現在、LocalStackのポート指定が変わっているようです

# ざっくりとした手順
1. Dockerのインストール
1. Docker HubよりLocalStackと、Step Functions Localのイメージを取得
1. LocalStack起動
1. DynamoDBテーブル作成
1. Lambda関数作成
1. Step Functions作成
1. Step Functions起動

# Dockerのインストール
Dockerが必要なので、ない場合はインストールしてください
AWS CLIも、ない場合はインストールしてください

# Docker HubよりLocalStackと、Step Functions Localのイメージを取得
以下のコマンドでpullしましょう

```
$ docker pull localstack/localstack
$ docker pull amazon/aws-stepfunctions-local
```

取得できたか確認します

```
$ docker images
```

## 備考
https://github.com/localstack/localstack
をcloneしてきて、 `docker-compose` でも起動できます
こっちのほうが楽かもしれません

# LocalStack起動
以下のコマンドで起動できます

```
$ docker run --rm -it -p 4566:4566 -p 4571:4571 localstack/localstack
```

## 備考
https://github.com/localstack/localstack に記載がありますが、
LocalStackの `0.11.0` から、DynamoDB、Lambdaなどすべてのサービスが同じポート `4566` で起動するようになったそうです

## 備考2
```
$ aws configure --profile localstack
```

でプロファイルを適当に定義すると良いかもですが、設定しなくても動作はするようです
設定例）

```
AWS Access Key ID [None]: dummy
AWS Secret Access Key [None]: dummy
Default region name [None]: us-east-1
Default output format [None]: text
```

# DynamoDBテーブル作成

```
$ aws dynamodb create-table --table-name TestTable \
    --attribute-definitions AttributeName=Id,AttributeType=N \
    --key-schema AttributeName=Id,KeyType=HASH \
    --endpoint-url http://localhost:4566 \
    --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1
```

```
$ aws dynamodb scan --table-name TestTable --endpoint-url http://localhost:4566
```

# Lambda作成

## 関数作成
参考サイトから ~~パクって~~ オマージュして来たものをもとに関数を作ります
DynamoDBのエンドポイントが記載されているので、LocalStackのエンドポイントを指定します
中身は `TestTable` に1行だけPUTするものです
ファイル名は適当に `lambda.py` としています 

```
import boto3
def lambda_handler(event, context):
    dynamodb = boto3.resource('dynamodb', region_name='us-east-1',endpoint_url='http://localhost:4566/')
    table = dynamodb.Table('TestTable')
    response = table.put_item(
        Item={
            'Id': 1,
            'Name': 'Mayoi'
        }
    )
    return response
```

## Lambda関数を作成
作成した関数をzipにします

```
$ zip lambda.zip lambda.py
```

次にデプロイします

```
$ aws lambda create-function \
  --function-name=TestFunction \
  --runtime=python3.6 \
  --role=DummyRole \
  --handler=lambda.lambda_handler \
  --zip-file fileb://lambda.zip \
  --endpoint-url=http://localhost:4566
```

エンドポイントURLはDynamoDBと同一でOKです（LocalStackの `0.11.0` 以降）

# Step Functions作成

## 設定ファイル作成
```
$ vi aws-stepfunctions-local-credentials.txt 
```

vi で以下の内容のファイルを作成してください

```
LAMBDA_ENDPOINT=http://host.docker.internal:4566
```

LambdaのエンドポイントをStep Functionsに設定しています
他にも、もろもろ設定する場合は以下を参考にしてください
https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/sfn-local-config-options.html#docker-credentials

## StepFunctions Localコンテナ起動
StepFunctionsのコンテナを起動します

```
docker run -p 8083:8083 --env-file aws-stepfunctions-local-credentials.txt amazon/aws-stepfunctions-local
```

## ステートマシン作成
StepFunctionsのステートマシンを作成します
ステートマシンとはざっくり言うと、状態管理の定義かと思います
StepFunctions君は、横浜駅へ行って高島屋で日本酒買って帰ってくるみたいな指令書を定義します

参考にした記事では `defin_statemachine.json` というファイルにステートマシンを定義しています

```
{
  "StartAt": "Shinobu",
  "States": {
    "Shinobu": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:::function:TestFunction",
      "End": true
    }
  }
}
```

ステートマシンの定義ファイルを書いたら、以下のコマンドで実際にステートマシンを作成します

```
aws stepfunctions create-state-machine \
  --name TestState \
  --definition file://defin_statemachine.json \
  --role-arn "arn:aws:iam::000000000000:role/DummyRole" \
  --endpoint http://localhost:8083
```

うまく作成できると、以下のようなのが返ってきます

```
1622974168.008	arn:aws:states:us-east-1:123456789012:stateMachine:TestState
```

`arn:aws:states:us-east-1:123456789012:stateMachine:TestState` はARNです
ステートマシンを実行するときには、こいつを指定します

# Step Functions起動
ステートマシンの定義ができたので、実際に実行してみます

```
$ aws stepfunctions start-execution \
  --state-machine arn:aws:states:us-east-1:123456789012:stateMachine:TestState \
  --endpoint http://localhost:8083
```

上記を実行すると、ステートマシンが起動し、Lambdaが実行され、DynamoDBに値が書き込まれるはずです
実行すると、以下のように実行のARNが払い出されるので、これを用いて結果確認も可能です

```
arn:aws:states:us-east-1:123456789012:execution:TestState:6a2e5112-6c3e-42d8-9359-426b66e26617	1622975148.062
```

結果確認は以下のようなコマンドです

```
$ aws stepfunctions describe-execution \
  --execution-arn arn:aws:states:us-east-1:123456789012:execution:TestState:6a2e5112-6c3e-42d8-9359-426b66e26617 \
  --endpoint=http://localhost:8083
```

`SUCCEEDED` が返ってきたら成功やで！

# 結果確認
DynamoDBをscanしてみて、データが入っているか確認してみましょう

```
$ aws dynamodb scan --table-name TestTable --endpoint-url http://localhost:4566
```

値が入っていたら優勝！

# 参考にした記事 :bow: 
https://dev.classmethod.jp/articles/stepfunctionslocal-localstack/
https://dev.classmethod.jp/articles/localstack-lambda/

https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/sfn-local-config-options.html#docker-credentials