🌸はじめまして AWS SAM

AWS SAM を使ってみたので、記録用に


## プロジェクト作成

-r：Lambdaのランタイム
-n：プロジェクト名

次なにやればいいのかを案内してくれる、優しい

```bash
$ sam init -r nodejs -n sam-test
[+] Initializing project structure...

Project generated: ./sam-test

Steps you can take next within the project folder
===================================================
[*] Invoke Function: sam local invoke HelloWorldFunction --event event.json
[*] Start API Gateway locally: sam local start-api

Read sam-test/README.md for further instructions

[*] Project initialization is now complete
```

## ディレクトリ構成

`sam init` でできたやつ

```bash
.
├── README.md
├── event.json
├── hello-world
│   ├── app.js
│   ├── package.json
│   └── tests
│       └── unit
│           └── test-handler.js
└── template.yaml
```

## app.js 見てみる

```javascript:app.js
// const axios = require('axios')
// const url = 'http://checkip.amazonaws.com/';
let response;

/**
 *
 * Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format
 * @param {Object} event - API Gateway Lambda Proxy Input Format
 *
 * Context doc: https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html 
 * @param {Object} context
 *
 * Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html
 * @returns {Object} object - API Gateway Lambda Proxy Output Format
 * 
 */
exports.lambdaHandler = async (event, context) => {
    try {
        // const ret = await axios(url);
        response = {
            'statusCode': 200,
            'body': JSON.stringify({
                message: 'hello world',
                // location: ret.data.trim()
            })
        }
    } catch (err) {
        console.log(err);
        return err;
    }

    return response
};
```

## npm install

いつやればいいかわからないけどやっておく

```bash
cd hello-world/
npm install
```

## lambda確認

Lambda関数を実行する

- 使いそうなオプション
    - --event：eventデータが渡せる（json形式）
    - --env-vars：環境変数を使うとき（json形式）

```bash
$ sam local invoke HelloWorldFunction
yyyy-MM-dd hh:mm:ss Invoking app.lambdaHandler (nodejs10.x)
yyyy-MM-dd hh:mm:ss Found credentials in shared credentials file: ~/.aws/credentials

Fetching lambci/lambda:nodejs10.x Docker container image......
yyyy-MM-dd hh:mm:ss Mounting /hoge/fuga/piyo/sam-test/hello-world as /var/task:ro,delegated inside runtime container
START RequestId: 52fdfc07-2182-154f-163f-5f0f9a621d72 Version: $LATEST
END RequestId: 52fdfc07-2182-154f-163f-5f0f9a621d72
REPORT RequestId: 52fdfc07-2182-154f-163f-5f0f9a621d72	Duration: 11.66 ms	Billed Duration: 100 ms	Memory Size: 128 MB	Max Memory Used: 42 MB	
{"statusCode":200,"body":"{\"message\":\"hello world\"}"}
```

レスポンスが帰ってきた

## コメントアウトを外した

ipアドレスを表示するAPIを呼ぶらしい

```javascript
const axios = require('axios')
const url = 'http://checkip.amazonaws.com/';
let response;

/**
 *
 * Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format
 * @param {Object} event - API Gateway Lambda Proxy Input Format
 *
 * Context doc: https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html 
 * @param {Object} context
 *
 * Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html
 * @returns {Object} object - API Gateway Lambda Proxy Output Format
 * 
 */
exports.lambdaHandler = async (event, context) => {
    try {
        const ret = await axios(url);
        response = {
            'statusCode': 200,
            'body': JSON.stringify({
                message: 'hello world',
                location: ret.data.trim()
            })
        }
    } catch (err) {
        console.log(err);
        return err;
    }

    return response
};
```

## lambda確認

```bash
$ sam local invoke HelloWorldFunction
~
略
~
{"statusCode":200,"body":"{\"message\":\"hello world\",\"location\":\"123.456.789.123\"}"}
```

## local api 起動

ついにローカルにapi gatewayを

```bash
$ sam local start-api
yyyy-MM-dd hh:mm:ss Mounting HelloWorldFunction at http://127.0.0.1:3000/hello [GET]
yyyy-MM-dd hh:mm:ss You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template
yyyy-MM-dd hh:mm:ss  * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)
```

## curl

```bash
$ curl http://127.0.0.1:3000/hello
{"message":"hello world","location":"123.456.789.123"}
```

結果が帰ってきたので、ローカル開発環境は整った

## deploy



### s3バケット作成

```bash
$ aws s3 mb s3://sam-test-bucket
make_bucket: s3://sam-test-bucket/
```

### パッケージングしてデプロイ

```bash
$ sam package \
    --output-template-file packaged.yaml \
    --s3-bucket sam-test-bucket
$ sam deploy \
    --template-file packaged.yaml \
    --stack-name sam-test-stack \
    --capabilities CAPABILITY_IAM
```

### apigateway エンドポイント確認

```bash
$ aws cloudformation describe-stacks \
    --stack-name sam-test \
    --query 'Stacks[].Outputs[?OutputKey==`HelloWorldApi`]' \
    --output table
--------------------------------------------------------------------------------------------------------------------------------------------------------
|                                                                    DescribeStacks                                                                    |
+-------------------------------------------------------------------+-----------------+----------------------------------------------------------------+
|                            Description                            |    OutputKey    |                          OutputValue                           |
+-------------------------------------------------------------------+-----------------+----------------------------------------------------------------+
|  API Gateway endpoint URL for Prod stage for Hello World function |  HelloWorldApi  |  https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/  |
+-------------------------------------------------------------------+-----------------+----------------------------------------------------------------+
```

```bash
$ curl https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/
{"message":"hello world","location":"123.456.789.123"}
```

## 感想

チュートリアルはできたけど、ここからが難しいとおもいました
cloudFormationを学べば良い感じに使いこなせるのかなあ