结构任务是否可以执行其他任务并尊重装饰器,例如runs_once?

时间:2013-10-22 02:45:21

标签: python fabric

结构中execute是否有办法尊重装饰器(hosthostsroleroles和{{1}除外} ---看here),或其他方式来完成这样的事情)?这是一个用例:

exclude_hosts

如果我从命令行运行以下任务序列,那么这很好:

from fabric.api import task, execute, run, runs_once

@task
def setup_environment():
    # ... set up env.hosts, env.roledefs, env.use_ssh_config, etc.

@task
def provision():
    # ... do some stuff on each host here, e.g. install mongodb

@task
def is_primary():
    return run('mongo --quiet --eval "db.isMaster().ismaster"') == 'true'

@task
@runs_once
def change_to_primary():
    env.hosts = []
    for host, result in execute(is_primary, roles=('mongo',)).iteritems():
        if result:
            env.hosts.append(host)

@task
def add_user():
    # ... do something here that needs to be done on primary

但由于我始终在配置过程中运行> fab setup_environment provision change_to_primary add_user change_to_primary,因此我想修改add_user,以便我可以运行provision并拥有{{1}并执行fab setup_environment provision,如下所示:

set_primary

但是,与命令行用法不同,这会多次执行add_user(不会运行一次)。有没有办法实现这个目标?

1 个答案:

答案 0 :(得分:1)

一种方法是使用mongo装饰器在roles角色的所有节点上执行任务,并通过检查节点是否实际是主要任务来开始任务:

@task
def provision():
    execute(stuff_to_do_on_all_hosts)
    execute(stuff_to_do_on_mongo_primaries)

@task
def stuff_to_do_on_all_hosts():
    do_stuff()

@task
@roles('mongo')
def stuff_to_do_on_mongo_primaries():
    if not is_primary():
        return
    add_user()
    do_other_stuff()

另一种方法是首先构建原色列表,然后使用hosts参数execute

@task
def provision():
    # ... do some stuff on each host here, e.g. install mongodb
    execute(stuff_to_do_on_all_hosts)

    # build list of mongo primaries
    primaries = [host for host, result in execute(is_primary, roles=('mongo',)).iteritems() if result]

    # run task only on those hosts
    execute(stuff_to_do_on_mongo_primaries, hosts=primaries)

@task
def stuff_to_do_on_all_hosts():
    do_stuff()

@task
def stuff_to_do_on_mongo_primaries():
    add_user()
    do_other_stuff()

希望这有帮助。