VS Codeでlambda-localを実装し、ローカル環境でデバッグ

#はじめに
前回の記事では、Alexaスキル開発に、Visual Studio Code (VS Code)を利用して、ローカルPC上でソースコード開発するための環境づくりについて説明しました。
私は、これまでAlexaスキル開発には、フロント部分は、Alexa Developer Consoleで開発し、バックエンド部分は、AWS lambda上でソースコードを書いて開発していました。
スキルの試験は、Alexa Deleloper Consoleのシミュレーターでの試験と、AWS lambda上で各ハンドラー処理用のJSONを作成して試験していました。

AWS lambda上の試験では、Step by Stepで試験できないため、エラーが発生しエラーメッセージをみたときに、その処理の何が悪いのか特定するのに苦労していました。変数の値に問題があるのか？とか、Case文が違う処理に飛んでしまっていないか？など、エラーメッセージだけではなかなか判断に迷うことがあります。
そこで、いたるところに、console.logを入れて変数の値や、処理の通った所などをチェックしながら状況を把握していました。
VS Codeではデバッグ機能もあるため、今回その環境を作ることにしました。これができればかなりデバッグが楽になります。
まだ、完全ではありませんが、まとめておきます。
今のところ以下はできません。

- 最後のJSON出力が表示されない
- DynamoDBはローカルではない

でも、**ブレークポイント**を設けてそこで変数の値を調べることはできるようになったため、まずはこれで随分に私の期待することはできるようになったかなと思います。

#環境
OS:Windows 10 JP
Alexaスキル言語：Node.js
Editor：Visual Studio Code
Alexa実行環境：lambda-local

