AWS Amplify フレームワークの使い方Part9〜Function 基礎編〜

# はじめに
Lmabda関数を管理しようと思うとServerlessFrameworkなんかがベタなのかな、と勝手に思っていて、なかなかGUIでの管理から抜け出せない日々が続いていた中で出会った、このAmplifyのfunction管理機能。

一言で言えば、素晴らしい。

# 設定の流れ
## amplifyにfunctionを追加
おなじみのコマンドでfunctionのファイルを作成。この時、cognito,auth,api,storage,functionの権限が聞かれますが、一旦スルー。私の場合は、基本的には別でロールを作成して紐付けるため、ここでは何も選択しません。(本当は利用したほうが、よりセキュアなロールポリシーをつけれる気はしているが、、、)

```console
$ amplify add function
? Provide a friendly name for your resource to be used as a label for this category in the project: createUser // 今回はfunction名と同一名で管理
? Provide the AWS Lambda function name: createUser // function名
? Choose the function template that you want to use: Hello world function //templateは何でもOK
? Do you want to access other resources created in this project from your Lambda function
? No
```

## 生成されたファイルの編集
pushする前に、各種ファイルを編集していきます。
### [ function名 ]-cloudformation-template.json
以下のコメント部分を必要に応じて追加します。基本的には`Resources`部分を編集していきます。

#### 基本設定
ロール、タイムアウト秒数、説明文、メモリサイズなどは`Resources > LambdaFunction `直下を編集する。

```json:functionName-cloudformation-template.json
{
    ...

    "Resources": {
        "LambdaFunction": {
          "Type": "AWS::Lambda::Function",
          "Metadata": {...},
          "Properties": {
            "Handler": "index.handler",
            "FunctionName": {...},
            "Environment": {...},
            "Role": "arn:aws:iam::xxxxxxxx:role/xxxxx", // 自身で作成したロールを設定
            "Runtime": "nodejs10.x", // 言語選択
            "Timeout": "60", // 必要な実行秒数変更
            "Description": "ユーザー情報の新規作成", // functionの説明文追加
            "MemorySize": "256" // 必要なメモリ数変更
          }
        },
    ...
}
```
#### DynamoDBストリームの設定
DynamoDBの書込を検知して実行する場合は、`Resources>EventSourceMapping`を編集する。基本的には、以下をまるっとコピペして貼り付け、`EventSourceArn`の部分だけ、DynamoDBの指定したテーブルの概要に記載されている、ストリームのarmをコピペすればOK。

```json:functionName-cloudformation-template.json
{
    ...

    "Resources": {

          ...
        },
       	"EventSourceMapping": {
			"Type": "AWS::Lambda::EventSourceMapping",
			"Properties": {
				"EventSourceArn": "arn:aws:dynamodb:ap-northeast-1:xxxxxxxxxxx:table/User/stream/2019-10-30T07:18:17.435", // DynamoDBの指定テーブルの概要に記載があるのでそれをコピペ
				"FunctionName": {
					"Fn::GetAtt": [
						"LambdaFunction",
						"Arn"
					]
				},
				"StartingPosition": "TRIM_HORIZON",
				"BatchSize": "100"
			}
		}
    },
    ...
}
```
複数のDynamoDBを複数指定したい場合は、現在わからなかったため、その場合のみGUIから手動で設定しています。

また、CloudWatch Eventsでの定時実行の設定もわからなかったため、こちらもGUIから手動設定しています。このあたりご存じの方いれば、ぜひ教えていただきたい。

#### 環境変数の設定
以下の通りに追記します。

```json:functionName-cloudformation-template.json
{
    ...

    "Resources": {
        "LambdaFunction": {
          "Type": "AWS::Lambda::Function",
          "Metadata": {
            "aws:asset:path": "./src",
            "aws:asset:property": "Code"
          },
          "Properties": {
            "Handler": "index.handler",
            "FunctionName": {},
            "Environment": {
                "Variables" : {
                    "ENV": {
                        "Ref": "env"
                    },
                    "REGION": { 
                        "Ref": "AWS::Region"
                    },
                    "TZ": "Asia/Tokyo" // ここに追記
                }
            }
    ...
}
```

## package.json
必要なmoduleを追加する場合は編集。

```
{
  "name": "createUser",
  "version": "2.0.0",
  "description": "Lambda function generated by Amplify",
  "main": "index.js",
  "license": "Apache-2.0",
  "dependencies": {
    "libmime": "^4.2.1"
    "stripe": "^7.12.0" 
  }
}

```

## index.js
実行したい関数の内容を記載。

## event.json
実行したいテストデータを編集。ここに記載したjsonデータはテスト実行時に、引数のeventから取得ができます。

