Может ли задача Python Fabric вызывать другие задачи и учитывать их списки хостов?

У меня есть fabfile, подобный следующему:

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


person fabricquestion    schedule 17.03.2011    source источник


Ответы (4)


Начиная с Fabric 1.3, помощник execute теперь доступен именно для этого. Документация доступна здесь: Интеллектуальное выполнение задачи с выполнением.

Вот пример, который они используют:

from fabric.api import run, roles, execute

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)

И это будет учитывать роли и списки хостов, которые есть у этих задач.

person Mitchell    schedule 17.11.2011
comment
Можно ли добавить роль в метод класса? Я использую классы для задач ткани - person Francesco Della Vedova; 28.11.2013
comment
Ссылка на документацию битая. Вот последняя версия: docs.fabfile. .org/en/1.8/использование/ - person krd; 22.05.2014

Это хромает, но работает с 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')
person Evan R.    schedule 12.07.2011

Вероятно, есть лучший способ справиться с этим, но вы можете передать оба хоста в deploy(), а затем в 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()
person pwan    schedule 18.03.2011

Попробуй это. Очевидно, вы хотите заменить 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()
person Charles Hooper    schedule 28.06.2011