Tecido e aipo podem ser amigos!

Recentemente, estive trabalhando em um projeto que requer muito gerenciamento de host remoto. É baseado em Django e usa Celery e Fabric para gerenciamento de tarefas e conexão SSH, respectivamente. Existem, no entanto, alguns gottchas que são aplicáveis ​​tanto na minha situação quanto em qualquer outra situação em que você queira usar o Fabric como uma API.

Hosts Dinâmicos

O primeiro grande passo foi ser capaz de oferecer suporte a hosts dinâmicos. A solução para isso é simples. Dentro de qualquer método no qual estamos obtendo informações do host e queremos nos conectar a esse host via SSH por meio do Fabric, definimos um método interno com o decorador @hosts da API do fabric.

from fabric.api import hosts
from celery import task

@task()
def my_celery_task():
username
, host = grab_my_host_info()
host_string
= "%s@%s" % (username, host)

@hosts(host_string)
def my_fab_task():
run
("ls")

execute
(my_fab_task)

Manipulação de exceção

Isso exigiu um pouco mais de pesquisa, mas acabou não sendo tão ruim quanto eu pensava. O Fabric tem uma política de execução rápida contra falhas. Portanto, se absolutamente alguma coisa acontecer, ele será abortado por meio de abort ().

Esse é um grande problema com o aipo, pois o que ele acaba matando seu trabalhador. A solução para isso é dupla, e ambas são configurações que habilitamos na variável global fabric.api.env do Fabric.

Essas configurações são skip_bad_hosts e warn_only . Ambos permitem o tratamento de erros personalizado pelo programador. Observe que, em ambos os casos, você precisará observar o valor de retorno de qualquer chamada para o erro. Embora a maioria das chamadas de malha como run (), cd () e get () retornem com um atributo * .failed, execute não.

Execute retornará um dicionário cujas chaves são as diferentes cadeias de caracteres do host nas quais a tarefa deveria ser executada, junto com uma exceção como o valor, caso ocorresse. O tratamento de erros pode ser parecido com isto, modificando nosso exemplo anterior.

from fabric.api import hosts, env
from celery import task

env
.skip_bad_hosts = True
env
.warn_only = True

@task()
def my_celery_task():
username
, host = grab_my_host_info()
host_string
= "%s@%s" % (username, host)

@hosts(host_string)
def my_fab_task():
run
("ls")

try:
result
= execute(my_fab_task)
if isinstance(result.get(host_string, None), BaseException):
raise result.get(host_string)
except Exception as e:
print "my_celery_task -- %s" % e.message

Substituindo a declaração de impressão pelo seu logger favorito, é claro.

Gestão de Contexto Env

Agora, pode não ser a melhor coisa do mundo ir e especificar valores de variáveis ​​env rígidas no script dessa forma. Você também pode usar o gerenciador de contexto de configurações, decorando a tarefa de tecido ou usando uma instrução with.

Links legais

Aqui estão alguns links que me ajudaram a descobrir tudo isso.

http://awaseroot.wordpress.com/2012/06/05/fabric-wrappers-and-more-error-handling/

http://docs.fabfile.org/en/1.4.0/usage/env.html

http://docs.fabfile.org/en/1.4.0/usage/execution.html