[ChatOps]Opsidianとdroneを使って、SlackからAWSへデプロイしてみた

#はじめに

　先日[【drone.ioを使ってCI環境を構築したので、色々整理してみた___<基本編>】](http://qiita.com/jobbin/items/e45ded6ae6972fed56dc)を書きました。タイトルは揃っていませんが、今回はそれの続編で、**Slackからデプロイコマンドを打って、droneがおとなしく指示通りにやってくれる**方法について書きます、。

# SlackでのChatOps

　(AWS寄りになってしまいますが)Slackを使って、ChatOpsをする時に、下記API Gatewayを使うパータンがよくあるのではないかと思います。もちろん、SlackからHubotを呼ぶのもあります。
<img width="816" alt="スクリーンショット 0029-08-01 20.56.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/117156/71522730-1138-acc2-329e-78f4522058e2.png">
　ちなみに、Slack → API Gateway → Lambdaにご興味がある方は、下記、昨年私が書いた記事を見て頂ければと思います。
[【Slack de AWS CLI】SlackのChannelからAWS CLIを実行できるようにしてみました!](http://qiita.com/jobbin/items/d8b32be94593a202c23b)

　元々、自分もAPI Gatewayを使うと考えていました...が、つい先日(夜眠れない日)に、「なんか面白いツールないかな」とSlackのインテグレーションを漁っていて、偶然に見つかったのはOpsidianというツールです。正確的には**Opsidian.ai**という名で、<font color="red">**ai**</font>が付いています...よ。Opsidian.aiにご興味がある方は、是非[Opsidian.aiの公式ページ](http://opsidian.ai/)を見てください。面白いことをいっぱい書いてあります。
※ 私はあまりにも感動しすぎて、めちゃくちゃの英語でこのツールの親である**ewadwornikowska**さんにメッセージを送りました。

　話を戻りますと、最終的にAPI Gatewayを辞めて、こんな感じにしました。

<img width="794" alt="スクリーンショット 0029-08-01 21.00.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/117156/23637910-c88e-93eb-00d0-cff69b0ee892.png">
　一見、API GatewayのかわりにOpsidianを使っているだけじゃんというツッコミもありますが、個人的にはOpsidianのほうが結構楽だと思います。
　API Gatewayもそれなりの使い方がありますので、ChatOpsをやる時に、選択肢が１つ増えたという捉え方のほうがいいと思っています。

　API GatewayとOpsidianを簡単に比べてみますと、

　1. API Gatewayの設定より、Opsidianのほいうが楽
　2. API Gatewayを利用する場合、認証とか入れないと、エンドポイントがバレたら、だれでも叩けるようになる。一方、OpsidianはSlackに設定したアクセスキーでLambdaをinvokeするので、安全(?)かも
　3. だれがLambdaを呼べるかの処理は、Opsidian側で制御可能。
　4. Opsidianって、ただLambdaをinvokeするだけではなく、AWSリソースのモニタリングもできる。
　※ 私個人的な意見にはなりますが、<font color="red">OpsidianってChatOpsの神ツール</font>だと思っています。

# SlackからAWS ECRにイメージプッシュまでやってみる
　流れ的には、こんな感じになります。
　<font color="red">**Slack → Opsidian → Lambda → GitHub → drone → AWS ECR**</font>
　何をやっているかとざっくり説明しますと、
　1: Slackからデプロイの指示を出します
　2: Opsidianはその指示通りにLambdaをinvokeします。
　3: invokeされたLamndaはGitHubへdeploy APICallします。
　4: GitHubはdeployのWebhookをdroneに送信します。
　5: droneは受信したWebhookからソースを取得し、ビルドを実行し、AWS ECRへイメージをpushします。

　細かい設定とかは割愛します。今後時間がありましたら、書くかもしれません。...と言っても、簡単に何を設定しているかを書きます。

1: SlackからOpsidianを呼べるようにしました。
　　- Opsidianのインストールは[こちら](http://opsidian.ai/install/)
　　- Opsidianの設定は[こちら](http://opsidian.ai/connect/)
  
2: OpsidianがinvokeするLambdaを作りました。
　　- Opsidianの[Dashboard](https://slack.com/oauth/authorize?scope=identity.basic,identity.email,identity.team,identity.avatar&client_id=82618423970.83166425361&redirect_uri=https%3A%2F%2Fwebapi.opsidian.ai%2Fv1%2Foauth)にて、Slackから呼べるLambdaのコマンド**deploy**を設定しました。
　　<img width="911" alt="WechatIMG27.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/117156/c74f7bed-20a1-c4a4-4d4b-98c88752ed74.jpeg">

　　- 下記、超雑なLambdaサンプルコード
　　　※ Opsidianのコマンドから渡された引数を使って、GitHubへdeploy APICall
　　　※ GithubのPersonal access tokenはlambdaの環境変数**GIT_KEY**に設定しています。

```py:deploy
import boto3
import json
import os
import http.client

def lambda_handler(event, context):
    conn = http.client.HTTPSConnection("api.github.com")
    print(event)
    args = event["args"].split(" ")
    repo    = args[0]
    branch  = args[1]
    env     = args[2]
    payload = {
        "ref": branch,
        "auto_merge": False,
        "environment": env,
        "description": "Deploy to "+ env,
        "required_contexts": []
    }

    headers = {
        'authorization': "token " + os.environ['GIT_KEY'],
        'User-Agent': "Awesome-Octocat-App"
    }

    conn.request("POST", "/repos/"+ repo +"/deployments", json.dumps(payload).encode("utf-8"), headers)

    res = conn.getresponse()
    data = res.read()

    print(data.decode("utf-8"))
    return json.dumps({'message': 'Hello world!'})
```
3: Github
　　- 下記２つのファイル(あくまでもサンプル)が対象のリポジトリの配下に格納しました。


```yaml:.drone.yml

# masterブランチに対して、
# GitHubのevnetがdeploymentかつenvironmentがproductionと指定された場合
# ビルドを実行

pipeline:
  ecr:
    image: plugins/ecr
    region: ap-northeast-1
    repo: 284****1948.dkr.ecr.ap-northeast-1.amazonaws.com/ecr
    tags: [ latest,drone-test ]
    secrets: [ ECR_ACCESS_KEY,ECR_SECRET_KEY ]
    when:
      branch: master
      event: deployment
      environment: production
```
```docker:Dockerfile
FROM centos:6

RUN set -x && \
    yum install -y httpd
```

4: drone
　　- AWS ECRへpushできるdroneのプラグイン[plugins/drone-ecr](https://hub.docker.com/r/plugins/drone-ecr/)を利用しています
　　　　※ ソースコードは[こちら](http://plugins.drone.io/drone-plugins/drone-ecr/)
　　- 対象ブランチを有効化しました。
　　<img width="838" alt="1.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/117156/3fff699c-f765-c8d2-cb1d-edc71e76bb6e.jpeg">
　　
　　- droneにecrへpushできる権限のキーを設定しました。
　　　※ plugins/drone-ecr利用時、設定する環境変数は**ECR_ACCESS_KEY**と**ECR_SECRET_KEY**になります。
　<img width="838" alt="2.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/117156/62810eb7-80ad-1c60-b0d8-0cec14ca663e.jpeg">

　　- 今回はGitHubのdeploymentの場合ですので、「Settings」の**「Deploy Hook」**を有効にしました。
<img width="838" alt="3.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/117156/4487ad2e-df68-ff5b-ba26-e5705e36d289.jpeg">



5: ECR
　　- droneがビルドしたdockerイメージのpush先を予め用意しました。
<img width="837" alt="WechatIMG16.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/117156/30017949-692c-cd7b-9c80-b0a9423a3835.jpeg">



# Slackからやってみる

1: Slackから ```/ops run deploy [repository] [branch] [environment]```を打ってみます。
<img width="875" alt="W1.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/117156/b33f8ab5-8a6d-946e-2902-e2c35cdd4051.jpeg">

2: Opsidianから返信が来ました. やっはり Hello worldにすべきじゃなかったかもしれません。微妙に違和感が感じますが、一旦よしとします。
<img width="879" alt="W2.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/117156/9f6514e0-2c47-78aa-fe6a-d784a83a8513.jpeg">

3: droneが動いていますね。
<img width="883" alt="W3.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/117156/99e26ab0-36a9-8815-0403-e06c9e74f5ba.jpeg">

<img width="886" alt="W4.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/117156/0b5f24fe-6d92-943f-b5c4-95e045d93ddd.jpeg">

<img width="881" alt="W5.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/117156/0d355135-0889-bdbf-4cdd-1faecfbea25c.jpeg">
ちゃんとpushまでできましたね!

4: ECRにpushされたことも確認できました。
<img width="875" alt="W7.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/117156/8f7f0d5e-f2da-ef7b-cd3a-e57c05ad89d4.jpeg">

5: 終了

# 最後
　Opsidianとdroneで、SlackからAWS ECRへイメージをpushするまでについて整理しました。繰り返しにはなってしまいますが、Opsidianが結構便利なツールなので、ChatOpsだけではなく、モニタリングとかにも活用したいと思っています。
　今日はとりあえずここまでにします。