Deployment 结构-顺序元任务?

Deployment 结构-顺序元任务?,deployment,fabric,Deployment,Fabric,我有一个执行任务的任务- @roles('group_django') @task @serial def deploy_web(): execute(pre_deploy) execute(fix_srv_perms) execute(force_checkout_branch_to_production) execute(update_sources) execute(pip_install_requirements) #execute(bou

我有一个执行任务的任务-

@roles('group_django')
@task
@serial
def deploy_web():
    execute(pre_deploy)
    execute(fix_srv_perms)
    execute(force_checkout_branch_to_production)
    execute(update_sources)
    execute(pip_install_requirements)
    #execute(bounce_workers)
    execute(bounce_uwsgi)
    execute(clear_cache)
在deploy_web中,如果提供的主机可以顺序执行,但可以一起执行

假设角色“group_django”有4台服务器,它将从该角色中的第一台主机开始,执行每个执行,然后重复。或者我需要做更多的前期工作,抓取当前的
env.hosts
并在
deploy\u web
中的一个循环中使用
hosts=[current\u host]调用每个
execute

我的目标是,如果这是一个糟糕的部署,它将只淘汰一个服务器池,这样负载平衡器将淘汰它,但平台将保持一些完整性的外观


已经阅读()了,它不适用于我的
deploy\u web
任务的工作方式。

我的问题的基本答案是使用这个小助手函数

def execute_serial(func, *args, **kwargs):
    a2set = lambda x : set(getattr(func, x)) if hasattr(func, x) else None

    func_hosts = a2set('hosts')
    func_roles = a2set('roles')
    should_exec = False

    if 'host' not in kwargs:
        kwargs['host'] = my_host = env.host_string

    if func_hosts and my_host in func_hosts:
        should_exec = True


    if func_roles:
        for func_role in func_roles:
            if func_role in env.roledefs and my_host in env.roledefs[func_role]:
                should_exec = True

    if should_exec:
        return execute(func, *args, **kwargs)
使用方法如下

@roles('group_django')
@task
def deploy_web():
    execute(pre_deploy)
    execute_serial(fix_srv_perms)
    execute_serial(force_checkout_branch_to_production)
    execute_serial(update_sources)
    execute_serial(pip_install_requirements)

    #these won't work correctly anymore
    execute(bounce_workers)
    execute(bounce_uwsgi)
    execute(clear_cache)
我已经讨论了fabric.main.main()并且没有简单的钩子机会(在开始之前,所有任务都完成了,出错了等等),所以可能需要一个额外的解决方案

@roles('local') # defined in roledefs as {'local':'127.0.0.1'}
@task    
def deploy_web():
    execute(pre_deploy) #This is already role('local') with @runonce

    for host in env.roledefs['group_django'].values():
        execute_serial(fix_srv_perms, host = host)
        execute_serial(force_checkout_branch_to_production, host = host)
        execute_serial(update_sources, host = host)
        execute_serial(pip_install_requirements, host = host)

    #These will pickup the @role decorators
    execute(redeploy_web_crontab)
    execute(redeploy_work_crontab)
    execute(bounce_workers) 
    execute(bounce_uwsgi)
    execute(clear_cache)
另外,我已经写过几次类似的东西,但是我有一个boto迭代器,它使用~/.boto来决定区域并生成一个
env.roledefs
,如伪代码所示

{{instance.tags中的name}{instance.tags[name]}:[匹配的instance.public\u dns\u名称列表]}

此外,对于我当前的webstack,所有实例都有“group”、“type”和可选的“lead”等标记,用于指定安装crontab或执行最终部署脚本的位置

使用本地任务循环,您需要对
execute_serial
进行一些轻微的修改,特别是env.host_字符串将等于“{env.user}@127.0.0.1”,这并不理想

def execute_serial(func, *args, **kwargs):
a2set = lambda x : set(getattr(func, x)) if hasattr(func, x) else None

no_user = lambda x: x.split("@")[-1]
func_hosts = a2set('hosts')
func_roles = a2set('roles')
should_exec = False
my_host = env.host_string

my_host = env.host_string = kwargs['host']


if func_hosts and no_user(my_host) in func_hosts:
    should_exec = True


if func_roles:
    for func_role in func_roles:
        if func_role in env.roledefs and no_user(env.host_string) in env.roledefs[func_role]:
            should_exec = True
            break

if should_exec:
    return execute(func, *args, **kwargs)

如果我正确理解了您的问题,您希望更改结构串行执行模型:而不是
pre\u deploy host1
->
pre\u deploy host2
->
fix\u srv\u perms host1
等您想要的
pre\u deploy host1
>
fix\u srv\u perms host1
..>
pre_deploy host2
->
fix_srv\u perms host2
等。在这种情况下,我认为您应该迭代
deploy\u web
中的每个主机,并将
主机
传递给执行。@alecxe我认为,目前正在休假一周,但我计划拼凑一个支持库来完成这项工作,因为这似乎是推出复杂服务的好方法。