【続】WSL2 + AWS Toolkit for Visual Studio Code + SAM local + DynamoDB local

自分用の備忘録程度にと思ったら、タイトルのせいか結構Viewされていて、見て頂いた方に申し訳なく、ちょっと後ろめたくなったので、少し補足します。
主に参考にした記事へのリンクですが。

元々の記事の趣旨はvscode以外、全てWSL2(Ubuntu)のbash上で完結するlambda + dynamodbのローカル開発環境環境を作ってみたいと思い、試行した結果（元々はハマったことの共有）です。

モチベーションは、PowerShellが好きじゃない（食わず嫌い）MS-DOSなオッサンだけど、cmdよりbashが使いたいからです。

**※Windows 10 Insider Preview 20H1が前提のため、自己責任でお願いします。
※最近は殆どありませんが、数か月前まで私の環境では１日数回グリーンバックが出てました。
※Windows Update自体がバグってたりすることもあります。
※辞めたいと思っても次のメジャーアップデートまでクリーンインストール以外で製品版に戻せません。製品版でやりたい人は2020年春まで待ってください。**

## 手順全体
1. Windows 10 Insider Preview 20H1のインストールとWSL2のインストール
2. docker desktop community 2.1.7.0(41536) edge
3. WSL2(Ubuntu)に各種ソフトをインストール
  1. Python 3.7.5
  2. pip 19.3.1
  3. aws-cli 1.16.299
  4. aws-sam-cli 0.37.0
4. DynamoDB local (docker image : amazon/dynamodb-local)
  1. SAM localから通信させるための設定
5. Visual Studio Code 1.41.0
  1. AWS Toolkit for Visual Studio Code 1.4.0
  2. Remote - WSL 0.41.5
6. SAM localでHello World
7. NoSQL Workbench for Amazon DynamoDB (Preview)を使う
8. SAM localからDynamoDB localに接続してみる

## lambda + dynamodbなPythonコード環境をローカルで動かす。

### 1. Windows 10 Insider Preview 20H1のインストール

