Fabric: Meta-ticket de feedback alfa/beta do Fabric 2!

Criado em 21 abr. 2017  ·  28Comentários  ·  Fonte: fabric/fabric

Por favor, certifique-se de ler esta postagem do blog e todos os seus links primeiro!: http://bitprophet.org/blog/2017/04/17/fabric-2-alpha-beta


Este é o local para deixar comentários sobre problemas não cobertos por nenhum dos tickets existentes; por favor, procure os lugares abaixo primeiro!!


Não encontra nada relevante? Deixe um comentário abaixo! Estou procurando feedback _semelhante, mas não limitado a_:

  • "Eu me recuso a usar 2.0 até que você coloque de volta no modo mágico, global, não orientado a objetos!" (embora eu apenas vincule você a pyinvoke/invoke#186 e peça que você forneça a lógica lá ;))
  • "Eu realmente gosto do que você fez com o $feature, mas está faltando o $sub-recurso, que eu realmente preciso! Isso está planejado?" (Eu direi 'sim', 'não' ou 'não, mas agora você pode implementá-lo trivialmente! ele não precisa estar no núcleo!')
  • "Eu realmente gosto do que você fez com $feature, mas do jeito que está configurado agora, é difícil/impossível fazer $sub-use-case!" (Provavelmente pedirei detalhes e possivelmente pedirei um exemplo de PR da API que você gostaria de ver.)

Comentários muito úteis

@haydenflinner Vai acontecer na próxima semana ou duas!! (O objetivo é lançar antes de eu pegar meu avião para o PyCon, que é 10 de maio.)

Por exemplo, consulte os documentos de atualização recentemente atualizados nos quais eu estava trabalhando esta semana: http://docs.fabfile.org/en/v2/upgrading.html

Na verdade, eu posso fechar este ticket agora, já que estarei aceitando reais reais para 2.0.0 e acima em breve 👍

Todos 28 comentários

Vai mostrar o quão bem eu me lembro do meu próprio site, hein? Obrigado! Eu até fiz um verificador de links no meu post, mas... não contra este ticket ;)

Eu tenho uma proposta de como o sistema roledefs do fabric 1 pode ser implementado de uma forma que acredito estar de acordo com a filosofia do fabric 2. Cada Collection de tarefas também pode ter funções decoradas @group no mesmo namespace que retornam objetos Group preenchidos nos quais as tarefas podem ser executadas. Namespaces seriam importantes, então se fabfile.py contivesse um Collection chamado deploy que tivesse @group s chamados web e db , pode-se usar deploy.web.execute(mytask) ou fab -G deploy.web mytask para executar mytask em cada host no grupo web . Essas funções decoradas seriam chamadas preguiçosamente e memorizadas para evitar chamadas de API desnecessárias, caso uma pesquisa na lista de hosts fosse uma operação lenta conforme implementada pelo usuário.

Isso está de acordo com a filosofia de design do tecido 2? Eu adoraria dar uma olhada na implementação, se assim for.

Essa é uma ideia legal, @RedKrieg! Eu tenho adiado meu próprio brainstorm sobre como "melhor" gerar objetos de grupo e/ou como se referir a eles na CLI, mas de improviso isso parece um caminho razoável a seguir. Acabei de descartar muitas palavras em #1594 e incluí sua ideia lá (+ um link). Vamos continuar a discussão lá, mas tl;dr sim, eu adoraria ver um PoC PR.

Qual é a melhor abordagem para executar um comando localmente, apesar do argumento -H estar presente, por exemplo, se eu quiser combinar compilação local e rsync para host remoto em uma única tarefa?

Objetos de conexão @max-arnold têm um atributo .local que age como .run na máquina local: http://docs.fabfile.org/en/v2/api/connection.html#fabric .connection.Connection.local

Ok, eu acho que um exemplo é melhor do que palavras:

