Fabric env.roledefs没有按预期运行

时间:2014-09-12 17:50:27

标签: python fabric

fabric website上,给出了这个例子:

from fabric.api import env

env.roledefs = {
    'web': {
        'hosts': ['www1', 'www2', 'www3'],
        'foo': 'bar'
    },
    'dns': {
        'hosts': ['ns1', 'ns2'],
        'foo': 'baz'
    }
}

据我从文档中可以看出,在主机'www1','www2','www3'上执行时,此设置应该为env dict键'foo'赋值'bar'。虽然结构正确地确定了主机,但我无法获得此行为。一个示例fabfile:

env.foo = 'WRONG'
@task()
def set_role():
    env.roles.append('web')

@task()
def print_foo():
    print env.foo

示例命令:

fab set_role print_foo

意外输出:

[www1] Executing task 'print_foo'
WRONG
[www2] Executing task 'print_foo'
WRONG
[www3] Executing task 'print_foo'
WRONG

Done.

我误解了这个目的吗?我怎样才能使一个服务器看到一个不同的密钥值而另一个服务器没有太多麻烦?

我正在使用fabric 1.10.0

4 个答案:

答案 0 :(得分:3)

两个问题,首先使用的结构版本比基于字典的定义旧,因此它将密钥解释为主机名。这可以通过升级到> = fabric 1.10.0来解决。其次,此处定义的设置不会自动填充env,但如果您使用任务设置角色,则可以这样设置:

@task
def set_role(role_name):
    env.roles.append(role_name)
    for k, v in env.roledefs[role_name].iteritems():
        if k == 'hosts':
            continue
        env[k] = v

调用:

fab set_role:dns do_my_task

答案 1 :(得分:2)

我也对此感到困惑。事实证明,可以在Fabric 1.11中访问这些: https://github.com/fabric/fabric/issues/1276

答案 2 :(得分:1)

回答这个问题:

env.roledefs = {
    'prod': {
        'hosts':['server1','server2'],
        'path':'/opt/prod'
        },
    'stag': {
        'hosts':['server3','server4'],
        'path':'/opt/stag'
        }
}

@roles('prod')
def runa():
    role = env.effective_roles[0]
    print env.roledefs[role]['path']

答案 3 :(得分:0)

如果您希望在给定任务的env中自动设置额外的roledef键,则可以使用装饰器。这是我正在使用的那个:

from functools import wraps

def apply_role(f):
    "Decorator to apply keys in effective roledef to current env."
    @wraps(f)
    def wrapper(*args, **kwargs):
        if env.effective_roles:
            for k, v in env.roledefs[env.effective_roles[0]].items():
                if k in env and isinstance(env[k], list) and isinstance(v, list):
                    env[k].extend(v)
                elif k in env and isinstance(env[k], list):
                    env[k].append(v)
                else:
                    env[k] = v
        return f(*args, **kwargs)
    return wrapper

然后装饰要为其应用roledef键的任何任务:

@apply_role
def mytask():
    ...