Conectando-se a um host listado em ~ / .ssh / config ao usar o Fabric

83

Estou tendo problemas em Fabricnão reconhecer os hosts que tenho em ~/.ssh/config.

Meu fabfile.pyé o seguinte:

from fabric.api import run, env

env.hosts = ['lulu']

def whoami():
    run('whoami')

Correr $ fab whoamidá:

[lulu] run: whoami

Erro fatal: a pesquisa de nome falhou para lulu

O nome luluestá no meu ~/.ssh/config, assim:

Host lulu
     hostname 192.168.100.100
     port 2100
     IdentityFile ~/.ssh/lulu-key

Meu primeiro pensamento para resolver este está adicionando algo como lulu.lulua /etc/hosts(eu estou em um Mac), mas então eu tenho que passar também no arquivo de identidade de tecido - e eu prefiro manter a minha autenticação (ie ~/.ssh/config) separada da minha implantação ( ie fabfile.py).

Também, aliás, se você tentar se conectar a um host no arquivo hosts, fabric.contrib.projects.rsync_projectnão parece reconhecer as 'portas' no hosts.env(ou seja, se você usar hosts.env = [lulu:2100]uma chamada para, rsync_projectparece tentar se conectar a lulu:21).

Existe um motivo pelo qual o Fabric não reconhece esse lulunome?

Brian M. Hunt
fonte

Respostas:

145

Desde a versão 1.4.0, o Fabric usa sua configuração ssh (parcialmente). No entanto, você precisa ativá-lo explicitamente, com

env.use_ssh_config = True

em algum lugar próximo ao topo do seu fabfile. Depois de fazer isso, o Fabric deve ler sua configuração de ssh ( ~/.ssh/configpor padrão ou de env.ssh_config_path).

Um aviso: se você usar uma versão anterior a 1.5.4, um aborto ocorrerá se env.use_ssh_configestiver definido, mas não houver nenhum arquivo de configuração presente. Nesse caso, você pode usar uma solução alternativa como:

if env.ssh_config_path and os.path.isfile(os.path.expanduser(env.ssh_config_path)):
    env.use_ssh_config = True
rbp
fonte
A resposta originalmente começava com "A resposta aceita está desatualizada" [já que documentou o comportamento anterior à 1.4.0]. Eu removi este prefácio, já que minha resposta foi aceita;) Obrigado!
rbp
9

Observe que isso também acontece quando o nome não está incluído /etc/hosts. Eu tive o mesmo problema e tive que adicionar o nome do host a esse arquivo e ~/.ssh/config.

MrD
fonte
5

atualização : Esta resposta está desatualizada .


O Fabric não tem suporte atualmente para o arquivo .ssh / config. Você pode configurá-los em uma função para então chamar o cli, por exemplo: tarefa de produção fab; onde a produção define o nome de usuário, nome do host, porta e identidade ssh.

Quanto ao projeto rsync, que agora deve ter capacidade de configuração de porta, se não, você sempre pode executar local ("rsync ..."), pois é essencialmente isso que a função de contribuição faz.

Morgan
fonte
1
Defina env.key_filename como o caminho completo da chave privada. Além disso, se você tiver problemas, consulte code.fabfile.org/issues/show/265 para alguns problemas em torno disso.
tobych de
1
Sim, agora tem suporte. (embora fosse antes de 1.0 quando comentei) Notando para leitores posteriores.
Morgan
4

Pode-se usar o seguinte código para ler a configuração (código original retirado de: http://markpasc.typepad.com/blog/2010/04/loading-ssh-config-settings-for-fabric.html ):

from fabric.api import *
env.hosts = ['servername']

def _annotate_hosts_with_ssh_config_info():
    from os.path import expanduser
    from paramiko.config import SSHConfig

    def hostinfo(host, config):
        hive = config.lookup(host)
        if 'hostname' in hive:
            host = hive['hostname']
        if 'user' in hive:
            host = '%s@%s' % (hive['user'], host)
        if 'port' in hive:
            host = '%s:%s' % (host, hive['port'])
        return host

    try:
        config_file = file(expanduser('~/.ssh/config'))
    except IOError:
        pass
    else:
        config = SSHConfig()
        config.parse(config_file)
        keys = [config.lookup(host).get('identityfile', None)
            for host in env.hosts]
        env.key_filename = [expanduser(key) for key in keys if key is not None]
        env.hosts = [hostinfo(host, config) for host in env.hosts]

        for role, rolehosts in env.roledefs.items():
            env.roledefs[role] = [hostinfo(host, config) for host in rolehosts]

_annotate_hosts_with_ssh_config_info()
jmu
fonte
1
fabric 1.2+ usa sshbiblioteca ( paramikofork):try: \n from ssh.config import SSHConfig \n except ImportError: \n from paramiko.config import SSHConfig
jfs
A biblioteca SSH foi incorporada de volta ao Paramiko, por exemplofrom paramiko.config import SSHConfig
n8henrie