2010-07-19 21 views
8

Est-il possible de rendre le fabfile autonome?
Je ne suis pas très friand de l'outil externe 'fab'. Si je parviens à obtenir la version autonome de fabfile je peux exécuter le fichier à partir de la (Eclipse/Pydev) IDE, déboguer facilement, utiliser des configurations de projet et chemins, etc.
Pourquoi pas ce travail:Fabfile autonome pour le tissu?

from fabric.api import run 

def host_type(): 
    run('uname -s') 

if __name__ == '__main__': 
    host_type()  

Répondre

13


Dans mon fabfile, j'ai ajouté:

from fabric.main import main 

if __name__ == '__main__': 
    import sys 
    sys.argv = ['fab', '-f', __file__, 'update_server'] 
    main() 

J'espère que cela aide les gens ...

+0

Est-ce que cela engendre un sous-processus comme la solution de muksie? La principale raison pour laquelle j'explorais cette question est que les sous-processus supplémentaires sont quelque chose que nous voulons éliminer. –

+1

Si vous modifiez votre affectation sys.argv, cela fonctionnera avec n'importe quel ensemble de commandes. sys.argv [0] est déjà le nom du script, donc: sys.argv = ['fab', '-f'] + sys.argv – mqsoh

+0

Cela fonctionne tant que le fichier porte l'extension '.py'. Je n'ai pas encore trouvé le moyen de le faire fonctionner pour n'importe quelle extension. – Wernight

2

ce n'est pas une solution vraiment agréable, mais fonctionnera:

import subprocess 

def hello(): 
    print 'Hello' 

if __name__ == '__main__': 
    subprocess.call(['fab', '-f', __file__, 'hello']) 
+0

Oui, pas vraiment sympa (mais très original + 1!). De même, n'aborde pas stdio (par exemple une invite interactive pour un mot de passe (que je suppose résolu)). –

+0

Hijacking le commentaire haut de dire que dans les dernières versions de la structure, vous pouvez utiliser la commande 'execute' au lieu de' subprocess.call' http://fabric.readthedocs.org/fr/1.4.3/usage/execution.html# exécuter. – tutuca

3

Si je me souviens bien, je ne pouvais pas obtenir l'API de tissu pour faire ce que je voulais soit. J'ai décidé d'abandonner la couche supplémentaire entièrement et utiliser Paramiko (la bibliothèque SSH sous-jacente utilisée par tissu) directement:

import os 
import paramiko 

ssh = paramiko.SSHClient() 
ssh.load_system_host_keys() 
ssh.load_host_keys(os.path.expanduser('~/.ssh/known_hosts')) 
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
ssh.connect('hostname.example.com', 22, 'username', 'password') 
ssh.save_host_keys(os.path.expanduser('~/.ssh/known_hosts')) 
stdin, stdout, stderr = ssh.exec_command('uname -s') 
print stdout.read() 

Bien qu'il existe quelques étapes, cette façon de faire vous permet de tirer parti de la couche SSH directement , par opposition à l'utilisation de subprocess pour spwan une autre instance de Python ou pour déterminer l'API Fabric. J'ai plusieurs projets, à la fois sur le web et sur console, en utilisant Paramiko de cette manière et je n'ai pas eu trop de problèmes.

Paramiko est extensively documented. J'ai fini par trouver la solution (et c'est vraiment simple!)

+0

Malheureusement, c'est la meilleure réponse pour moi. Merci! –

2

Je peaufiné l'exemple ci-dessus passé par des arguments argv vous pouvez passer aux commandes locales et spécifier un liste default_commands facultative au lieu d'un nom de commande codée en dur. Notez que le nom de fichier doit avoir une extension .py ou fab ne le détectera pas comme un fichier fab!

#!/usr/bin/env python 
from fabric.api import local 

default_commands = ['hello', ] 

def hello(): 
    print ('hello world') 

def hostname(): 
    local('hostname') 

if __name__ == '__main__': 
    import sys 
    from fabric.main import main 
    sys.argv = ['fab', '-f', __file__,] + default_commands + sys.argv[1:] 
    main() 
2

docs.fabfile.org/en/1.4.0/usage/library.html

« Comme cette section mentionne, la clé est tout simplement cette course, et les autres sudo opérations seulement regarder dans Un seul endroit lors de la connexion: env.host_string Tous les autres mécanismes de configuration des hôtes sont interprétés par l'outil fab lors de son exécution, et n'a pas d'importance lors de l'exécution en tant que bibliothèque. "

Je regardais ce même problème quand je l'ai trouvé. Aussi, tout en regardant je me souviens de mentionner que lorsqu'il est utilisé dans un fabfile, les changements d'env ne devraient pas être dans le même def que courir, sudo. Qui sait si cela s'applique encore en mode "bibliothèque"?

EDIT: Voici un exemple de ladite mise en œuvre

from fabric.api import env, run 

def main(): 
    run("uname -a") 

def setup(): 
    env.host_string = "[email protected]" 

if __name__ == '__main__': 
    setup() 
    main() 
2
# thanks to aaron, extending his code a little more 
# here is a little bit more of a graceful solution than running subprocess.call, and specifying multiple hosts 

from fabric.api import env, run 

def main(): 
    run("uname -a") 

def setup(): 
    env.hosts = ['host0','host1'] 

if __name__ == '__main__': 
    setup() 
    for host in env.hosts: 
     env.host_string = host 
     main() 
1

Ajouter ce au fond de votre fichier fab.

if __name__ == '__main__': 
    from fabric.main import main 
    import sys 

    sys.argv = ['fab', '-f', __file__] + sys.argv[1:] 

    main() 
2

Depuis 1.5.0 il y a une façon meilleure façon de le faire que de déconner avec argv.

import fabric.main 

def main(): 
    fabric.main.main(fabfile_locations=[__file__]) 

if __name__ == "__main__": 
    main() 

Cela peut aussi être utilisé comme un script de console dans setup.py

0

Ceci est ma version modifiée de Greg's answer qui modifie le comportement par défaut pour afficher les commandes disponibles au lieu de la liste des tonnes d'options de tissu.

if __name__ == '__main__': 
    # imports for standalone mode only 
    import sys, fabric.main 

    # show available commands by default 
    if not sys.argv[1:]: 
     sys.argv.append('--list') 

    fabric.main.main(fabfile_locations=[__file__])