Может ли задача Python Fabric вызывать другие задачи и уважать их списки хостов?
У меня есть файл, похожий на следующий:
@hosts('host1')
def host1_deploy():
"""Some logic that is specific to deploying to host1"""
@hosts('host2')
def host2_deploy():
"""Some logic that is specific to deploying to host2"""
def deploy():
""""Deploy to both hosts, each using its own logic"""
host1_deploy()
host2_deploy()
Я хотел бы сделать
fab deploy
и пусть это будет эквивалентно
fab host1_deploy host2_deploy
Другими словами, запустите каждую из подзадач и для каждого из них используйте список узлов, которые он задает. Однако это не работает. Вместо этого задача deploy() хочет иметь собственный список хостов, который будет распространять на все его подзадачи.
Есть ли способ обновить задачу deploy() здесь, чтобы он выполнял то, что мне нужно, оставив подзадачи в одиночку, чтобы они могли запускаться индивидуально?
Ответы
Ответ 1
Так как Fabric 1.3, хелпер execute
теперь доступен для этого. Документация доступна здесь: Интеллектуальное выполнение задач с выполнением.
Вот пример, который они используют:
from fabric.api import run, roles
env.roledefs = {
'db': ['db1', 'db2'],
'web': ['web1', 'web2', 'web3'],
}
@roles('db')
def migrate():
# Database stuff here.
pass
@roles('web')
def update():
# Code updates here.
pass
И затем для запуска migrate
и web
из другой задачи deploy
:
def deploy():
execute(migrate)
execute(update)
И это будет учитывать списки ролей и хостов, которые эти задачи имеют.
Ответ 2
Это хромает, но работает как с Fabric 1.1.2
def host1_deploy():
"""Some logic that is specific to deploying to host1"""
if env.host in ["host1"]:
pass #this is only on host2
def host2_deploy():
"""Some logic that is specific to deploying to host2"""
if env.host in ["host2"]:
pass #this is only on host2
def deploy():
""""Deploy to both hosts, each using its own logic"""
host1_deploy()
host2_deploy()
здесь мой тестовый код:
@task
@roles(["prod_web","prod_workers"])
def test_multi():
test_multi_a()
test_multi_b()
def test_multi_a():
if env.host in env.roledefs["prod_web"]:
run('uname -a')
def test_multi_b():
if env.host in env.roledefs["prod_workers"]:
run('uname -a')
Ответ 3
Вероятно, лучший способ справиться с этим, но вы можете передать оба узла для развертывания(), а затем в host1_deploy() и host2_deploy() проверить env.host:
def host1_deploy():
if env.host in ['host1']:
run(whatever1)
def host2_deploy():
if env.host in ['host2']:
run(whatever2)
@hosts('host1','host2')
def deploy():
host1_deploy()
host2_deploy()
Ответ 4
Попробуйте это. Очевидно, вы хотите заменить local на run
или sudo
. Ключ - пустой декоратор @hosts
для deploy
from fabric.api import local
from fabric.decorators import hosts
@hosts('host1')
def host1_deploy():
"""Some logic that is specific to deploying to host1"""
local('echo foo')
@hosts('host2')
def host2_deploy():
"""Some logic that is specific to deploying to host2"""
local('echo bar')
@hosts('')
def deploy():
""""Deploy to both hosts, each using its own logic"""
host1_deploy()
host2_deploy()