#参考
[Visual Studio CodeとASK CLIのインストールと設定](https://qiita.com/Mount/items/bb949956b88dffcf5b95)
Visual Studio CodeとASK CLIで、AWS lambdaへソースコードをダウンロードしたりアップロードしたりする手順をまとめました。

[New Alexa Technical Tutorial: Debugging AWS Lambda Code Locally](https://developer.amazon.com/ja/blogs/post/Tx24Z2QZP5RRTG1/new-alexa-technical-tutorial-debugging-aws-lambda-code-locally)
今回のデバッグの方法を調べていたところ、Alexa Blogがひっかかり、この記事を参考にしました。

[Locally Debugging AWS Lambdas written in Node.JS](https://standardofnorms.wordpress.com/2017/12/03/locally-debugging-aws-lambdas-written-in-node-js/)
今回のデバッグの方法を調べていたところ、この記事を見つけました。
最終的にこの記事が決め手になりました。

#用語説明
##「Node.js」
サーバサイドのJavascriptであり、その環境。
AlexaスキルでもNode.jsを利用可能です。

##「DynamoDB」
AmazonのAWSで提供するNonSQLのデータベースです。
Alexaスキル開発において、過去の情報を保持するためにDynamoDBに情報を保存します。
私にとっては、Alexaスキル開発には必要不可欠なものです。

#前提
[Visual Studio CodeとASK CLIのインストールと設定](https://qiita.com/Mount/items/bb949956b88dffcf5b95)
の続きの記事ですので、Node.jsやVS Codeがインストールされていることが前提です。

#今回作成する環境
今回作成する環境は、以下の図の通りです。
![lambda-local構成.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405480/c88e019c-3ab4-9966-6648-18b573f88a52.jpeg)

ローカルPC上に、Alexaスキルのソースとモジュールを置き、またLambda-localをインストールします。
DynamoDBは、ローカルではなく、AWSにあるものを利用します。
他の方が書かれている記事では、DynamoDBをローカルにおいて実施されていることが多いようです。
もちろんDynamoDBのローカル環境での実施の需要があることも理解できますが、色々試してみたのですが、なかなかうまくいきませんでした。
私の場合、すでにDynamoDBにいろいろテーブルがあってそれを読み込むため、別途ローカルにDynamoDBを置くよりも、そのままAWSにあるものを使えたほうが有用でしたので、これで進めます。

#lambda-localのインストール
lambdaをローカルPC上で実施するために、コマンドプロンプトからlambda-localを以下の通りインストールします。

```
$ npm install -g lambda-local
```


lambda-localは、`%appdata%npm\node_modules\lambda-local`にインストールされます。
`%appdata%`は、普通は`C:\Users\(ユーザ名)\AppData\Roaming`です。
ちなみにアンインストールする場合は、以下の通りです。

```
$ npm uninstall -g lambda-local
```

#lambda-localでスキル実行
lambda-localが正常にインストールされているか確認します。
まずはじめに何かのスキルを作成し、それをローカルPC上のどこかに置きましょう。
VS CodeでASK CLI経由でCloneを使ってすでにあるスキルをダウンロードしてもよいですし、自分で一から作ってもよいです。
ASK CLI経由でスキルをダウンロードする場合、aws-sdkが存在しない可能性があります。その場合は、コマンドプロンプトからnpmコマンドでインストールします。
このコマンドを実行する場合、index.jsが存在するフォルダ上で実施しましょう。すると、その配下のnode_modulesにask-sdkがインストールされます。一緒にaws-sdkもインストールされます。

```
$ npm install ask-sdk
```

続いて、index.jsのイベントハンドラーとして、JSONファイル(ここでは`launchrequest.json`)を準備します。私は大変なので、これは、Alexa developer consoleのシミュレータでスキルの呼び出しコマンドを入力して作成されたJSONファイルをコピーして作成しています。それをとりあえず、`index.js`と同じフォルダに置きます。

コマンドプロンプトから`index.js`の存在するフォルダパス上で、以下のコマンドを実行します。もし、実行するときのフォルダパスとindex.jsやlaunchrequest.jsonのパスが異なる場合はカレントフォルダからの相対パスを設定して実行します。
これでうまく、結果のJSON応答がコマンドプロンプトに表示されれば、正常です。

```
$ lambda-local -l index.js -h handler -e launchrequest.json
```

|オプション|説明|
|:---|:---|
|-l|Lambda関数ハンドラーが定義されたファイルのパス|
|-h|同ハンドラーの名称|
|-e|ハンドラーに渡すJSONファイルのパス|

実行した結果は以下の通りです。
![lambda-local.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405480/cc75e17f-6733-b8c6-f1e5-84abf008dfc8.jpeg)

#VS Code上でデバッグ環境を構築
1. ソースコードの準備
VS Code上でソースコードを準備する。
普通に実施すれば、`lambda\[地域名_スキル名]`の配下にソースコードは置かれるはずです。
ローカルPC上でデバッグする場合、aws-sdkも必要ですので、もし、node_modulesにaws-sdkフォルダが存在しない場合、**lambda-localでスキル実行**を参考に、aws-sdkをインストールする。

2. イベントハンドラー用のJSONファイル作成
試験で使用するイベントハンドラー用のJSONファイルは、`lambda`配下に新たにフォルダを作成し(私の場合は、`lambda\test`のようにしています)、そこにJSONファイルを置く。
index.jsと異なる場所に億音は、最終的にAWSのlambdaへファイルをdeploy（アップロード）する場合、`lambda\[地域名_スキル名]`のフォルダ配下のファイルがdeployされます。試験用のJSONファイルは不要かと思いますので、ここに置いています。
ファイルの置き場所の参考に図を載せておきます。
![JSON保存先.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405480/2afd2185-e8df-47f5-a556-0441a371fbf8.jpeg)

3. デバッグの設定

ここでは、デバッグの設定を記載します。まずは図を載せます。
![debug手順.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405480/820af1e6-37b9-cf11-25cb-8b186e309a81.jpeg)


①デバッグボタンをクリック。
②設定ボタンをクリック。「環境の選択」と表示されるため、「Node.js」を選択する。
③そうすると、デフォルトのlaunch.jsonが表示されるため、以下の通りに編集する。

```json:launch.json
            "program": "${env:AppData}\\npm\\node_modules\\lambda-local\\bin\\lambda-local",
            "cwd": "${workspaceFolder}",
            "args" : [
                "-l",
                "lambda\\[地域名_スキル名]\\index.js",
                "-h",
                "handler",
                "-e",
                "lambda\\test\\LaunchRequest.json"
            ]
```

実施していることはコマンドプロンプトで実施していることは同じですが、少し記載が違います。
実はここで少し詰まりましたので、説明します。

- program：lambda-localのパスを記載します。`${env:AppData}`で、`%AppData%`と同じ場所を指します。コマンドプロンプトで実施する場合は、環境変数のPATHが通っていて、`lambda-local`だけでよかったですが、ここでは絶対パスを記載する必要があるようです。
- cwd：`${workspaceFolder}`は、VS Codeのワークフォルダを示します。コマンドプロンプトでは、`index.js`が置かれているフォルダ上で、コマンドを実行しましたが、ここでは、それをこのように記載して実行する作業フォルダを指定します。
- arg：少し書き方が違いますが、-l, -h, -eはコマンドプロンプトと同じです。その後のファイル指定は、cwdで指定した作業フォルダからのindex.jsの相対位置や、JSONファイルの相対位置です。

わかれば大したことないのですが、なかなかパスの違う場所のファイルをどう指定するのか？がわからなかったため、つまっていました。

④デバッグ実行ボタンを押す。
これで、デバッグが開始されます。
ブレイクポイントの設定もできますが、その辺の説明はここでは記載しませんので、必要に応じてネットを検索するなりしてください。

#DynamoDBへのアクセス
実は何もしなくても、このままDynamoDBへアクセスができました。
`node_modules`配下に`aws-sdk`が入っていれば、そのまま、AWSのDynamoDBへアクセス可能です。

ただし、DynamoDBへのアクセスのために権限設定が必要です。
[Visual Studio CodeとASK CLIのインストールと設定](https://qiita.com/Mount/items/bb949956b88dffcf5b95)を参考に、「2. AWS IAMユーザーのセットアップ」で、「AmazonDynamoDBFullAccess」のあるユーザーを作ります。
「3. AWSの資格情報とASK CLIとの関連付け」に従って、`credentials`に反映します。
そうすると、DynamoDBへアクセスできます。

AWS上のlambdaからDynamoDBへアクセスする場合、関数にロール設定しますが、VS Codeから実施する場合、ユーザーの権限からアクセスしているように感じました。
`credentials`に設定するのが、ユーザーのアクセスキーとシークレットキーなためそう感じました。
また、最終確認はしなかったのですが、[default]のキーを使っているのでは？と思いました。

#おわりに
今回の説明は以上です。

DynamoDB-localのインストールも試していましたが、まだうまくいっていません。
私の用途ではAWSへアクセスするほうが楽なので別によいのですが、少し気にはなります。

また、AWS toolkit for visual studio codeがVS Codeのマーケットプレイスからインストールできるため、これでサクッとできるのでは？と期待しましたが、そのままではできないようです。
最終的には、このtoolkitで、ローカル、リモートともに試験できるようになるようですが、現在はリモート接続して、実行できるとか情報をとるくらいしかできませんでした。実行できるだけでもありがたいですが、デバッグできなさそうだったので残念です。

まだまだ、AWSのサービスは発展途上だと思いますので、これから開発が楽になるようにどんどんツールを提供してもらえたらうれしいなと思うのでした。