fabfileの構造化

fabfile.pyって、task数個までならまあ1ファイルでいいんですが、それ以上増えてくるとスクリプト自体がカオスになって収集がつかなくなります。

更に似たような、けど微妙に違うtaskをいっぱい定義したりすると名前まで酷くなってきます。こんなかんじに。

@roles('lb')
def lbserver_deploy():
    """ロードバランサーにデプロイする"""
    ...

@roles('app')
def appserver_deploy():
    """アプリケーションサーバーにデプロイする"""
    ...

@roles('batch')
def batchserver_deploy():
    """バッチサーバーにデプロイする"""
    ...

こんなファイルメンテする気が起こらないので、なんとか綺麗にしたいと思って調べたところ、fabric1.1から付いたクラスベースのtaskというのを使うとよいようです。

http://docs.fabfile.org/en/1.2.2/usage/tasks.html#new-style-tasks

つかいかた

あんまり詳しく調べてないのでベーシックな使い方を。

1. まずfabfile.pyを、モジュールからパッケージに直します
fabfile/
     ┣__init__.py

__init__.pyに元のfabfile.pyの内容をまんま移せばとりあえずこれまでどおり動きます。

2. 思うがままにモジュール化する

心ゆくまで分割してください。

fabfile/
     ┣__init__.py
     ┣lb.py
     ┣app.py
     ┣batch.py

とりあえずサーバー種別ごとに3つのモジュールに分解した と思ってください。

この段階で関数名も被りを気にしない短いモノに変えてしまいましょう。この例だと"appserver_deploy" -> "deploy"ぐらい。

3. 各task関数に@taskデコレータをかける
from fabric.decorators import task

@task
@roles('app')
def deploy():
    """アプリケーションサーバーにデプロイする"""
    ...

これはまあおまじないで。

4. __init__.pyでimportする

最後に分割した各モジュールを__init__.pyでimportします

import lb
import app
import batch

これで終わりです。fab --listコマンドで一覧をだしてみると

$ fab --list

lb.deploy     ロードバランサーにデプロイする
app.deploy    アプリケーションサーバーにデプロイする
batch.deploy  バッチサーバーにデプロイする

みたく表示されます。モジュール名がまんま名前空間になってくれてる感じですね。

もちろん

fab app.deploy

と叩けば動作します。

モジュールじゃなくてパッケージにしたら多段の名前空間が使えるのか とかは調べてないです(´・ω・)

おわり

極力こういう複雑なfabfileは書きたくないもんですが、必要なときにはこうやって構造化するのもよいかと思います。汚いよりよっぽどいいです。

他にもcontribとか面白そうなモジュールがいっぱいありそうなので、また調べて書くかも。