Errbot×Fabric -Pythonで組み立てるチャットボットでのデプロイ-

# TL;DR

- Pythonパッケージ同士は組み合わせやすい
- Errbotは楽しい

# 期待値調整

もうちょっとちゃんとしたのを作る予定ですが、とりあえず当日投稿を最優先します。


# 振り返り

## Errbotのおさらい

**Python**製のチャットボットフレームワーク。
コマンドなどをPythonのコードで書けることと、プラグインの仕組みにより拡張が比較的容易なのが特徴。


## Fabricのおさらい

**Python**製のデプロイツール。
コマンドなどをPythonのコードで書けることが特徴。


## まとめると

どちらも**Python製**である。そして、Python3系で動く。[^1] [^2]
つまり、**Pythonパッケージのみで、ChatOpsデプロイができる。**


# やってみた

## 今回の素材

- Dockerイメージを利用したアプリ(GitLab.comでプライベートレジストリを利用)
- Docker-composeを使った構成
- デプロイ先のサーバーと、アクセス+`docker`系コマンドを使えるユーザー
- Errbot+Fabricが動くPython3.x系環境
- Slack

## まずは、Fabricだけの独立した構成を用意

```py3:fabfile.py
import os
from fabric.api import cd, sudo, settings, env, run

env.user = 'service'
# 細かいenvは略
env.key = os.environ['SSH_PRIVATE_KEY']


def deploy(self):
    image_name = 'myapp'
    target_dir = '/{}/{}/myapp'.format('home', env.user)
    image_url = '{}/{}'.format('registry.gitlab.com', image_name)
    with settings(use_shell=False), cd(target_dir):
        run('sudo docker pull ' + image_url)
        run('sudo docker-compose up -d')
```

これは、

* `docker pull`して、レジストリからイメージを取ってくる
* イメージを元に`docker-compose up`をしてよしなにコンテナを起動してもらう。

ものです。

```shell-session:fab_deploy
[127.0.0.1] run: sudo docker pull registry.gitlab.com/attakei/myapp
[127.0.0.1] out: latest: Pulling from attakei/myapp
[127.0.0.1] out:
                           Digest: sha256:5757fa47a27c3df8d0196b06df311e88a9021f5ef3f6407a4c4a11943efe2916
[127.0.0.1] out: Status: Image is up to date for registry.gitlab.com/attakei/myapp
[127.0.0.1] out:

[127.0.0.1] run: sudo docker-compose up -d
[127.0.0.1] out: myapp_cron_1 is up-to-date
[127.0.0.1] out: myapp_web_1 is up-to-date
[127.0.0.1] out:


Done.
Disconnecting from 127.0.0.1... done.
```

こんな感じになります。


## Errbotに組み込む

まずはプラグインを作りましょう。（もちろん既存のものを流用するでもOK）

```shell-session
$ errbot --new-plugin plugins/deploy
This wizard will create a new plugin for you in 'plugins/deploy'.
What should the name of your new plugin be?
> Deploy
What may I use as a short (one-line) description of your plugin?
> Deployment from Errbot
Which minimum version of errbot will your plugin work with? Leave blank to support any version or input CURRENT to select the current version (4.3.3)
>
Which maximum version of errbot will your plugin work with? Leave blank to support any version or input CURRENT to select the current version (4.3.3)
>
Success! You'll find your new plugin at 'plugins/deploy/deployment.plug'
(Don't forget to include a LICENSE file if you are going to publish your plugin)

$ ls -l plugins/deploy
total 16
-rw-r--r--  1 attakei  staff   132 12 14 00:07 deploy.plug
-rw-r--r--  1 attakei  staff  2987 12 14 00:07 deploy.py
```


```plugins/deploy/deploy.py
import os
from errbot import BotPlugin, botcmd
from fabric.api import env, settings, run, cd


env.user = 'service'
# 細かいenvは略
env.key = os.environ['SSH_PRIVATE_KEY']


class Deploy(BotPlugin):
    """
    Deployment from Errbot
    """

    @botcmd
    def deploy(self, message, args):
        image_name = 'myapp'
        target_dir = '/{}/{}/myapp'.format('home', env.user)
        image_url = '{}/{}'.format('registry.gitlab.com', image_name)
        result = ''
        with settings(use_shell=False), cd(target_dir):
            result += run('sudo docker pull ' + image_url)
            result += '\n'
            result += run('sudo docker-compose up -d')
        return result
```

これが、ミニマムな構成（多分）。

テキストモードのErrbotで呼び出してみる。

```shell-session
> errbot -T
(略)

 >>> !deploy
[127.0.0.1] run: sudo docker pull registry.gitlab.com/attakei/myapp

 >>> [127.0.0.1] out: latest: Pulling from attakei/myapp
[127.0.0.1] out:
                           Digest: sha256:5757fa47a76c3ddf85d196b01f301e88a9021f5ef3a6407a4c4a11943efe2916
[127.0.0.1] out: Status: Image is up to date for registry.gitlab.com/attakei/myapp
[127.0.0.1] out:

[127.0.0.1] run: sudo docker-compose up -d
[127.0.0.1] out: myapp_cron_1 is up-to-date
[127.0.0.1] out: myapp_web_1 is up-to-date
[127.0.0.1] out:

latest: Pulling from attakei/myapp

Digest: sha256:5757fa47a76c3ddf85d196b01f301e88a9021f5ef3a6407a4c4a11943efe2916
Status: Image is up to date for registry.gitlab.com/attakei/myapp
myapp_cron_1 is up-to-date
myapp_web_1 is up-to-date

```

無事に、`docker-compose up`まで実行した模様。

`[127.0.0.1]`で始まる行は勝手に出力されているもので、それ以外(`latest`あたりから始まる行)は`result`変数から出たやつ。

### Slackに組み込んでみる

![errbot-fabric-2.gif](https://qiita-image-store.s3.amazonaws.com/0/6805/6ebe60f1-a25d-a076-e706-d08604c95f2c.gif)

やったぜ


[^1]: 少し前のバージョンから、ErrbotはPython2.x系のサポートをやめています
[^2]: Fabricはオフィシャルではないですが、3.x対応用にフォークされたFabric3があります