Fabric: c.put confusão sobre string vs objeto semelhante a arquivo no local

Criado em 14 mai. 2018  ·  6Comentários  ·  Fonte: fabric/fabric

De acordo com os documentos transfer.put () , devo ser capaz de fornecer o caminho local para um arquivo (como uma string) ou um objeto semelhante a um arquivo.

Ao usar o anterior (string), posso especificar no caminho remote apenas o diretório de destino. Isso é usado em alguns exemplos :

c.put('myfiles.tgz', '/opt/mydata')

Mas quando tento fazer o mesmo ( c.put('file.txt', '/home/me/dir') , sempre acabo com IOError: Failure , porque na verdade está se comportando como se o caminho local fosse um objeto semelhante a um arquivo e não uma string.

Ele falha especificamente em paramiko.transport.sftp.sftp._log: [chan 0] open('/home/me/dir', 'wb')

A solução é sempre fornecer o caminho completo, por exemplo

c.put('file.txt', '/home/me/dir/file.txt')

Mas isso é inconsistente com os documentos e exemplos.

Finalmente, ter que fornecer o caminho completo para $HOME é menos que o ideal, mas parece haver um problema para isso já # 1653

  • Testado em Windows 10
  • Fabric 2.0.0
  • Paramiko 2.4.1
  • Invoke 1.0.0
Bug Wart put()/get()

Todos 6 comentários

Alguma atualização sobre isso? Connection.put com remote como string de caminho de diretório atualmente aumenta IOError .

(Também obrigado por todo o trabalho em Fabric et al!)

Tecido 2.1.3
Paramiko 2.4.1
Invoke 1.0.0

Parece um bug legítimo, daremos uma olhada mais tarde. Patches (e testes! Uma vez que todos os nossos passam :( implicando que estamos perdendo alguns ...) bem-vindos.

Olhando para isso agora, não tenho certeza se o problema é a suposição de FLO, acho que, em vez disso, é apenas uma falta direta de implementação de munging de caminho remoto correto - em outras palavras, estamos pedindo ao servidor SFTP para abrir o diretório como um arquivo para gravar, em vez de adicionar o nome de base do arquivo local ao caminho do diretório remoto.

Log de depuração parcial do final do Fabric:

invoke.transfer.put: Massaged relative local path 'setup.py' into '/Users/jforcier/Code/oss/fabric/setup.py'
invoke.transfer.put: Uploading '/Users/jforcier/Code/oss/fabric/setup.py' to '/Users/jforcier/tmp/'
paramiko.transport.sftp.sftp._log: [chan 2] open(b'/Users/jforcier/tmp/', 'wb')

Em seguida, parte do traceback mostra que estamos lançando esse caminho de diretório em CMD_OPEN, em sftp_client.py :

t, msg = self._request(CMD_OPEN, filename, imode, attrblock)

O que eventualmente atinge o mesmo arquivo / classe de tratamento de erro em torno do que o servidor SFTP disse que estava errado com a operação IO (que é o motivo pelo qual é apenas "Falha", porque é claro que é ... AFAIK é culpa do OpenSSH.)


De qualquer forma, é hora de escrever alguns testes para provar isso e então descobrir se é uma lógica opa (eu pensei que _estávamos_ construindo um caminho anexado em algum ponto) ou uma parte real de funcionalidade ausente.

OK, não, todo o munging gira em torno de caminhos remotos vazios ou relativos, não há verificação do diretório is.

Enquanto estou aqui, me perguntando como lidar com FLOs também, no caso em que o caminho remoto é um diretório.

Na v1, vimos o atributo .name dos FLOs porque faz parte da API Python FLO ..._ but_ aparentemente apenas para fins de registro de depuração (em # 699). Opa. Eu examinei o código do nosso e do Paramiko e não vi nada usando isso como uma pista de "nome de arquivo".

De qualquer forma, aqui na v2 temos a oportunidade de resolver isso para reais, ou apenas lançar uma exceção explícita dizendo "uau, você precisa fornecer um caminho de arquivo remoto não-diretório para estes". Provavelmente ambos, uma vez que nem todos os FLOs necessariamente têm o atributo name de qualquer maneira.

OK, está tudo consertado, será lançado na próxima versão de correção de bugs 🎉

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