```json:event.json
{
    "key1": "value1",
    "key2": "value2",
    "key3": "value3"
}
```
# ハマリポイント
沼ったポイントを紹介します。
## SyntaxError: Unexpected token   in JSON at position XXXX
package.json内の記述に無駄な半角やインデントのズレがあると出るエラーです。(はまったぁーこれ。)
下記のサイトで全ファイルを修正して、完璧なJSONです、と言われるまで修正すれば解消します。

[JSON Pretty Linter Ver3](https://lab.syncer.jp/Tool/JSON-Viewer/) 

## node_moduleがインストールされない①
これも同じで、`package.json`に余計な空白が1つでもあろうものなら、インストールされません。エラーが出ればまだ気付けるのですが、誰も何もお知らせしてくれず、ひっそりとLambda上にインストールされない事実だけ残ります。JSONさんってこんなにも気厳しいんですね、、、。

## node_moduleがインストールされない②
`package.json`にぱっと見正しい記述なのに、インストールがされていないこともありました、、、。
たまーにある、エディタの半角/全角空白チェックに検知されないなぞの空白的なやーつ？(textからコピペしたりするとおきることある)なんてことも考えましたが、原因はわからず、、、。
強制的な解決策として、一旦インストールしたいパッケージを削除して、`$ amplify push`。その後、再度、`package.json`に追加して再プッシュで解決しました。

## amplify pushで更新したはずなのにGUIで見ると反映されていない
これは気をつけないといけないうっかりミスについてです。

GUIでLambda関数を見ながら作業することはよくありますが、基本的にamplify pushで関数を更新しても、リロードしないとGUI上のLambda関数は更新されません。

この状況で、うっかりGUIから関数を触って保存してしまうと更新された情報に上書きされるため、更新分がなかったことになってしまいます。地味に無駄な時間を過ごすことになるので気をつけましょう。

# index.jsの編集サイクル
push後は、GUIの`index.js`を編集してテスト→問題なければ、ローカルの`index.js`に内容をコピペ→`$ amplify push`して履歴を残す、というやり方がスムーズかと思います。

# おわりに
更新のフローとしては、ローカル上Lambda関数を編集した上で、`$ amplify push`して更新する流れになります。これでlambda関数がgit管理も行えるようになるので、Lambda関数がかなり使いやすくなるかと思います。

# 参考
[AWS CloudFormation AWS::Lambda::Function(公式ドキュメント)](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html)
[AWS CloudFormation AWS::Lambda::EventSourceMapping(公式ドキュメント)](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-eventsourcemapping.html#cfn-lambda-eventsourcemapping-functionname)

# 関連記事
[AWS amplify フレームワークの使い方Part1〜Auth設定編〜](https://qiita.com/too/items/fc961283dcbef3aafdeb)
[AWS Amplify フレームワークの使い方Part2〜Auth実践編〜](https://qiita.com/too/items/54992bb871fc1a2ab101)
[AWS Amplify フレームワークの使い方Part3〜API設定編〜](https://qiita.com/too/items/c0ce14d16772b9f71223)
[AWS Amplify フレームワークの使い方Part4〜API実践編〜](https://qiita.com/too/items/f9078803ea394c35df7d)
[AWS Amplify フレームワークの使い方Part5〜GraphQL Transform @model編〜](https://qiita.com/too/items/ab6b313da9f9e34be4a7)
[AWS Amplify フレームワークの使い方Part6〜GraphQL Transform @auth編〜]
(https://qiita.com/too/items/fae2879ea36f00c3ae10)
[AWS Amplify フレームワークの使い方Part7〜GraphQL Transform @key編〜]
(https://qiita.com/too/items/cb1dfb4f44536a3e9855)
[AWS Amplify フレームワークの使い方Part8〜GraphQL Transform @connection編〜](https://qiita.com/too/items/c77f1e5487d2497b5061)
[AWS Amplify フレームワークの使い方Part10〜Storage編〜](https://qiita.com/too/items/361bc10b6d27f133e9f8)
[AWS Amplify フレームワークの使い方Part11〜Function 権限管理編〜](https://qiita.com/too/items/b34cbfd7e96a01e33f23)
[AWS Amplify フレームワークの使い方Part12〜ENV編〜](https://qiita.com/too/items/5c1e28cf95fc6229547e)
[AWS Amplify フレームワークの使い方Part13〜Auth 設定更新編〜]
(https://qiita.com/too/items/52f35860bcb5bdf5e667)
[AWS Amplify フレームワークの使い方Part14〜Lambda レイヤー編〜]
(https://qiita.com/too/items/54de781085bd9a3a66d0)