在Anaconda2 5.1.0下使用fabric 1.14.0 ...确认使用@roles
装饰器时的问题...尤其是在@roles
装饰器与多个参数一起使用的情况下,然后调用另一个没有@roles
装饰器(或具有不同参数)的任务从第一个任务中。以我的经验,这可能会导致主机不匹配,这取决于我如何发现角色(即role = env.effective_roles[0]
)。
请注意,role = env.effective_roles[0]
在简单的情况下确实可以很好地工作,例如(a)@roles
只指定一个角色,并且(b)原始任务不调用另一个任务。
还要注意-R
命令行上不覆盖@roles
并且必须使用的情况task:roles=role1
:如何仅在单个主机上运行@roles-decorated 结构任务......还想知道如何将多个角色传递给名为...的参数roles
...嗯,但我离题了。
也许有更好的方法,但文档@roles
留下一个想要的。下一步可能是在这一点上通读源代码。
与此同时,我已经破解了以下解决方法......
from fabric.api import env
from fabric.decorators import roles
from fabric.decorators import task
def get_host_roles(env, of=None, die=False):
"""
Get the role(s) for a host at run time
:param env: Fabric env
:param of: tuple/set/list
:param die: boolean
:return: tuple(host, roles) or tuple(host, role)
"""
host = env.host
def valid(role):
return host in env.roledefs[role]:
roles = set(filter(valid, env.roledefs.keys()))
if of:
roles = tuple(roles & set(of)) # set intersection
if len(roles) == 1:
return host, roles[0]
elif die:
e = 'Host "%s" is not in just one of the provided roles: %s!' \
% (host, repr(roles))
raise Exception(e)
return host, roles
_roles = ('role1', 'role2')
@task
@roles(*_roles)
def do_something_with_roles():
host, roles = get_host_roles(env)
# roles is a tuple with all of the roles the host is in.
@task
@roles(*_roles)
def do_something_with_roles_diy():
host, roles = get_host_roles(env, _roles)
# `roles` is a tuple with the set intersection of `_roles` and the
# host's actual roles... so you handle the situation!
if 'role1' in roles:
# do whatever
pass
@task
@roles(*_roles)
def force_single_role():
host, role = get_host_roles(env, _roles, True)
# this usage raises an exception in the instance that the host is not
# exclusively in either 'role1' or 'role2'.
# roles is a string with the role for that host.
希望有帮助。