Quero usar o Fabric para implantar meu código de aplicativo da web em servidores de desenvolvimento, teste e produção. Meu fabfile:
def deploy_2_dev():
deploy('dev')
def deploy_2_staging():
deploy('staging')
def deploy_2_prod():
deploy('prod')
def deploy(server):
print 'env.hosts:', env.hosts
env.hosts = [server]
print 'env.hosts:', env.hosts
Saída de amostra:
host:folder user$ fab deploy_2_dev
env.hosts: []
env.hosts: ['dev']
No hosts found. Please specify (single) host string for connection:
Quando eu crio uma set_hosts()
tarefa conforme mostrado nos documentos do Fabric , env.hosts é definido corretamente. No entanto, essa não é uma opção viável, nem um decorador. Passar hosts na linha de comando acabaria resultando em algum tipo de script de shell que chama o fabfile. Eu preferiria que uma única ferramenta fizesse o trabalho corretamente.
Ele diz na documentação do Fabric que 'env.hosts é simplesmente um objeto de lista Python'. Pelas minhas observações, isso simplesmente não é verdade.
Alguém pode explicar o que está acontecendo aqui? Como posso definir o host para implantar?
Respostas:
Faço isso declarando uma função real para cada ambiente. Por exemplo:
Usando as funções acima, eu digitaria o seguinte para implantar em meu ambiente de teste:
... e o seguinte para implantar na produção:
O bom de fazer isso dessa maneira é que as funções
test
eprod
podem ser usadas antes de qualquer função fab, não apenas na implantação. É incrivelmente útil.fonte
code.fabfile.org
domínio têm respostas assim.fab A B C
estilo sem que sejam definidas como tarefas.Use roledefs
Escolha a função com -R:
fonte
roledef
? Uma outra entrada do dicionário'password': 'some_password'
parece ser ignorada e leva a um prompt em tempo de execução.Aqui está uma versão mais simples da resposta do serverhorror :
fonte
env
variáveis, não para defini-las inicialmente. Acho que usar roledefs , como sugeriu thomie, é mais apropriado para definir hosts como stage, dev e test.Eu mesmo estava preso nisso, mas finalmente descobri. Você simplesmente não pode definir a configuração env.hosts de dentro de uma tarefa. Cada tarefa é executada N vezes, uma para cada Host especificado, portanto, a configuração está fundamentalmente fora do escopo da tarefa.
Olhando para o seu código acima, você poderia simplesmente fazer isso:
O que parece que faria o que você pretende.
Ou você pode escrever algum código personalizado no escopo global que analisa os argumentos manualmente e define env.hosts antes que sua função de tarefa seja definida. Por alguns motivos, foi assim que configurei o meu.
fonte
from fabric.api import env
:;env.host_string = "dev"
Desde o fab 1.5, esta é uma maneira documentada de configurar hosts dinamicamente.
http://docs.fabfile.org/en/1.7/usage/execution.html#dynamic-hosts
Citação do doc abaixo.
fonte
Ao contrário de algumas outras respostas, é possível modificar as
env
variáveis de ambiente dentro de uma tarefa. No entanto, issoenv
só será usado para tarefas subsequentes executadas com afabric.tasks.execute
função.Sem envolver subtarefas
execute(...)
, suasenv
configurações de nível de módulo ou o que for passado dafab
CLI serão usados.fonte
Você precisa dar o
host_string
exemplo:fonte
Para explicar por que é um problema. O comando fab está aproveitando a estrutura da biblioteca para executar as tarefas nas listas de hosts. Se você tentar alterar a lista de hosts dentro de uma tarefa, estará essencialmente tentando alterar uma lista enquanto itera sobre ela. Ou, no caso em que você não tem hosts definidos, faça um loop em uma lista vazia onde o código onde você definiu a lista para fazer um loop nunca é executado.
O uso de env.host_string é uma solução alternativa para esse comportamento apenas porque especifica diretamente para as funções com quais hosts se conectar. Isso causa alguns problemas, pois você estará refazendo o loop de execução se quiser ter vários hosts para executar.
A maneira mais simples de as pessoas criarem a capacidade de definir hosts em tempo de execução é manter o preenchimento de env como uma tarefa distinta, que configura todas as strings de host, usuários, etc. Em seguida, eles executam a tarefa de implantação. Se parece com isso:
ou
Onde a preparação e a produção são como as tarefas que você atribuiu, mas não chamam a próxima tarefa por si mesmas. A razão para funcionar assim é que a tarefa precisa terminar e sair do loop (de hosts, no caso de env Nenhum, mas é um loop de um naquele ponto), e então ter o loop encerrado os hosts (agora definidos pela tarefa anterior) novamente.
fonte
Você precisa modificar env.hosts no nível do módulo, não dentro de uma função de tarefa. Eu cometi o mesmo erro.
fonte
É muito simples. Basta inicializar a variável env.host_string e todos os comandos a seguir serão executados neste host.
fonte
Sou totalmente novo no fabric, mas para fazer com que o fabric execute os mesmos comandos em vários hosts (por exemplo, para implantar em vários servidores, em um comando), você pode executar:
onde staging-server e production-server são 2 servidores nos quais você deseja executar a ação de implantação. Aqui está um fabfile.py simples que exibirá o nome do sistema operacional. Observe que o fabfile.py deve estar no mesmo diretório onde você executa o comando fab.
Isso funciona com o tecido 1.8.1, pelo menos.
fonte
Portanto, para definir os hosts e fazer com que os comandos sejam executados em todos os hosts, você deve começar com:
Depois de definidos, execute o comando na linha de comando:
O que executará a tarefa de implantação em todos os servidores listados na função PROD, pois define o env.hosts antes de executar a tarefa.
fonte
Você pode atribuir a
env.hoststring
antes de executar uma subtarefa. Atribua a esta variável global em um loop se quiser iterar em vários hosts.Infelizmente para você e para mim, o tecido não foi projetado para esse caso de uso. Verifique a
main
função em http://github.com/bitprophet/fabric/blob/master/fabric/main.py para ver como funciona.fonte
Aqui está outro padrão "summersault" que permite o
fab my_env_1 my_command
uso:Com esse padrão, só temos que definir ambientes uma vez usando um dicionário.
env_factory
cria funções com base nos nomes-chave deENVS
. ColoqueiENVS
em seu próprio diretório e arquivosecrets.config.py
para separar a configuração do código de malha.A desvantagem é que, conforme está escrito, adicionar o
@task
decorador irá quebrá-lo .Notas: Nós usamos em
def func(k=k):
vez dedef func():
na fábrica devido à encadernação tardia . Pegamos o módulo em execução com esta solução e corrigimos para definir a função.secrets.config.py
fabfile.py
fonte
Usar funções é atualmente considerado a maneira "adequada" e "correta" de fazer isso e é o que você "deve" fazer.
Dito isso, se você for como a maior parte do que você "gostaria" ou "desejo", é a capacidade de executar uma "manobra torcida" ou alternar sistemas de destino em tempo real.
Portanto, apenas para fins de entretenimento (!), O exemplo a seguir ilustra o que muitos podem considerar uma manobra arriscada, mas de alguma forma totalmente satisfatória, que é mais ou menos assim:
Em seguida, executando:
fonte