如何在Python Fabric中发现当前角色

25 投票
5 回答
8445 浏览
提问于 2025-04-16 00:19

这是一个非常关于Fabric的问题,不过有经验的Python高手可能也能回答,即使他们不熟悉Fabric。

我想根据命令运行的角色来指定不同的行为,也就是说:

def restart():
    if (SERVERTYPE == "APACHE"):
        sudo("apache2ctl graceful",pty=True)
    elif (SERVERTYPE == "APE"):
        sudo("supervisorctl reload",pty=True)

我之前用这样的函数来处理这个问题:

def apache():
    global SERVERTYPE
    SERVERTYPE = "APACHE"
    env.hosts = ['xxx.xxx.com']

但这样显然不太优雅,而且我刚发现了角色的概念,所以我想问:

我怎么才能知道当前实例属于哪个角色呢?

env.roledefs = {
    'apache': ['xxx.xxx.com'],
    'APE': ['yyy.xxx.com'],
}

谢谢!

5 个回答

12

我没有测试过,但可能可以用:

def _get_current_role():
    for role in env.roledefs.keys():
        if env.host_string in env.roledefs[role]:
            return role
    return None
18

对于所有有这个问题的人,这里是我的解决办法:

关键在于找到 env.host_string。

这样我就可以用一个命令重启不同类型的服务器:

env.roledefs = {
    'apache': ['xxx.xxx.com'],
    'APE': ['yyy.xxx.com']
}

def apache():
    env.roles = ['apache']

...

def restart():
    if env.host_string in env.roledefs['apache']:
        sudo("apache2ctl graceful", pty=True)
    elif env.host_string in env.roledefs['APE']:
        sudo ("supervisorctl reload", pty=True)

希望你喜欢!

5

更新: 刚刚查看了 源代码,发现这个功能早在 1.4.2 版本就已经有了!

更新 2: 在使用 @roles 装饰器时(在 1.5.3 版本),这个功能似乎好使! 只有在命令行中使用 -R 参数时才有效。

在 fabric 1.5.3 版本中,当前的角色可以直接在 `fabric.api.env.roles` 中找到。例如:

import fabric.api as fab

fab.env.roledefs['staging'] = ['bbs-evolution.ipsw.dt.ept.lu']
fab.env.roledefs['prod'] = ['bbs-arbiter.ipsw.dt.ept.lu']


@fab.task
def testrole():
    print fab.env.roles

在控制台上的测试输出:

› fab -R staging testrole
[bbs-evolution.ipsw.dt.ept.lu] Executing task 'testrole'
['staging']

Done.

或者:

› fab -R staging,prod testrole
[bbs-evolution.ipsw.dt.ept.lu] Executing task 'testrole'
['staging', 'prod']
[bbs-arbiter.ipsw.dt.ept.lu] Executing task 'testrole'
['staging', 'prod']

Done.

通过这个,我们可以在 fabric 任务中做一个简单的 in 测试:

@fab.task
def testrole():
    if 'prod' in fab.env.roles:
        do_production_stuff()
    elif 'staging' in fab.env.roles:
        do_staging_stuff()
    else:
        raise ValueError('No valid role specified!')

撰写回答