<strong i="6">@task</strong>
def build(ctx):
    # should always run locally
    ctx.local('uname -a')


<strong i="7">@task</strong>
def deploy(ctx):
    build(ctx)
    # this one should run on remote host
    ctx.run('uname -a')

A tarefa combinada funciona bem:

fab -H host deploy

A tarefa local sozinha falha com AttributeError: Nenhum atributo ou chave de configuração encontrada para 'local':

fab build

Basicamente eu quero ter uma tarefa que faça algo localmente, não importa como ela foi invocada (com ou sem -H ).

Por outro lado, alguns comandos destinam-se apenas a serem executados remotamente. Se nenhum host estiver presente, ctx.run tentará executá-los localmente, o que pode levar a consequências inesperadas.

| O usuário executa a tarefa | O autor do comando/tarefa deseja que seja executado | Como deve se comportar? |
|----------|--------------------------- ---|----------------|
| localmente | localmente | comportamento run() é bom (mas irá violar a intenção do autor se executado remotamente) |
| localmente | remotamente | Ele deve falhar (ou solicitar a string do host como o tecido antigo fez) |
|localmente | localmente ou remotamente | comportamento run() é bom |
| remotamente | localmente | Ele deve sempre ser executado localmente, mas Context não tem o método local() para garantir |
| remotamente | remotamente | comportamento run() é bom (mas são esperados problemas durante a chamada local) |
| remotamente | localmente ou remotamente | comportamento run() é bom |

@max-arnold é exatamente o nº 98! que eu ainda não resolvi totalmente. Colocando alguns pensamentos modernos lá como um comentário ... edit: este

Eu notei o que parece ser inconsistência com o sudo.

Onde connection é um servidor remoto, autenticado como root.

Tentando expandir o til como outro usuário que não seja o root:

c.sudo("echo bar > ~/foo", user="builder")

Isso é bem-sucedido, mas em vez de escrever /home/builder/foo, ele escreveu /root/foo.

Por outro lado, se eu apenas tentar ls:

c.sudo("ls", user="builder")

Eu recebo Permission denied .

Algo parece errado.

Meu palpite quando Dustin relatou o fora de banda acima, foi que esta é uma ruga específica de sudo (o comando, não o método), desde a última vez que olhei, estamos usando -H e aparentemente não se comporta 100% como esperamos.

Olá Jeff,
como já estou trabalhando em python 3, agora estou usando fabric3 (a portabilidade do fabric 1.x).

Fiquei tentado a tentar a migração para o fabric 2, mas imediatamente bati em uma rolha. Eu faço uso extensivo das funções fabric.contrib , mas o documento de migração diz que não existe mais.

Com certeza eu não quero inchar o código revertendo para o equivalente do shell, e como, a julgar pelo número de problemas em contrib.* do fabric 1.x, parece que é muito usado, acho que é a falta pode ser um sério obstáculo para a migração de muitos outros.
Encontrei um projeto de patchwork que aparentemente contém o equivalente a fabric.contrib , mas seu código não é atualizado há anos.
Você tem algum plano para portar fabric.contrib para o tecido 2?

Obrigado,
Gabriel

@garu57 Sim, o plano agora é usar patchwork como basicamente "contribuição de 2.0". No momento, é baseado no Fabric 1, mas isso mudará depois que o Fabric 2.0.0 for lançado. Espero que os bits de contribuição mais usados ​​sejam transferidos rapidamente.

Olá a todos,

Às vezes, meu programa executa um comando remoto, por exemplo

source /opt/centos/vars && su - -c 'cd /opt/QA/rpm_tests/p_lvemanager && ALT_TEST=base ALT_PACKAGE_NAME=lvemanager ALT_PACKAGE_VERSION=3.0 ALT_PACKAGE_RELEASE=11.el6.cloudlinux.21100.1.1505113712 ./00-update-kernel.sh'

Eu vejo que os scripts são executados assim:

