Использование матрицы 1.14.0 под Anaconda2 5.1.0 ... подтвердите проблему при использовании декоратора @roles
... особенно в том случае, если декоратор @roles
используется с несколькими аргументами, а затем с другой задачей без @roles
декоратор (или с другими аргументами) вызывается из первой задачи. По моему опыту, это может привести к бессмысленному несоответствию хостов, в зависимости от того, как я обнаружу роль (т.е. role = env.effective_roles[0]
).
Обратите внимание, что role = env.effective_roles[0]
хорошо работает в простых ситуациях, например, (a) @roles
определяет только одну роль, и (b) исходная задача не вызывает другую задачу.
Обратите также внимание на ситуацию, когда -R
в командной строке не переопределяет @roles
и должен вместо этого использовать task:roles=role1
: Как запустить задачу фабрики с @ ролями на одном хосте . ... также интересно, как передать несколько ролей аргументу с именем 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.
Надеюсь, это поможет.