そもそも既知の不具合ありの状態です。
この辺を参考に、自分の環境で入れても大丈夫か判断してください。
[Tattuの備忘Log](https://tattu1902.blog.fc2.com/blog-entry-123.html)

以下の記事など参考にしてインストールしてください。
[WSL 2 のインストール手順](https://docs.microsoft.com/ja-jp/windows/wsl/wsl2-install)

**※2019/12/17現在、FastリングはDevelopment branchに変わりました。
※WSL2を使うだけならSlowリングからインストールしてください。**

「Linux ディストリビューションがインストールされていない場合は～」
のステップでは、Windows StoreからUbuntuをインストールしてから先に進みます。

入れ終わったらお約束の「sudo apt update / sudo apt upgrade」をお忘れなく。


### 2. docker desktop community 2.1.7.0(41536) edge

公式からダウンロードしてインストールします。
[WSL2 で Docker Desktop for Windows (Edge) を利用する](https://qiita.com/SakaiYuki/items/e5ab0061ff3273c0e80f)

設定が完了すると、ubuntu上でdockerをインストールしなくてもbashからdockerコマンドが使用できます。（便利！）

動作確認にbashから「docker info」してみてください。


### 3. WSL2(Ubuntu)に各種ソフトをインストール
Pythonかpipのインストールでは先にインストールしておくaptなパッケージが足らず１度やり直しています。
ご注意ください。

#### 3.1. Python / 3.2. pip

pyenvを入れて、そこからインストールしました。
[Ubuntu 18.04 に pyenv と Python 3.7.2 をインストールしたメモ](http://s-edword.hatenablog.com/entry/2019/04/14/155432)


#### 3.3. aws-cli 1.16.299

公式通りpipを使ってインストールしました。
pip自体は既に入っているかもしれないので「pip --version」で確認してみてください。

https://docs.aws.amazon.com/ja_jp/streams/latest/dev/kinesis-tutorial-cli-installation.html

ローカルで使うだけなら「aws configure」のAccess KeyとSecret Access Keyはいい加減で構いません。
そもそもいらないような？
region は「ap-northeast-1」でいいと思います。


#### 3.4. aws-sam-cli 0.37.0

aws-cliと同様にpipを使っていれました。
[AWS SAM で Hello World する](https://qiita.com/mokuo/items/3348f19d12cb9b17295d)

この記事と同じようにパッケージが足らず、途中でエラーになった気がします。
必要なパッケージをapt installで追加でいれて再試行したような気がしますが、参考にした記事を失念してしまいました。


### 4. DynamoDB local (docker image : amazon/dynamodb-local)

普通にdocker runしてイメージを取ってきます。
[dockerhub](https://hub.docker.com/r/amazon/dynamodb-local/)


docker network createして。

```bash:bash
$ docker network create aws-local
```

docker runしたコンテナを停止してから、適当なディレクトリに「docker-compose.yml」を作成して、docker-compose upします。

```yml:docker-compose.yml
version: "3"

services:
  dynamodb:
    container_name: dynamodb-local
    image: amazon/dynamodb-local
    volumes:
      - ./data:/data
    ports:
      - 58000:8000
    command: -jar DynamoDBLocal.jar -port 8000 -dbPath /data -sharedDb
    networks:
      - aws-local

networks:
  aws-local:
    external: true
```

「comannd:」の部分がjavaランタイムに渡す値です。この例ではカレントディレクトリ配下の「./data」に「shared-local-instance.db」を残して他と共有します。このファイルはSQLiteで弄れるらしいのですが、試してません。

```bash:bash
user@MYHOSTNAME:~/docker/dynamodb-local$ docker-compose up -d
```

#### 4.1. SAM localから通信させるための設定

「.bash_profile」（※１）にSAM_DOCKER_NETWORKを環境変数として追加します。

（※１）penvのインストール時に作ったはず。

```bash:.bash_profile
export SAM_DOCKER_NETWORK=aws-local
export PYENV_ROOT=$HOME/.pyenv
export PATH=$PYENV_ROOT/bin:$PATH
eval "$(pyenv init -)"
source ~/.bashrc
```

### 5. Visual Studio Code 1.41.0

公式通りに普通にインストールします。
[Visual Studio Code - コード エディター | Microsoft Azure](https://azure.microsoft.com/ja-jp/products/visual-studio-code/)


#### 5.1. AWS Toolkit for Visual Studio Code 1.4.0 / 5.2. Remote - WSL 0.41.5

vscode上のExtentionから普通にインストールします。
[Installing the AWS Toolkit for Visual Studio Code](https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/setup-toolkit.html)

Remote - WSLはExtentionから入れなくても有効になるようです。（私はExtentionから自前で入れました。）
[VSCodeのRemote WSLでWSLを快適に使う](https://qiita.com/nj_ryoo0/items/a42c47436b77310f5430)

### 6. SAM localでHello World

ここまで来たらSAM localでPythonなlambda関数を動かせるはずです。

このページの「特徴」→「迅速に使用を開始する方法」にあるイメージのようにコマンドパレットからPython3.7のアプリケーションを作成してください。
https://aws.amazon.com/jp/visualstudiocode/

作成できたら、サイドメニューのファイルのアイコン（explorer）で表示されるツリーから「app.py」を選択してエディタで表示した後にサイドバーの「AWS」のアイコンを選択します。
しばらく待つと「def lambda_handler(event, context):」の上にCodeLensで「Run Locally | Debug～」と出るので「Run Locally」をクリックすればSAM localでアプリケーションが実行されます。

[Visual Studio CodeでSAMアプリケーション開発](http://www.s-watanabe.work/article/470692989.html)

今回の手順では、全てローカル実行しAWSには接続しないので「Connect to AWS...」は触らなくて良いです。

コンソールにjsonでHello Worldとレスポンスが表示されればOKです。


### 7. NoSQL Workbench for Amazon DynamoDB (Preview)を使う

最近、「NoSQL Workbench」でDynamoDB localの操作も可能になりましたのでこれを使ってテーブル作成や初期データを投入しました。
次のステップで使用するので適当に簡単なテーブルを作成して、初期データを１件投入しておいてください。

公式からダウンロードしてインストールします。
[Download NoSQL Workbench](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/workbench.settingup.html)

使い方の参考はこちら。
N[oSQL Workbench for Amazon DynamoDB - プレビューの使用が可能になりました](https://aws.amazon.com/jp/blogs/news/nosql-workbench-for-amazon-dynamodb-available-in-preview/)


### 8. SAM localからDynamoDB localに接続してみる

「app.py」を修正してDynamoDB localのコンテナに接続してみます。
テーブル名やPKのカラム名や値は前項で作成した自身のものを使用してください。

```python:app.py
# ～中略～

import os
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)

import boto3

def lambda_handler(event, context):

# ～中略～

    # SAM local上の環境変数を見る
    logger.info('## ENVIRONMENT VARIABLES')
    logger.info(os.environ)
    # 実行時のリクエストを見る
    logger.info('## EVENT')
    logger.info(event)

# ～中略～

    # dockerコンテナなSAM localからだとlocalhostでつながらない。
    # SAM_DOCKER_NETWORKでdynamodb localと同じネットワークでSAM localのコンテナを動くよう指定し、dyanmodb localのコンテナ名と”コンテナ内のポート”番号をendpoint_urlに指定する。
    dynamodb = boto3.resource('dynamodb', endpoint_url="http://dynamodb-local:8000")

    pk = {'YOUR KEY': 'KEY VALUE'}
    table = dynamodb.Table('YOURTABLE NAME')
    res = table.get_item(Key = pk)
    print(res)

# ～中略～

```

上手く動けば前項で設定した初期データがjson形式で表示されるはずです。


## 雑感

とりあえずクローズドネットワーク環境でlambda + dynamodbの開発が出来そうな目途が立ちました。
ただ、boto3.resource()のendpoint_url指定はデプロイしたら不要になるようなので、一工夫必要になると思ってます。