033[0;32m[DONE]\033[0m'
+ return 0
+ alt_test_done_msg 'Prepare evironment'
+ echo -e '* Prepare evironment    \033[0;32m[DONE]\033[0m'
+ exit 0

e devo ver também minha saída de depuração "?" de acordo com meu código:

class GenericFabric(object):
    def __init__(self, host, user, key_filename=None, port=22):
        connection_string = "{u}@{h}:{p}".format(u=user, h=host, p=port)
        self.connection = Connection(connection_string)
        self.key_filename = key_filename

    #<strong i="13">@with_settings</strong>
    def generic_cmd(self, command_str, timeout, fabric_timeout, **kwargs):
        """
        Creating remote container from template

        <strong i="14">@type</strong> command_str:     str
        <strong i="15">@param</strong> command_str:    command for execute with VM
        <strong i="16">@type</strong> timeout          int or float
        <strong i="17">@param</strong> timeout         number of seconds for pause
        <strong i="18">@type</strong> fabric_timeout   int or float
        <strong i="19">@param</strong> fabric_timeout  number of seconds for timeout fabric run

        <strong i="20">@rtype</strong>:                FabricResponse
        <strong i="21">@return</strong>:               Return remote status of operation VM
        """
        if fabric_timeout > 0:
            command = self.connection.run(command_str.format(**kwargs),
                                          timeout=fabric_timeout,
                                          warn=True, echo=True)
        else:
            command = self.connection.run(command_str.format(**kwargs),
                                          warn=True, echo=True)
        print("?")
        if timeout > 0:
            sleep(timeout)
        return FabricResponse(command)

    def simple_generic_cmd(self, command_str, **kwargs):
        """
        <strong i="22">@type</strong> command_str:     str
        <strong i="23">@param</strong> command_str:    command for execute with VM

        <strong i="24">@rtype</strong>:                FabricResponse
        <strong i="25">@return</strong>:               Return remote status of operation VM
        """
        return self.generic_cmd(command_str, 0.1, 0, **kwargs)

Mas não há ninguém "?". Então, sugiro que houvesse travamento no run().

Na verdade, meu programa é enorme e há programação multi-processo. Para travar estou executando comandos remotos com o seguinte código:

class TestingSystemVM(GenericFabric):
#######
    <strong i="7">@signal_alarm_down</strong>
    def run_rpm_test(self, command_test, package, type_of_test="base"):
        """

        """
        signal.signal(signal.SIGALRM, alarm_handler)
        signal.alarm(self.__timeout)
        returned_value = Queue()
        start_time = datetime.utcnow()
        directory, command_test = os.path.split(command_test)
        try:
            if command_test.endswith(".yml"):
                directory = directory.replace("/opt/QA", self.ansible.git_qa_repo)
                output = self.ansible.play_ansible(command_test,
                                                   package,
                                                   directory)
            else:
                vm_instance = (self.host,
                               self.user,
                               self.key_filename,
                               self.os_name,
                               self.platform,
                               self.arch)
                running_test = Process(target=separate_process_running_test,
                                       args=(vm_instance,
                                             returned_value,
                                             directory,
                                             command_test,
                                             package,
                                             type_of_test))
                running_test.start()
                running_test.join(self.__timeout)
                if running_test.is_alive():
                    running_test.terminate()
                    command_test_res = "FAIL: Timeout\n"
                    return command_test_res, work_time(start_time), 1
                elif returned_value.empty():
                    command_test_res = "FAIL: Problem while getting result\n"
                    return command_test_res, work_time(start_time), 1
                else:
                    output = returned_value.get()
        except TimeOut:
            command_test_res = "FAIL: Timeout\n"
            return command_test_res, work_time(start_time), 1
        if output.failed or (package.name in ("lve-utils", "lve-stats") and
                                     "FAIL" in output.stdout):
            res_output = "FAIL: " + output.stdout
        else:
            res_output = output.stdout
        return res_output, work_time(start_time), 0 if output.succeeded else 1

def separate_process_running_test(vm_instance, return_value_queue,
                                  directory, command_test, package,
                                  type_of_test="base"):
    """

    """
    sleep(0.5)

    signal.signal(signal.SIGTERM, kill_fabric_runner)
    signal.signal(signal.SIGINT, kill_fabric_runner)
    (host,
     user,
     key_filename,
     os_name,
     platform,
     arch) = vm_instance
    child_vm_instance = TestingSystemVM(host,
                                        user,
                                        key_filename,
                                        os_name,
                                        platform,
                                        arch,
                                        FakeAnsible())
    if command_test.endswith(".bats"):
        command_test = "/usr/bin/bats --tap " + command_test
    else:
        command_test = os.path.join("./", command_test)

    output = child_vm_instance.simple_generic_cmd(child_vm_instance._c_run_test,
                                                  envvars=child_vm_instance.env_vars,
                                                  exec_test=command_test,
                                                  dir=directory,
                                                  package=package.name,
                                                  pver=package.version,
                                                  prel=package.release,
                                                  type_test=type_of_test)
    print("!")
    return_value_queue.put(output)

Quando uso o fabric2, alguns comandos iniciados a partir de processos filho ficam suspensos de tempos em tempos.
Atualizado Na verdade, foi meu erro no código. Então, fabric2 não contém hang

Olá pessoal,
Fiz alguns experimentos de lançamento e posso compartilhar minha experiência.

Em primeiro lugar, executei o comando do meu console

ssh [email protected] -t "source /opt/centos/vars && su - -c 'cd /opt/QA/rpm_tests/p_lvemanager && ALT_TEST=base ALT_PACKAGE_NAME=lvemanager ALT_PACKAGE_VERSION=3.0 ALT_PACKAGE_RELEASE=11.el6.cloudlinux.21100.1.1505113712 ./01-prepare-environment.sh'"

e isso terminou perfeitamente e rápido com exit=0:

###
+ echo -e '* Prepare evironment    \033[0;32m[DONE]\033[0m'
* Prepare evironment    [DONE]
+ exit 0
Connection to 192.168.0.34 closed.

Boa.
Então executei outro comando:

ssh [email protected] "source /opt/centos/vars && su - -c 'cd /opt/QA/rpm_tests/p_lvemanager && ALT_TEST=base ALT_PACKAGE_NAME=lvemanager ALT_PACKAGE_VERSION=3.0 ALT_PACKAGE_RELEASE=11.el6.cloudlinux.21100.1.1505113712 ./01-prepare-environment.sh'"

Isso foi concluído tão rápido com exit=0 também:

###
+ echo -e '* Prepare evironment    \033[0;32m[DONE]\033[0m'
+ exit 0

Mas não há "Conexão com 192.168.0.36 fechada". Não sei se é importante ou não.

Depois disso, recriei VMs e lancei o comando pelo fabric2 (do IPython):

In [1]: from fabric import Connection
In [2]: Connection('[email protected]').run("source /opt/centos/vars && su - -c 'cd /opt/QA/rpm_tests/p_lvemanager && ALT_TEST=base ALT_PACKAGE_NAME=lvemanager ALT_PACKAGE_VERSION=3.0 ALT_PACKAGE_RELEASE=11.el6.cloudlinux.21100.1.1505113712 ./01-prepare-environment.sh'", pty=True)
....
+ echo -e '* Prepare evironment    \033[0;32m[DONE]\033[0m'
* Prepare evironment    [DONE]
+ exit 0
Out[2]: <Result cmd="source /opt/centos/vars && su - -c 'cd /opt/QA/rpm_tests/p_lvemanager && ALT_TEST=base ALT_PACKAGE_NAME=lvemanager ALT_PACKAGE_VERSION=3.0 ALT_PACKAGE_RELEASE=11.el6.cloudlinux.21100.1.1505113712 ./01-prepare-environment.sh'" exited=0>

Além disso, eu corri com pty=False:

In [1]: from fabric import Connection

In [2]: Connection('[email protected]').run("source /opt/centos/vars && su - -c 'cd /opt/QA/rpm_tests/p_lvemanager && ALT_TEST=base ALT_PACKAGE_NAME=lvemanager ALT_PACKAGE_VERSION=3.0 ALT_PACKAGE_RELEASE=11.el6.cloudlinux.21100.1.1505113712 ./01-prepare-environment.sh'", pty=False)
+ echo -e '* Prepare evironment    \033[0;32m[DONE]\033[0m'
+ exit 0
Out[2]: <Result cmd="source /opt/centos/vars && su - -c 'cd /opt/QA/rpm_tests/p_lvemanager && ALT_TEST=base ALT_PACKAGE_NAME=lvemanager ALT_PACKAGE_VERSION=3.0 ALT_PACKAGE_RELEASE=11.el6.cloudlinux.21100.1.1505113712 ./01-prepare-environment.sh'" exited=0>

Não havia "Conexão comfechado." em ambos os testes. Novamente, não sei se é importante ou não.

Em segundo lugar, decidi que não é um bom ambiente para o meu estande, pois preciso lançar do processo filho. Então, recriei as VMs novamente e executei o script com o próximo código:

In [1]: import subprocess

In [2]: t = subprocess.Popen(""" ssh [email protected] -t "source /opt/centos/vars && su - -c 'cd /opt/QA/rpm_tests/p_lvemanager && ALT_TEST=base ALT_PACKAGE_NAME=lvemanager ALT_PACKAGE_VERSION=3.0 ALT_PACKAGE_RELEASE=11.el6.cloudlinux.21100.1.1505113712 ./01-prepare-environment.sh'" """, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True); r = t.communicate()

Na saída desta execução havia "Conexão com 192.168.0.34 fechada".

Por outro lado

In [1]: import subprocess

In [2]: t = subprocess.Popen(""" ssh [email protected] "source /opt/centos/vars && su - -c 'cd /opt/QA/rpm_tests/p_lvemanager && ALT_TEST=base ALT_PACKAGE_NAME=lvemanager ALT_PACKAGE_VERSION=3.0 ALT_PACKAGE_RELEASE=11.el6.cloudlinux.21100.1.1505113712 ./01-prepare-environment.sh'" """, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True); r = t.communicate()

Ambos não foram enforcados.

Hoje à noite vou lançar meus scripts com fabric2 no processo que foi bifurcado e escreverei.
Atualizado Na verdade, foi meu erro no código. Portanto, fabric2 não contém enforcamento.

Seria bom obter suporte de $ use_sudo para Transfer.put .

Eu acho que a solução mais simples por enquanto é apenas fazer um put em algum lugar que eu tenha permissões, então um sudo mv ?

@ned2 isso é tudo que use_sudo pode realmente fazer em get / put de qualquer maneira, por exemplo, é como v1 faz isso. Na verdade, não é possível fazer upload de um arquivo "com sudo", tanto quanto sei! (Não sem conectar como root, o que é uma má ideia e, idealmente, nem é permitido.)

Dada a tentativa de ter uma API um pouco mais limpa na v2, é quase mais provável que eu implemente um wrapper em vez de agrupar esse comportamento dentro get / put . Talvez apenas algo como Transfer.sudo_put (que chamaria self.put ). Dessa forma, o put "puro" é mantido no mínimo.

@bitprophet Gostaria de começar agradecendo por alguns softwares bastante estáveis ​​e úteis com o Fabric1 e sua abordagem para lançar o Fabric2.

Comecei a brincar com a v2, mas tive um problema com o Connection. Estou usando minha configuração SSH do Fabric 1, o Fabric 1 me solicitaria uma senha ao tentar me conectar. O Fabric 2 não está fazendo isso e falha informando que a autenticação falhou. Não consigo ver em nenhum lugar nos documentos da v2 que menciona o mecanismo de autenticação para conexão. Há uma menção de senhas com sudo, mas pelo que posso perceber isso é depois que a conexão foi bem-sucedida de qualquer maneira.

Minha pergunta é se eu perdi alguma coisa nos documentos ou se esse é um recurso ausente ou um problema.

O código:

<strong i="10">@task</strong>
def testing(c):
    with Connection('MyHostname') as cxn:
        print("Connected")

        cxn.run('ls -l')

O erro:

  File /lib/python3.4/site-packages/paramiko/auth_handler.py", line 223, in wait_for_response
    raise e 
paramiko.ssh_exception.AuthenticationException: Authentication failed.

Minha configuração SSH (valores substituídos para postar aqui):

Host MyHostname
  HostName replacedhostname.co.uk
  Port 22
  IdentityFile ~/.ssh/id_rsa
  User replaceduser

Estou na versão v2 mais recente: https://github.com/fabric/fabric/commit/fec3a22ee89900500ae731913fd33f9b56e89f46

Espero que resolver isso ajude alguém com o mesmo problema.

Obrigado pelo seu tempo.

@ Aiky30 Provavelmente não é você, o material de autenticação ainda precisa de trabalho (em grande parte devido à necessidade de algum trabalho em andamento do Paramiko, para que as exceções de autenticação não sejam horrivelmente difíceis de interpretar corretamente.) Acho que neste caso pode ser simplesmente que Fab 2 não está interpretando IdentityFile - pegamos host, usuário, porta e várias outras configurações, mas IdentityFile ainda é um TODO.

Isso ocorre em parte porque também não lidamos com senhas no momento (veja acima - queremos evitar um grande truque do Fabric 1, onde temos que fazer suposições selvagens se uma determinada falha de autenticação significar que é necessária senha ou senha). Então você provavelmente faria a transição para um erro "Não consigo desbloquear este arquivo" depois disso. E ambos são porque eu uso um agente ssh na maioria das vezes - o que seria minha primeira sugestão para uma solução imediata.

Dito isso, acho que provavelmente vale a pena invadir o suporte de configuração de senha do IdentityFile e explícito, porque as chaves não-agentes são provavelmente a configuração de autenticação mais comum número 1, então falta provavelmente significa que a maioria dos usuários alfa/beta são deixados na mão . Vou ver se consigo fazer isso hoje.

Tomou 2.0a para dar uma volta.

1) Também estou um pouco perdido sobre como definir e usar hosts. Eu posso correr:

   fab -H user<strong i="7">@host</strong>:22 some-task

Mas se eu não quiser passar detalhes do host (usuário, host, porta) toda vez, não tenho certeza de como configurar hosts em fabfile.py ( Connection s ou Group ) e, em seguida, apenas consulte-os. Se eu entendi https://github.com/fabric/fabric/issues/1591#issuecomment -296343613 corretamente, ele não é suportado no momento (e rastreado em https://github.com/fabric/fabric/issues/1594 )?

2) Além disso, bati o problema em que criptografei a chave SSH (em ~/.ssh/id_rsa ) e tenho ssh-add para ssh-agent . Ele aparece se eu listar as chaves via ssh-add -l . Quando executo alguma tarefa, fornecendo o nome de usuário adequado:

   fab -H musttu<strong i="20">@host</strong> sometask

