Can a Python Fabric task invoke other tasks and respect their hosts lists?

后端 未结 4 1150
误落风尘
误落风尘 2020-12-30 20:52

I have a fabfile like the following:

@hosts(\'host1\')
def host1_deploy():
    \"\"\"Some logic that is specific to deploying to host1\"\"\"

@hosts(\'host2\         


        
相关标签:
4条回答
  • 2020-12-30 21:01

    This is lame but it works as of 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()
    

    here's my test code:

    @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')
    
    0 讨论(0)
  • 2020-12-30 21:05

    Try this one. Obviously you want to replace local with run or sudo. The key is the empty @hosts decorator for 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()
    
    0 讨论(0)
  • 2020-12-30 21:06

    There's probably a better way to handle it, but you could pass both hosts to deploy(), and then in host1_deploy() and host2_deploy() check 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()
    
    0 讨论(0)
  • 2020-12-30 21:07

    Since Fabric 1.3, the execute helper is now available to do just this. The documentation is available here: Intelligently executing tasks with execute.

    Here is the example they use:

    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
    

    And then to run both migrate and web from another task deploy:

    def deploy():
        execute(migrate)
        execute(update)
    

    And this will respect the roles and hosts lists that those tasks have.

    0 讨论(0)
提交回复
热议问题