JAWS Frameworkを使ってお手軽にLambda+API GatewayでHelloWorldするメモ


はじめに
=======

昨今 **AWSでServerlessアーキテクチャ！**という響きが中々素敵な感じになってきました。慣れないとやや面倒な感じですが、 **メリットも非常に大きい**ので今後作られるシステムはこのようなアーキテクチャになることも増えると思います。

**だがしかし！ めんどくさいぞ！！**  **API Gateway とか Lambda とか IAM Roleとか煩雑すぎんぞ！！！**
と感じる方も多いと思います（それ私）。
「そういうのは自動化してしまえばいいんだよ」というのが王道で、そして既にいい感じにできつつある **[JAWS Framework](https://github.com/jaws-framework/JAWS)**というものがあります。

今回はそのJAWS Frameworkを使って Hello World を表示するまでの手順をメモしたものです。

準備するもの
---------

* AWS アカウント： 要IAMユーザが作成できる権限
* npm が動く環境

今回の環境・Version
-----------

* npm 2.12.1
	* jaws-framework@1.3.3

手順
=======
基本は https://github.com/jaws-framework/JAWS の *Quick Start* に書かれている手順に従うだけです。

概ね以下の手順で可能です。

* JAWS実行用IAMユーザの作成
* JAWS Frameworkのインストール
* プロジェクト作成
* デプロイと確認

JAWS実行用IAMユーザの作成
------------
JAWSから AWSにAPIアクセスするための「IAMユーザ」を作成します。
名前を **jaws-admin** とするとします。
この **jaws-admin**に **AdministratorAccess** という超強力な権限を付与します。

ただし、これは面倒な手順を省くためのやや危ない設定で本番環境ではもう少し別のものにした方が良いそうです。
https://github.com/jaws-framework/JAWS/blob/master/docs/account_setup.md

まあ、HelloWorldするくらいならとりあえず問題無いです。

※ 本当はGroupを作って、、、とした方が良いですが

### 手順
* AWS Web Consoleにログインして、IAMサービスを開きます
* [ユーザ]->[新規ユーザの作成] で **jaws-admin** を作成します。その時の **「アクセスキー」「Secret」** をコピペでメモしておきます。
* 作成されたユーザを選択して、[ポリシーのアタッチ]->[`AdministratorAccess`] をアタッチします
* 自分のpcの `~/.aws/credentials` に以下を追記します

```
[jaws-admin]
aws_access_key_id = <<アクセスキー>>
aws_secret_access_key = <<Secret>>
```

### 手順： AWS CLI
CLI不慣れなのですがCLIでやるとしたらこんな感じかと思います。

```text:cmd
% aws iam create-user --user-name jaws-admin
% aws iam create-access-key --user-name jaws-admin  
# -> 結果をメモっておく -> ~/.aws/credentials に書く

% aws iam attach-user-policy --user-name jaws-admin --policy-arn arn:aws:iam::aws:policy/AdministratorAccess
```

JAWS Frameworkのインストール
------------
簡単です。

```
% npm install jaws-framework -g
```

プロジェクト作成
------------

* Project名: `MyHello` 
* Domain名： my.hello.com
	* APIのドメイン名とは基本的に関係ない（たぶん…）ので適当でOKですが、Bucket名作成に使われるのでUniqueな文字列が望ましいと思います
* Region: 東京(ap-northeast-1)
* Aws profile: jaws-admin (さっき作ったIAMユーザ)

```text:cmd
% jaws project create                                                                                                    
       ____   _____  __      __  _________
      |    | /  _  \/  \    /  \/   _____/
      |    |/  /_\  \   \/\/   /\_____  \
  /\__|    /    |    \        / /        \
  \________\____|__  /\__/\__/ /_________/ v1 (BETA)

       *** The Server-Less Framework ***

JAWS: Enter a project name:  (jaws-4yV6HyNbg) MyHello
JAWS: Enter a project domain (You can change this at any time:   (myapp.com) my.hello.com
JAWS: Enter an email to use for AWS alarms:  (you@yourapp.com)
JAWS: Enter a stage for this project:  (dev)
JAWS: Select a region for your project:
    us-east-1
    us-west-2
    eu-west-1
  > ap-northeast-1
JAWS: Select an AWS profile for your project:
    default
  > jaws-admin
JAWS: Creating CloudFormation Stack for your new project (~5 mins)...      ← 数分待ちます
JAWS: Preparing your runtime and installing jaws-core module...
npm WARN package.json MyHello@0.0.1 No license field.
jaws-core-js@0.0.2 node_modules/jaws-core-js
└── dotenv@1.2.0
JAWS: Your project "MyHello" has been successfully created in the current directory.
```

面白いのが、Region選択でCUIで選択するUIが表示されるところですね。初心者に優しいです。

正常に終了すると、以下のリソースが作成されるようです。

* S3 Bucket: jaws.dev.apnortheast1.my.hello.com
* IAM Group２つ
* IAM Role ２つ

AWS Module(AWSM) の作成
-------------
AWS Moduleというのは JAWS Frameworkの造語だと思いますが、基本この単位で(API<->Lambda)の管理を行うようです。

`greetings/hello` というのを作ってみます。

```text:cmd
% cd MyHello
% jaws module create greetings hello                                                                             
JAWS: Successfully created greetings/hello
```

すると `aws_modules` Directoryの下に `greetings/hello` というのが作成されます。
基本的にApplicationは `greetings/hello/index.js` に書いていくことになるようです。
Local環境でテスト可能になるように設計されていて、

```text:cmd
% cd aws_modules/greetings/hello
% jaws run
JAWS: {"message":"Your JAWS lambda executed successfully!"}
```

というような感じで動作確認できます。
こういうのが素晴らしいですよね。

デプロイ
------

`jaws dash` コマンドでインタラクティブなデプロイができます。
※（インタラクティブではない `jaws deploy` というのもある）。

```text:cmd
% jaws dash
JAWS: Dashboard for project "MyHello"
 -------------------------------------------
 Project Summary
 -------------------------------------------
    Stages:
       dev ap-northeast-1
    Lambdas: 1
    Endpoints: 1
 -------------------------------------------
 Select Resources To Deploy
 -------------------------------------------
    greetings/hello
      L) lGreetingsHello                   ← ここで <Enter> と <カーソル下>
      E) /greetings/hello - GET            ← ここで <Enter> と <カーソル下>
    - - - - -
  >   Deploy Selected -->                  ← ここで <Enter>!!
  
```

ここのUIが最初わからなかった（＾＾； のですが、

「 **どのType(Lambda or API)をデプロイするか選択**」→「 **選択されているものをデプロイ**」

という流れなので、２つをEnterで選択して、最後に一番下の Deploy を EnterすればOKでした。

すると

```
... 略
JAWS: Endpoint Deployer:  Endpoints for stage "dev" successfully deployed to API Gateway in the region "ap-northeast-1". Access them @ https://zxbv75oalh.execute-api.ap-northeast-1.amazonaws.com/dev/
JAWS: -------------------------------------------
JAWS:  Dashboard:  Deployments Completed
JAWS: -------------------------------------------
```

という感じでログが流れてくるので、最後に表示されているURL

`https://zxbv75oalh.execute-api.ap-northeast-1.amazonaws.com/dev/`

をBaseURLとして、今回であれば


`https://zxbv75oalh.execute-api.ap-northeast-1.amazonaws.com/dev/greetings/hello`

にアクセスすると、

```
% curl https://zxbv75oalh.execute-api.ap-northeast-1.amazonaws.com/dev/greetings/hello
{"message":"Your JAWS lambda executed successfully!"}
```

と表示されました。
やった！

HelloWorldじゃないじゃんよ
---------
あ、 **HelloWorldじゃないじゃん** ということで修正しましょう。

### コードの修正

```
% vi aws_modules/greetings/hello/index.js
```

として、

```javascript:index.js
/**
 * AWS Module: Action: Modularized Code
 */

// Export For Lambda Handler
module.exports.run = function(event, context, cb) {
  return cb(null, action());
};

// Your Code
var action = function() {
  return {message: 'Hello World!'};      // modify this!!
};
```

最後の部分を `Hello World!` に変更します。

### 再度デプロイ
今度は インタラクティブじゃないデプロイを試してみます。
その場合、AWSMのDirectoryに移動する必要があるようです（引数でもいけるのかな？）。

```
% cd aws_modules/greetings/hello
% jaws deploy lambda
```

とすると、

```
... 略 JAWS: Lambda Deployer:  Uploading lGreetingsHello to jaws.dev.apnortheast1.my.hello.com
JAWS: Running CloudFormation lambda deploy...
JAWS: Lambda Deployer:  Done deploying lambdas in ap-northeast-1
JAWS: Lambda Deployer:  Successfully deployed lambdas to the requested regions!
```

デプロイ成功のメッセージが表示されます。

で、先ほどのURLを叩いてみると

```
% curl https://zxbv75oalh.execute-api.ap-northeast-1.amazonaws.com/dev/greetings/hello
{"message":"Hello World!"}
```

ちゃんと `Hello World!` になってます！


余談
-------
stage/region などの構造は https://github.com/jaws-framework/JAWS/blob/master/docs/deployment.md に書いてありますが、別々に管理・デプロイできるようにと考慮されています。
色々ドキュメントも整備されてきているようです。

さいごに
=====
JAWS Frameworkは開発スピードも結構速そうですし、まだまだ互換性のない変更とかも多そうですが（この分野はAWS自体が発展途上ですし）、 **AWSM(AWS-Modules)** などはRubyGemsのような再利用性を持つと思いますし、
「Ruby界のRails」のように「AWS Serverless界のJAWS」と成長していく可能性が高そうです。