As coisas funcionam bem. Mas se eu usar usuário incorreto, por exemplo, fab -H bad_user<strong i="23">@host</strong> sometask , recebo:

Traceback (most recent call last): ... File "/home/maximus/.virtualenvs/testenv/lib/python3.6/site-packages/paramiko/pkey.py", line 326, in _read_private_key raise PasswordRequiredException('Private key file is encrypted') paramiko.ssh_exception.PasswordRequiredException: Private key file is encrypted

Mas presumo que se enquadre em https://github.com/paramiko/paramiko/issues/387 e não seja realmente específico para o fabric 2.0. Mas sim, parece estranho receber o erro PasswordRequiredException: Private key file is encrypted , quando o agente ssh já tem a chave descriptografada. Se entendi corretamente, após o login inválido, paramiko voltará a usar a chave diretamente e, sem a senha fornecida, lançará esse erro.

3) Seria bom permitir funções de tarefa de anotação de tipo (para melhor preenchimento automático no IDE). Você teve tempo para considerar https://github.com/pyinvoke/invoke/pull/458 ?

4) Gosto da ideia da biblioteca de retalhos. Para fabric 1.x, há https://github.com/sebastien/cuisine (que parece bem morto) que contém muitas funções extras (eu mesmo não usei). A ideia com patchwork é construir algo semelhante (portanto, funções declarativas no estilo Chef/Ansible/SaltStack, embora com escopo reduzido)? Eu sempre odiei a abordagem YAML/DSL de vários diretórios/vários arquivos que outras ferramentas seguem e gostaria de permanecer em python, para obter mais flexibilidade, sintaxe menos detalhada, preenchimento automático de IDE, depuração fácil etc.

