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

rdr*_*rey 23 python fabric

这是一个非常特定于Fabric的问题,但更有经验的python黑客可能能够回答这个问题,即使他们不了解Fabric.

我试图在命令中指定不同的行为,具体取决于它运行的角色,即:

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

我用这样的函数来攻击它:

def apache():
    global SERVERTYPE
    SERVERTYPE = "APACHE"
    env.hosts = ['xxx.xxx.com']
Run Code Online (Sandbox Code Playgroud)

但这显然不是很优雅,我只是发现了角色,所以我的问题是:

如何确定当前实例属于哪个角色?

env.roledefs = {
    'apache': ['xxx.xxx.com'],
    'APE': ['yyy.xxx.com'],
}
Run Code Online (Sandbox Code Playgroud)

谢谢!

rdr*_*rey 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)
Run Code Online (Sandbox Code Playgroud)

请享用!

  • 如果我有相同的主机与不同的角色关联,并希望根据当前执行的角色做不同的事情,这将失败:/ (4认同)

sem*_*nte 12

我没有测试它,但可能会工作:

def _get_current_role():
    for role in env.roledefs.keys():
        if env.host_string in env.roledefs[role]:
            return role
    return None
Run Code Online (Sandbox Code Playgroud)


pbe*_*ier 6

env.roles会给你通过-R标志指定或脚本本身硬编码的角色.它不包含使用命令行或使用@roles装饰器为每个任务指定的角色.目前无法获得此类信息.

下一个结构版本(可能是1.9)将提供env.effective_roles您想要的属性 - 用于当前执行任务的角色.该代码已经合并到master中.

看看这个问题.


exh*_*uma 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
Run Code Online (Sandbox Code Playgroud)

在控制台上测试输出:

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

Done.
Run Code Online (Sandbox Code Playgroud)

要么:

› 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.
Run Code Online (Sandbox Code Playgroud)

有了这个,我们可以in在Fabric任务中做一个简单的测试:

@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!')
Run Code Online (Sandbox Code Playgroud)