Conexión a un host enumerado en ~ / .ssh / config cuando se usa Fabric

83

Tengo problemas para Fabricno reconocer los hosts que tengo ~/.ssh/config.

Mi fabfile.pyes el siguiente:

from fabric.api import run, env

env.hosts = ['lulu']

def whoami():
    run('whoami')

Correr $ fab whoamida:

[lulu] corre: whoami

Error fatal: la búsqueda de nombre falló para lulu

El nombre luluestá en mi ~/.ssh/config, así:

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

Mi primer pensamiento para resolver este está añadiendo algo así como lulu.luluque /etc/hosts(estoy en un Mac), pero luego tengo que pasar también en el archivo de identidad a Tela - y yo prefiero mantener mi autenticación (es decir ~/.ssh/config) separado de mi despliegue ( es decir fabfile.py).

Además, por cierto, si intenta conectarse a un host en el archivo hosts, fabric.contrib.projects.rsync_projectparece que no reconoce los 'puertos' en el hosts.env(es decir, si usa hosts.env = [lulu:2100]una llamada a rsync_projectparece intentar conectarse lulu:21).

¿Hay alguna razón por la que Fabric no reconoce este lulunombre?

Brian M. Hunt
fuente

Respuestas:

145

Desde la versión 1.4.0, Fabric usa su configuración ssh (en parte). Sin embargo, debe habilitarlo explícitamente, con

env.use_ssh_config = True

en algún lugar cerca de la parte superior de su fabfile. Una vez que haga esto, Fabric debería leer su configuración de ssh (de ~/.ssh/configforma predeterminada o de env.ssh_config_path).

Una advertencia: si usa una versión anterior a la 1.5.4, se producirá un aborto si env.use_ssh_configestá configurado pero no hay ningún archivo de configuración presente. En ese caso, puede utilizar una solución alternativa como:

if env.ssh_config_path and os.path.isfile(os.path.expanduser(env.ssh_config_path)):
    env.use_ssh_config = True
rbp
fuente
La respuesta originalmente comenzaba con "La respuesta aceptada está desactualizada" [ya que documentó el comportamiento anterior a 1.4.0]. He eliminado este prefacio, ya que mi respuesta fue aceptada en su lugar;) ¡Gracias!
rbp
9

Tenga en cuenta que esto también sucede cuando el nombre no está en /etc/hosts. Tuve el mismo problema y tuve que agregar el nombre de host tanto a ese archivo como a ~/.ssh/config.

MrD
fuente
5

actualización : esta respuesta ahora está desactualizada .


Actualmente, Fabric no es compatible con el archivo .ssh / config. Puede configurarlos en una función para luego llamar al cli, por ejemplo: fab production task; donde producción establece el nombre de usuario, el nombre de host, el puerto y la identidad ssh.

En cuanto al proyecto rsync, ahora debería tener la capacidad de configuración de puertos, si no, siempre puede ejecutar local ("rsync ...") ya que eso es esencialmente lo que hace la función contribuida.

Morgan
fuente
1
Establezca env.key_filename en la ruta completa de la clave privada. Además, si tiene problemas, consulte code.fabfile.org/issues/show/265 para conocer algunos problemas relacionados con esto.
tobych
1
Sí, ahora tiene soporte. (aunque era anterior a 1.0 cuando comenté) Nota para lectores posteriores.
Morgan
4

Se puede usar el siguiente código para leer la configuración (código original tomado 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
fuente
1
fabric 1.2+ usa la sshbiblioteca ( paramikofork):try: \n from ssh.config import SSHConfig \n except ImportError: \n from paramiko.config import SSHConfig
jfs
La biblioteca SSH se ha fusionado de nuevo con Paramiko, por ejemplofrom paramiko.config import SSHConfig
n8henrie