5) Basta soltar o suporte py 2.6 e 3.2-3.3 para fabric 2.0. As pessoas não deveriam simplesmente seguir em frente?

@tuukkamustonen - obrigado pelo feedback! Respostas:

  1. As funções são realmente cobertas em # 1594 - e acho que há outro ticket para a questão relacionada de apenas ter dados de configuração por host, além de como o suporte ssh_config o faz em seu próprio nível.

    Decidir como exatamente reconciliar a configuração em nível de malha com ssh_config e também com qualquer coisa do Grupo ou dados de tempo de execução... não é trivial. Embora definitivamente precise acontecer em breve; Eu só quero ter uma solução meio pensada em vez de um primeiro rascunho.

  2. Novamente, sim, este é o ticket da Paramiko que você mencionou, e seu palpite é preciso, a situação do nome de usuário incorreto sempre falhará e, como a Paramiko rastreia apenas o último erro encontrado, acontece que a última coisa que tentou foi a cópia criptografada em disco da chave. (Se você moveu essa chave para outro lugar, por exemplo, o último erro seria outra coisa.)

  3. Acabei de comentar sobre esse ticket, ele pode (ou não) duplicar tickets existentes para o mesmo recurso geral. Eu comentei sobre os mais antigos e o IIRC é um "sim, acho que seria bom, desde que não estrague o Python 2". No entanto, não é tão alta prioridade quanto a maioria dos recursos ausentes maiores, por isso cai no bucket "precisa de um ótimo, todas as caixas marcadas PR que eu posso apenas mesclar" :)

  4. Sim, veja o nº 461, que é muito antigo, mas ainda está em minha mente. Atualmente, a grande questão é como tal lib seria escrita para abranger tanto o Invoke quanto o Fabric; em muitos/na maioria dos casos, pode-se simplesmente escrever tarefas Invoke genéricas que não "conhecem" quaisquer contextos locais/remotos divididos, que podem receber um contexto de conexão Fabric quando se deseja executá-las em um sistema remoto.

    Tais tarefas "agnósticas de contexto" gostariam de viver na biblioteca de 'invocações' (ou alguma outra lib ainda específica do Invoke); mas alguns (por exemplo, qualquer coisa que envolva transferência de arquivos e não apenas comandos de shell) precisariam ser "conscientes do tecido". Descobrir como preencher essa lacuna é o problema.

    Poderia seguir o caminho de "essa lib requer apenas invocar, não requer muito tecido, _mas_ um subconjunto de tarefas reclamará se você não instalar o tecido e entregar a eles um contexto de conexão". Poderia se dividir em duas libs (com a orientada a Fabric exigindo a mais genérica Invoke.) Etc.

  5. Recentemente, isso está definitivamente nos cartões, veja paramiko/paramiko#1070 e/ou pyinvoke/invoke#364. Invoke 1.0, Fabric 2.0 e Paramiko 3.0 (ou, _talvez_, um 2.4/2.5/whatever) serão todos Python 2.7/3.4 e superior.

