KONGでニフクラスクリプトもチームもマネジメントする話

この記事は[富士通クラウドテクノロジーズ Advent Calendar 2017](https://qiita.com/advent-calendar/2017/fjct)の12日目の投稿です。

11日目は@yaaamaaaguuuの[今年一年間の知見](http://yaaamaaaguuu.hatenablog.com/entry/2017/12/11/112356)に関する記事でした。私の過去10年間の知見よりも多くて正直焦りました。

#はじめに

私はニフクラのサービス開発エンジニアとして携わっていますが、様々な内外的要因とタイミングとあれやこれやあり今年の7月からマネージャーというポジションで仕事しています。
マネージャーであるからには、言いづらいけど言わないといけないこともはっきりとチームメンバーに伝える必要があります。しかし新米へっぽこマネージャーは~~ひとくせもふたくせもある~~優秀なエンジニアのチームメンバを相手にいつも四苦八苦してしまいます。

今回は私のようなヘタレでもチームメンバーに伝えたい事を伝えらるようなお話です。

#手段

エンジニアチームの話なのでコミュニケーションにもエンジニアリングを極力用いるのがいいでしょう。今回はニフクラのサーバーレスサービスの[スクリプト](https://cloud.nifty.com/service/script.htm)とオープンソースで豊富なプラグインが魅力的なAPIGateWay基盤である[KONG](https://getkong.org/)を活用して言いたいことを言ってみようと思います。やっとタイトル通りの記事っぽくなってきましたね。

#環境

* Docker version 17.11.0-ce
* KONG 0.11.2
* Postgresql 9.4
* ニフクラスクリプト

# 導入

まずは`KONG`とそのデータストアである`Postgresql9.4`を[マニュアル](https://getkong.org/install/docker/?_ga=2.6632050.1952266292.1512620076-854707353.1512397278)を基にDockerで構築します。

## Postgresql構築〜起動
```bash
$ docker run -d --name kong-database \
              -p 5432:5432 \
              -e "POSTGRES_USER=kong" \
              -e "POSTGRES_DB=kong" \
              postgres:9.4
```

## スキーマなどをマイグレーション
```bash
$ docker run --rm \
    --link kong-database:kong-database \
    -e "KONG_DATABASE=postgres" \
    -e "KONG_PG_HOST=kong-database" \
    -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
    kong:latest kong migrations up
```

## KONG構築〜起動
```bash
$ docker run -d --name kong \
    --link kong-database:kong-database \
    -e "KONG_DATABASE=postgres" \
    -e "KONG_PG_HOST=kong-database" \
    -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
    -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \
    -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \
    -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \
    -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \
    -p 8000:8000 \
    -p 8443:8443 \
    -p 8001:8001 \
    -p 8444:8444 \
    kong:latest
```
`docker ps -a` をして確認してみましょう。`kong`と`kong-database`がUPしてればOKです。


## スクリプト作成

今回は[クイックスタート](https://cloud.nifty.com/guide/script/quickstart.htm)にあるスクリプトをそのまま使ってみようと思います。
上記ページに従ってスクリプトを作成します。

## KONGにnifcloud-script pluginを配備して再イメージ化

KONGはデフォルトで[aws-lambda](https://getkong.org/plugins/aws-lambda/)という公式プラグインがありますが、残念ながらニフクラスクリプト用のプラグインはありません。
なので新規にプラグインを作成してインストールさせる必要があります。
プラグインの作成にあたっては公式の[Plugin development - Introduction](https://getkong.org/docs/0.11.x/plugin-development/)を読みながら作成します。
今回は他のlua-nginx-moduleを参考に[こちら](https://github.com/Ken-Moriizumi/kong-nifcloud-script-sample)を作りました。
配備後はcommitしておきます。

```bash

$ git clone https://github.com/Ken-Moriizumi/kong-nifcloud-script-sample.git nifcloud-script
$ docker cp nifcloud-script kong:/usr/local/share/lua/5.1/kong/plugins/
$ docker commit kong kong:nifcloud
``` 

## KONGへプラグインをインストール

上とほぼ同じですが`KONG_LOG_LEVEL`と`KONG_CUSTOM_PLUGINS`という環境変数が追加になっています。
また、立ち上げるのは先程commitしたイメージから立ち上げます。

```bash

$ docker run -d --name kong \
    --link kong-database:kong-database \
    -e "KONG_DATABASE=postgres" \
    -e "KONG_PG_HOST=kong-database" \
    -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
    -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \
    -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \
    -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \
    -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \
    -e "KONG_LOG_LEVEL=debug"  \
    -e "KONG_CUSTOM_PLUGINS=nifcloud-script"  \
    -p 8000:8000 \
    -p 8443:8443 \
    -p 8001:8001 \
    -p 8444:8444 \
    kong:nifcloud
```
立ち上がったら`docker logs kong`を実行して`nifcloud-script`プラグインがロードされていることを確認します。
環境構築はこれで完了です。

# 実行

## API作成

KONGのマニュアルに従って新規APIを作成します。`upstream_url`は通常転送先のURLを設定するのですが、今回は`aws-lambda`同様プラグイン内で強制的にニフクラスクリプトに転送するのでなんでも構いません。

```bash
curl -i -X POST \
  --url http://localhost:8001/apis/ \
  --data 'name=nifcloud-api' \
  --data 'hosts=nifcloud' \
  --data 'upstream_url=http://nifcloud.com'
```

## nifcloud-script プラグイン有効化

次に上記で作成したAPIに対してnifcloud-scriptプラグインを有効化します。
この時アクセスキーとシークレットキーを指定します。

```bash

curl -X POST http://localhost:8001/apis/nifcloud-api/plugins \
    --data "name=nifcloud-script" \
    --data-urlencode "config.access_key=<nifcloud-access-key>" \
    --data-urlencode "config.secret_key=<nifcloud-secret-key>" \
    --data "config.region=jp-east-1" \
    --data "config.function_name=dummy"
```

## クライアント作成〜実行

これでKONGを使用したニフクラスクリプトのAPIGateWayができました。
curlを使ってAPIGateWay経由でニフクラスクリプトを叩いてみます。

```bash
$ curl -i -X POST  --url http://${KONG_HOSTNAME}:8000/${EXEC_SCRIPT_NAME}   --header 'Host: nifcloud'

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Connection: keep-alive
ETag: W/"27a-Wjd06nqimAWgaLmPnQYR1T3HGno"
Content-Length: 634
Access-Control-Allow-Origin: *
Date: Thu, 07 Dec 2017 07:25:36 GMT
Connection: keep-alive
Server: kong/0.11.2

<?xml version="1.0"?><ExecuteScriptResponse><requestId>5f08a68c-ea04-41e6-9374-615059356498</requestId><ExecuteScriptResult><Result><console><log/><err/></console><ResponseStatus>200</ResponseStatus><ScriptIdentifier>test1.js</ScriptIdentifier><RequestQuery><![CDATA[{"name":"merryChristmasAndHappyNewYear!!"}]]></RequestQuery><RequestBody><![CDATA[{}]]></RequestBody><ResponseHeader><![CDATA[{"Content-Type":"text/plain"}]]></ResponseHeader><RequestHeader><![CDATA[{}]]></RequestHeader><ResponseData><![CDATA[merryChristmasAndHappyNewYear!!]]></ResponseData><Status>200</Status></Result></ExecuteScriptResult></ExecuteScriptResponse>c
```
`KONG_HOSTNAME` はAPIGateWayを構築したドメインもしくはIPアドレス、
`EXEC_SCRIPT_NAME` は上で保存したニフクラのスクリプト名を設定します。


無事200応答が帰ってきましたが、これではさすがのエンジニアもちょっと何言ってるのかわかりません。
なので簡単なクライアントを作りました。

```ruby:api-gateway-client.rb
#!/bin/ruby

require "httpclient"
require "rexml/document"

client = HTTPClient.new

body = ""
header = {
   "Host" => "nifcloud"
}

res = client.post(
   "http://#{ENV['KONG_HOSTNAME']}:8000/#{ENV['EXEC_SCRIPT_NAME']}",
   body,
   header
)

doc = REXML::Document.new res.body

puts doc.elements['ExecuteScriptResponse/ExecuteScriptResult/Result/ResponseData'].text
```
```
# bundle exec ruby api-gateway-client.rb
merryChristmasAndHappyNewYear!!
```

これでシンプルかつ明確にみんなへクリスマスと新年の挨拶をすることができました。
挨拶はマネジメントというよりそもそもコミュニケーションの基本ですし、lowerCamelにすることでちょっと親密なprivate感も醸せます。TPOに応じて使い分けましょう。
難点といえば自作プラグインの作りが少々雑なため他のメッセージを送信できないことくらいでしょうか。

# おわりに
今回は必要であったためプラグインを作成しましたが、KONGはデフォルトで豊富なプラグインが同梱されているため、ライトな用途であればほぼそのまま現場に導入可能な印象を受けました。
ただJavaを一切使っていないのに出力をlowerCamelにしてしまったことは反省しています。
是非みなさんもKONGを使ったコミュニケーションでAPIマネジメントだけでなくチームのマネジメントをしてみましょう。

あしたは@tunakyonnの「[Unity WebGLをmBaaSで使ってみた](https://qiita.com/tunakyonn/items/ef38124134cabae1d413)」です。お楽しみに！