fabricの環境設定とコマンドの実行の定義の区別が分かりにくい

注釈を付けるデコレータを定義すれば良いんじゃないかと思った。

とりあえずしたいこと

  • fabfileの中で「環境設定」、「操作」を一目で分かるようにする
  • あと、環境設定だけをリストで取り出せるとか便利

なんか注釈を付けるデコレータを定義すれば良いんじゃないかと思った。

こんな感じで書いてみた。

# -*- coding:utf-8
import collections as c

class AnnotateDecorator(object):
    """fabric用の関数に注釈をつけるためのデコレータを生成するオブジェクト
    """
    functions = c.defaultdict(list)  #デコレータが付与された関数を格納
    decorators = {} #生成されたデコレータを格納

    @classmethod
    def generate(cls, status):
        """statusに渡された引数の注釈を付けるデコレータを返す。
        """
        
        def generated(function): #生成されるデコレータ
            function.__status__ = status

            if not function in cls.functions[status]:
                cls.functions[status].append(function)

            return lambda *args, **kw : function(*args, **kw)

        cls.decorators[status] = generated

        return generated

    @classmethod
    def anotate(cls, status):
        """ 作ったデコレータを返す。無ければ作成
        """
        if not status in decoratos:
            return cls.generate(status)
        else:
            return cls.decorators[status]

    @classmethod
    def list(cls, status):
        """[maybe]:注釈をもとにフィルタリングした結果をリストで返す
        """
        if status in cls.functions:
            return cls.functions[status]

fab_operation = AnnotateDecorator.generate("operation")
fab_environment = AnnotateDecorator.generate("environment")
fab_aggregate = AnnotateDecorator.generate("aggregate")

@fab_aggregate
def operation_list():
    for f in AnnotateDecorator.list("operation"): print(f.__name__)

@fab_aggregate
def environment_list():
    for f in AnnotateDecorator.list("environment"): print(f.__name__)


### 
from fabric.api import run, local, env, sudo

env.user = "anonymous"

@fab_operation
def hello_function():
    print("hello %s" % env.user)

@fab_operation
def hello():
    local("echo hello %s" % env.user)

@fab_environment
def foo():
    env.environment = "foo"
    env.user = "foo"

@fab_environment
def bar():
    env.environment = "bar"
    env.user = "bar"

利用例

結構便利な気がする。

#fab [environment] <operation>

$ fab hello 
[localhost] local: echo hello anonymous
hello anonymous

Done.
$ fab foo hello
[localhost] local: echo hello foo
hello foo

Done.
$ fab bar hello
[localhost] local: echo hello bar
hello bar

Done.
$ fab foo hello_function
hello foo

Done.
$ fab environment_list
foo
bar

Done.