Sobre (1):

Tenho certeza que você já sabe disso, mas você pode querer pegar algumas ideias dos inventários do Ansible . Ou talvez não :).

Sobre (4):

Acho que https://github.com/pyinvoke/invocations é muito opinativo para isso. As invocações fornecem _conventions_ e podem ser construídas em cima do pacote patchwork/cozinha, mas eu não misturaria convenções (como liberar ou doctest) com utilitários (como copiar arquivos ou alterar permissões).

Não vejo problema em colocar utils para operações somente locais, somente remotas e locais + remotas na mesma biblioteca (patchwork). Qual operação suporta qual modo pode ser abordado como documentação (como docstring, gerado automaticamente a partir de anotação, etc.).

Isso é melhor do que dividir a lógica em mais de 2 pacotes. Porque e se você primeiro adicionar uma operação ao seu pacote "somente invocação" (e pode haver até operações "somente remotas") e depois adicionar suporte para que ele funcione também em servidores remotos? Você moveria, copiaria ou estenderia o código? Em ambos os casos, é mais trabalho, e o usuário precisa de importação diferente, etc., então soa um pouco complicado.

O que posso fazer para que isso seja polido o suficiente para ir no PyPi?

@haydenflinner Vai acontecer na próxima semana ou duas!! (O objetivo é lançar antes de eu pegar meu avião para o PyCon, que é 10 de maio.)

