Подтвердить что ты не робот

Может ли задача 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() здесь, чтобы он выполнял то, что мне нужно, оставив подзадачи в одиночку, чтобы они могли запускаться индивидуально?

4b9b3361

Ответ 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()