Ткань ОКР.roledefs не действует так, как ожидалось
на сайт ткани этот пример приведен:
from fabric.api import env
env.roledefs = {
'web': {
'hosts': ['www1', 'www2', 'www3'],
'foo': 'bar'
},
'dns': {
'hosts': ['ns1', 'ns2'],
'foo': 'baz'
}
}
насколько я могу судить из документации, эта настройка должна дать ключу env dict " foo "значение" bar "при выполнении на хостах "www1", "www2", "www3". Я не могу получить это поведение, хотя fabric правильно определяет хосты. Пример 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.
Я неправильно поняла цель этого? Как я могу сделать так, чтобы один сервер видел другое значение для ключа, а затем другой без особых проблем?
Я использую ткань 1.10.0
4 ответов
меня это тоже смутило. Оказывается, что будет возможно получить доступ к ним в Fabric 1.11: https://github.com/fabric/fabric/issues/1276
две проблемы, во-первых, версия используемой ткани старше определений на основе словаря, поэтому она интерпретирует ключи как имена хостов. Это может быть исправлено путем обновления до >= ткань 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
просто ответ на это:
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']
Если вы хотите, чтобы дополнительные ключи roledef автоматически устанавливались в env
для данной задачи вы можете использовать декоратор. Вот тот, который я использую:
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():
...