AWS × SERVERLESS v1.0を触ってみた

# 実施環境
- SERVERLESS 1.0.0-rc.1
- OSX

1ヶ月前くらいに[SERVERLESSフレームワーク](https://serverless.com/)のv1.0betaが出たと聞いて、触ろう触ろうと思い今日触ってみたらRCになってました。正式リリースは近いのかも。

# セットアップ
必要なのは以下。
- AWSアカウント
- node
- aws-cli
- serverless v1.0

以下は、インストール方法です。すでに入っている人は飛ばしてください。AWSのアカウントは、適当なユーザ作って、Administratorポリシーをアタッチしておいてください。Administratorじゃなくていいじゃんと思いますが、現状ではAdministratorじゃないと動かないみたいです。正式リリース時に必要なポリシーを列挙してくれることを期待。

## Macの方
### nodeインストール
下記手順に従ってインストール
http://www.websuppli.com/nodejs/424/

### aws-cliインストール
※Python 2.6.5以降必要。入ってなければインストール
1. curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
2. sudo python get-pip.py
3. sudo pip install awscli

共通の準備もやってくださいね。

## Windowsの方
動作試してません。

### nodeインストール
nodistを入れます。
1. https://github.com/marcelklehr/nodist/releases/tag/v0.7.2からダウンロード、インストール。
2. パス通す（設定されてたらスキップ）
3. 環境変数のPathにbinまでのパス
4. 環境変数のNODIST_PREFIXを新規追加しでnodistまでのパス
5. コマンドラインでnodist update実行

### aws-cliインストール
https://aws.amazon.com/jp/cli/
こっからインストーラ落としてインストール。


## 共通準備
### 確認
下記コマンドをターミナルで叩いて反応すれば大丈夫。

- node -v
- npm -v
- aws --version

### SERVERLESSインストール
僕の環境では、npm install -g serverlessでRC版がインストールされました。されない場合は、npm install -g serverless@betaかな。serverless -versionを叩いてv1系になってれば大丈夫だと思います。

ちなみにserverlessコマンドのエイリアスは下記。

- sls
- slss

僕は基本的に1つ目使います。

### awsアカウントの設定
ターミナルで、aws configureを実行。作ったユーザの情報を入力してください。


# SERVERLESSフレームワーク触る
v0系との違いも書きたいですが、後で加筆します。とりあえず、v1系の話をします。

## 雛形の作成
ターミナルで下記を行ってください。

```bash
$ mkdir slstest
$ cd slstest
$ sls create --template aws-nodejs
```

これをすることによって、サービスの雛形が作成されます。SERVERLESSでは1つのAPI Gatewayあたり1つのサービスが対応しているようです。

```bash
$ sls create --template [aws-nodejs | aws-python | aws-java-maven | aws-java-gradle]
```

このコマンドでサービスを作ります。Node.jsやpythonやJavaが選べるみたいです。Lambdaが対応している言語ですね。今回はNode.jsを使います。

これで下記のような構成になりました。v0系とは異なり、非常にシンプルな構成になっています。0系ではAWSで利用する前提でしたが、v1系ではAzureやGCPなどでも使えるようにするために、シンプルで汎用的な構成になっているみたいです。

```
slstest
|-- event.json                                                                                                                                 
|-- handler.js                                                                                                                                 
`-- serverless.yml  
```

- event.json：invoke（ローカルでAPIを叩く）時に利用します。APIに渡すJSONパラメータですね。
- handler.js：APIの処理を書きます。パラメータなどの情報がeventオブジェクトに詰めて渡されます。それをうまくパースして、処理を行い、cb関数の第2引数にレスポンスのJSONを渡してあげます。これはAWSのLambdaにあたります。
- serverless.yml：API Gatewayの設定を書きます。APIの名前や、どのようなFunctionを作るか、ステージングなどの設定を書きます。v0系でのs-function.jsonに近いです。個人的にはYAMLなのが辛い。そのうちJSONにも対応するってどこかに書いてありました。はよ。

## API名の変更、ステージング、functionの作成
serverless.ymlを編集します。せっかくなのでREST APIっぽくします。YAMLはインデントが命なので、気をつけてください。

```yaml:serverless.yml
# 不要なコメントは消しています
service: apitest # API Gatewayの名前

provider:
  name: aws
  runtime: nodejs4.3
  stage: dev # ステージング名
  region: us-east-1

# 下記コメントは元々書いてあるが、間違っている。
# 下記情報はproviderに書かないといけない。
# you can overwrite defaults here
#defaults:
#  stage: dev
#  region: us-east-1

functions:
  # Lambdaの名前、わかりやすいのをつけるとよい
  getuser:
    # handler.jsのuserモジュールが呼ばれる
    handler: handler.user
    events:
      # endpointの作成
      - http:
          # pathには例えば、v1/api/userとかもできる
          path: user
          method: get
          cors: true
  # このように書くとLambdaが2つできる
  postuser:
    handler: handler.user
    events:
      - http:
          path: user
          method: post
          cors: true

# こんな風にも書ける
# functions:
#   user:
#     handler: handler.user
#     events:
#       - http:
#           path: user
#           method: get
#           cors: true
#       - http:
#           path: user
#           method: post
#           cors: true
```

大体はコード内のコメントを読んでもらえればわかると思います。v0ではコマンドを叩いてfunctionを作成していましたが、v1ではserverless.ymlに記述します。

次にhandler.jsを修正します。

```js:handler.js
'use strict';

// helloになっているところをuserに変更
module.exports.user = (event, context, cb) => cb(null,
  { message: 'Go Serverless v1.0! Your function executed successfully!', event }
);
```

モジュールの中にAPIにさせたい処理を書いて、cbにレスポンスを返してあげればAPIの完成です。

## デプロイ
めちゃくちゃ簡単です。

```bash
$ sls deploy
Serverless: Uploading service .zip file to S3...                                                                                               
Serverless: Updating Stack...                                                                                                                  
Serverless: Checking Stack update progress...                                                                                                  
.......................................                                                                                                        
Serverless: Stack update finished...                                                                                                           
                                                                                                                                               
Service Information                                                                                                                            
service: apitest                                                                                                                               
stage: dev                                                                                                                                     
region: us-east-1                                                                                                                              
endpoints:                                                                                                                                     
  GET - https://hogehoge.execute-api.us-east-1.amazonaws.com/dev/user                                                                        
  POST - https://hogehoge.execute-api.us-east-1.amazonaws.com/dev/user                                                                       
functions:                                                                                                                                     
  apitest-dev-getuser: arn:aws:lambda:us-east-1:0000000000000:function:apitest-dev-getuser                                                      
  apitest-dev-postuser: arn:aws:lambda:us-east-1:0000000000000:function:apitest-dev-postuser
```

これでデプロイができました。AWSコンソールのAPI Gatewayを見てみると、こんな感じになっているかと。
<img width="1696" alt="スクリーンショット 2016-09-08 0.15.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/74853/b9a99c36-9222-1c05-f28b-e430184db8d0.png">

## 疎通確認
GETは、ブラウザからendpointにアクセスしてみてください。cbの第2引数のオブジェクトが表示されているはずです。試しに、URLに?id=10をつけてみてください。v0系までは、GETの場合リクエストテンプレートなどを設定しなければ、eventにパラメータが渡せなかったのですが、v1からは何もしなくても、eventオブジェクトの終わりの方のqueryに格納されていることが確認できるかと思います。これは、SERVERLESSフレームワークがデプロイ時にAPI Gatewayの統合リクエストの本文マッピングテンプレートにマッピングコードを記載してくれているためです。初心者に非常に優しいですね。v0系のときは、この部分に非常に泣かされました。

POSTは、GatewayのPOSTを押して、テストのリクエスト本文に適当なオブジェクトを渡してください。レスポンスが返ってきていれば大丈夫です。

# まとめ
「非常に簡単にWebAPIが作れるSERVERLESSフレームワークのv1の触ってみた」でした。v0との違いや、正式版がリリースされればそれの触ってみたも書いてみたいと思います。

また、業務でも使いそうなので、その際のハマったことなども記事にしていきたいと思います。

おわり。