Por exemplo, consulte os documentos de atualização recentemente atualizados nos quais eu estava trabalhando esta semana: http://docs.fabfile.org/en/v2/upgrading.html

Na verdade, eu posso fechar este ticket agora, já que estarei aceitando reais reais para 2.0.0 e acima em breve 👍

Observem, vocês ainda podem comentar aqui se quiserem. Observe que espero realizar pelo menos algumas partes do trabalho de recursos antes do lançamento, juntamente com toda a preparação do gerenciamento de projetos.

Eu olhei para o tecido v2 hoje e me desculpe, eu simplesmente não consigo usá-lo.

  1. Para onde foram os roledefs? Por que não posso mais passar um nome de função na linha de comando? Devo implementar isso sozinho?
  2. Por que não posso mais passar argumentos para tarefas na linha de comando? Eu deveria implementar isso sozinho também?
  3. Por que o parâmetro -H precisa vir antes do parâmetro tarefa? Deveria ser o contrário. Isso é tão horrível.

As tarefas aceitam argumentos, mas a sintaxe mudou. Consulte http://docs.pyinvoke.org/en/1.1/concepts/invoking-tasks.html#task -command-line-arguments

@dgarstang Você pode considerar adotar um tom mais neutro ou empático com pessoas que lhe dão seu trabalho gratuito! Só dizendo 😉

  1. Veja #1594, que IIRC está vinculado no documento de atualização
  2. @ploxiln te protege aqui
  3. (Parcialmente) veja #1772 que é mesclado para master e será lançado em breve; ele adiciona a capacidade de usar @task(hosts=xxx) .

(re: 3: Em termos de dar --hosts e amigos como se fossem argumentos por tarefa, isso é algo que eu poderia adicionar em algum momento, foi dividido se vale a pena. Semelhante a --help por tarefa

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

amezin picture amezin  ·  5Comentários

peteruhnak picture peteruhnak  ·  4Comentários

26huitailang picture 26huitailang  ·  3Comentários

TimotheeJeannin picture TimotheeJeannin  ·  3Comentários

bitprophet picture bitprophet  ·  6Comentários