Fabric: Méta-ticket de rétroaction alpha/bêta Fabric 2 !

Créé le 21 avr. 2017  ·  28Commentaires  ·  Source: fabric/fabric

Assurez-vous d'abord d'avoir lu ce billet de blog et tous ses liens ! : http://bitprophet.org/blog/2017/04/17/fabric-2-alpha-beta


C'est l'endroit où laisser des commentaires pour les problèmes qui ne sont couverts par aucun des tickets existants ; veuillez d'abord rechercher les endroits ci-dessous !!


Vous ne trouvez rien de pertinent ? Laissez un commentaire ci-dessous! Je recherche des commentaires _similaires mais non limités à_ :

  • "Je refuse d'utiliser la 2.0 jusqu'à ce que vous reveniez au mode magique, global, non orienté objet !" (bien que je vais simplement vous lier à pyinvoke/invoke#186 et vous demander de fournir une justification là-bas ;))
  • "J'aime vraiment ce que vous avez fait avec $feature mais il manque $sub-feature, dont j'ai vraiment besoin ! Est-ce prévu ?" (Je dirai soit "oui", "non" ou "non", mais vous pouvez maintenant l'implémenter vous-même de manière triviale ! Il n'est pas nécessaire que ce soit dans le noyau !')
  • "J'aime vraiment ce que vous avez fait avec $feature mais la façon dont c'est configuré en ce moment, c'est difficile/impossible de faire $sub-use-case !" (Je vous demanderai probablement des détails et éventuellement un exemple de PR de l'API que vous aimeriez voir.)

Commentaire le plus utile

@haydenflinner Ça se passe au cours de la semaine ou des deux prochaines !! (Le but est de libérer avant de monter dans mon avion pour PyCon, le 10 mai.)

Par exemple, veuillez consulter les documents de mise à jour récemment mis à jour sur lesquels je travaillais cette semaine : http://docs.fabfile.org/en/v2/upgrading.html

En fait, je peux aussi bien fermer ce ticket maintenant, puisque j'accepterai bientôt les vrais pour 2.0.0 et plus 👍

Tous les 28 commentaires

Petite erreur dans l'URL, ça devrait être http://bitprophet.org/blog/2017/04/17/fabric-2-alpha-beta/

Cela montre à quel point je me souviens de mon propre site Web, hein ? Merci! J'ai même lancé un vérificateur de liens sur mon post, mais... pas contre ce ticket ;)

J'ai une proposition sur la façon dont le système roledefs de fabric 1 peut être mis en œuvre d'une manière qui, je pense, est conforme à la philosophie de fabric 2. Chaque Collection de tâches peut également avoir @group fonctions décorées dans le même espace de noms qui renvoient des objets Group remplis sur lesquels les tâches peuvent être exécutées. Les espaces de noms seraient importants, donc si fabfile.py contenait un Collection appelé deploy qui avait @group s appelés web et db , on peut utiliser deploy.web.execute(mytask) ou fab -G deploy.web mytask pour exécuter mytask sur chaque hôte du groupe web . Ces fonctions décorées seraient appelées paresseusement et mémorisées pour éviter les appels d'API inutiles, si une recherche de liste d'hôtes était une opération lente telle qu'implémentée par l'utilisateur.

Est-ce conforme à la philosophie de conception du tissu 2 ? J'adorerais me lancer dans la mise en œuvre si c'est le cas.

C'est une bonne idée, @RedKrieg ! J'ai reporté mon propre remue-méninges sur la "meilleure" façon de générer des objets de groupe et/ou de s'y référer sur la CLI, mais cela semble être une façon raisonnable de procéder. J'ai juste chié beaucoup trop de mots dans # 1594 et y ai inclus votre idée (+ un lien). Continuons la discussion là-bas, mais tl; dr oui, j'aimerais voir un PoC PR.

Quelle est la meilleure approche pour exécuter une commande localement malgré la présence de l'argument -H , par exemple si je veux combiner la construction locale et rsync vers l'hôte distant en une seule tâche ?

@max-arnold Les objets de connexion ont un attribut .local qui agit comme .run sur la machine locale : http://docs.fabfile.org/en/v2/api/connection.html#fabric .connexion.Connexion.local

Ok, je suppose qu'un exemple vaut mieux que des mots:

<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')

La tâche combinée s'exécute correctement :

fab -H host deploy

La tâche locale seule échoue avec AttributeError : Aucun attribut ou clé de configuration trouvé pour 'local' :

fab build

Fondamentalement, je veux avoir une tâche qui fait quelque chose localement, peu importe comment elle a été invoquée (avec ou sans -H ).

De l'autre côté, certaines commandes ne sont destinées qu'à s'exécuter à distance. Si aucun hôte n'est présent, ctx.run tentera de les exécuter localement, ce qui peut entraîner des conséquences inattendues.

| L'utilisateur exécute la tâche | L'auteur de la commande/tâche veut qu'elle soit exécutée | Comment doit-il se comporter ? |
|---------------------|------------------------------------- ---|----------------|
| localement | localement | Le comportement de run() est correct (mais violera l'intention de l'auteur s'il est exécuté à distance) |
| localement | à distance | Il devrait échouer (ou demander une chaîne d'hôte comme l'ancien tissu) |
|localement | localement ou à distance | le comportement de run() est correct |
| à distance | localement | Il doit toujours s'exécuter localement, mais Context n'a pas de méthode local() pour s'en assurer |
| à distance | à distance | Le comportement de run() est correct (mais des problèmes sont attendus lors de l'invocation locale) |
| à distance | localement ou à distance | le comportement de run() est correct |

@max-arnold c'est exactement #98 ! que je n'ai pas encore complètement résolu. Mettre quelques pensées modernes là-dedans comme commentaire... edit: celui-ci

J'ai remarqué ce qui semble être une incohérence avec sudo.

connection est un serveur distant, authentifié en tant que root.

Essayer de développer tilde en tant qu'utilisateur autre que root :

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

Cela réussit, mais plutôt que d'écrire /home/builder/foo, il a plutôt écrit /root/foo.

D'un autre côté, si j'essaie juste de ls:

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

Je reçois Permission denied .

Quelque chose ne va pas.

Je suppose que lorsque Dustin a signalé le hors bande ci-dessus, c'est qu'il s'agit d'une ride spécifique sudo (la commande, pas la méthode), depuis la dernière fois que j'ai regardé, nous utilisons -H et apparemment il ne se comporte pas à 100 % comme prévu.

Salut Jef,
puisque je travaille déjà en python 3, j'utilise actuellement fabric3 (le portage de fabric 1.x).

J'ai été tenté d'essayer la migration vers fabric 2, mais j'ai immédiatement frappé un bouchon de spectacle. J'utilise beaucoup les fonctions fabric.contrib , mais la documentation sur la migration indique qu'elle n'existe plus.

Bien sûr, je ne veux pas gonfler le code en revenant à son équivalent shell, et puisque, à en juger par le nombre de problèmes sur contrib.* de fabric 1.x, il semble qu'il soit beaucoup utilisé, je pense que c'est le manque pourrait être un sérieux obstacle à la migration pour beaucoup d'autres.
J'ai trouvé un projet de patchwork qui contient apparemment l'équivalent de fabric.contrib , mais son code n'est pas mis à jour depuis des années.
Avez-vous l'intention de transférer fabric.contrib vers Fabric 2 ?

Merci,
gabrielle

@garu57 Oui, le plan actuel est d'utiliser patchwork comme "contribution 2.0". Pour le moment, il est basé sur Fabric 1, mais cela changera après la sortie de Fabric 2.0.0. Je m'attends à ce que les bits de contribution les plus couramment utilisés soient transférés rapidement.

Salut à tous,

Parfois, mon programme exécute une commande à distance, par exemple

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'

Je vois que les scripts sont exécutés comme ça:

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

et je devrais aussi voir ma sortie de débogage "?" selon mon code :

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)

Mais il n'y a pas de "?". Je suggère donc qu'il y avait des accrochages dans le run().

En fait, mon programme est énorme et il y a de la programmation multi-processus. Pour attraper la pendaison, j'exécute des commandes à distance avec le code suivant :

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)

Lorsque j'utilise fabric2, certaines commandes lancées à partir de processus enfants se bloquent de temps en temps.
Mise à jour En fait, c'était mon erreur dans le code. Donc, fabric2 ne contient pas de pendaison

Bonjour tous le monde,
J'ai fait quelques expériences de lancement et je peux partager mon expérience.

Tout d'abord, j'ai exécuté la commande depuis ma 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'"

et cela s'est terminé parfaitement et rapidement avec exit=0 :

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

Bon.
Puis j'ai exécuté une autre commande :

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'"

Cela s'est terminé si vite avec exit=0 aussi :

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

Mais il n'y a pas "Connexion à 192.168.0.36 fermée". Je ne sais pas si c'est important ou pas.

Après cela, j'ai recréé des machines virtuelles et lancé la commande par fabric2 (depuis 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>

Aussi, j'ai couru avec 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>

Il n'y avait pas de "Connexion àfermé." sur les deux tests. Encore une fois, je ne sais pas si c'est important ou non.

Deuxièmement, j'ai décidé que ce n'était pas un bon environnement pour mon stand, car j'avais besoin d'un lancement à partir du processus enfant. J'ai donc recréé à nouveau les VM et exécuté le script avec le code suivant :

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()

Dans la sortie de cette exécution, il y avait "Connexion à 192.168.0.34 fermée".

D'autre part

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()

Les deux n'ont pas été pendus.

Ce soir je lancerai mes scripts avec fabric2 sur le processus qui a été forké et j'écrirai.
Mise à jour En fait, c'était mon erreur dans le code. Ainsi, fabric2 ne contient pas de pendaison.

Ce serait bien d'obtenir un support use_sudo pour Transfer.put .

Je suppose que la solution de contournement la plus simple pour l'instant consiste simplement à faire un put quelque part où j'ai des autorisations, puis un sudo mv ?

@ned2 c'est tout ce que use_sudo peut vraiment faire dans get / put toute façon, par exemple c'est comme ça que v1 le fait. Pas réellement possible de télécharger un fichier "avec sudo" pour autant que je sache! (Pas sans se connecter en tant que root, ce qui est une mauvaise idée et idéalement n'est même pas autorisé.)

Étant donné la tentative d'avoir une API un peu plus propre dans la v2, je suis presque plus susceptible d'implémenter un wrapper au lieu de regrouper ce comportement dans get / put eux-mêmes. Peut-être juste quelque chose comme Transfer.sudo_put (qui appellerait self.put ). De cette façon, le "pur" put est maintenu au minimum.

@bitprophet Je voudrais commencer par vous remercier pour certains logiciels assez stables et utiles avec Fabric1 et votre approche pour publier Fabric2.

J'ai commencé à jouer avec la v2 mais j'ai rencontré un problème avec Connection. J'utilise ma configuration SSH de Fabric 1, Fabric 1 me demanderait un mot de passe lors de la tentative de connexion. Fabric 2 ne le fait pas et échoue en indiquant que l'authentification a échoué. Je ne vois nulle part dans la documentation v2 qui mentionne le mécanisme d'authentification pour Connection. Il y a une mention de mots de passe avec sudo mais d'après ce que je peux comprendre, c'est après que la connexion a réussi de toute façon.

Ma question est de savoir si j'ai raté quelque chose dans la documentation ou s'il s'agit d'une fonctionnalité manquante ou d'un problème.

Le code:

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

        cxn.run('ls -l')

L'erreur:

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

Ma configuration SSH (valeurs remplacées à poster ici):

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

Je suis sur la dernière version v2 : https://github.com/fabric/fabric/commit/fec3a22ee89900500ae731913fd33f9b56e89f46

J'espère que la résolution de ce problème aidera quelqu'un d'autre avec le même problème.

Merci pour votre temps.

@ Aiky30 Ce n'est probablement pas vous, les éléments d'authentification ont encore besoin de travail (en grande partie en raison de la nécessité de certains travaux Paramiko en cours, de sorte que les exceptions d'authentification ne sont pas horriblement difficiles à interpréter correctement.) Je pense que dans ce cas, il se peut simplement que Fab 2 n'interprète pas IdentityFile - nous saisissons l'hôte, l'utilisateur, le port et un tas d'autres paramètres, mais IdentityFile est toujours un TODO.

C'est en partie parce que nous ne traitons pas non plus les phrases secrètes pour le moment (voir ci-dessus - nous voulons éviter un gros problème Fabric 1 où nous devons faire des suppositions folles si un échec d'authentification donné signifie qu'un mot de passe ou une phrase secrète est nécessaire). Donc, vous passeriez probablement simplement à une erreur "Je ne peux pas déverrouiller ce fichier" après cela. Et les deux sont dus au fait que j'utilise un agent ssh la plupart du temps - ce qui serait ma première suggestion pour une solution de contournement immédiate.

Cela dit, je pense que cela vaut probablement la peine de pirater à la fois IdentityFile et la prise en charge de la configuration de la phrase de passe explicite, car les clés non-agent sont probablement la configuration d'authentification la plus courante, donc leur absence signifie probablement que la plupart des utilisateurs alpha/bêta sont laissés pour compte. . Je vais voir si je peux le faire aujourd'hui.

A pris 2.0a pour un tour.

1) Je suis aussi un peu perdu sur la façon de définir et d'utiliser les hôtes. Je peux courir:

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

Mais si je ne veux pas transmettre les détails de l'hôte (utilisateur, hôte, port) à chaque fois, je ne sais pas comment configurer les hôtes dans fabfile.py ( Connection s ou Group ) puis faites simplement référence à eux. Si j'ai bien compris https://github.com/fabric/fabric/issues/1591#issuecomment -296343613, il n'est tout simplement pas pris en charge pour le moment (et suivi dans https://github.com/fabric/fabric/issues/1594 ) ?

2) De plus, j'ai rencontré un problème où j'ai une clé SSH cryptée (à ~/.ssh/id_rsa ) et j'ai ssh-add 'd cela à ssh-agent . Il apparaît si je liste les clés via ssh-add -l . Lorsque j'exécute une tâche, je donne le nom d'utilisateur approprié :

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

Les choses fonctionnent bien. Mais si j'utilise un utilisateur incorrect, par exemple fab -H bad_user<strong i="23">@host</strong> sometask , alors j'obtiens:

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

Mais je suppose que cela relève de https://github.com/paramiko/paramiko/issues/387 et n'est pas vraiment spécifique au tissu 2.0. Mais oui, ça fait bizarre d'avoir une erreur PasswordRequiredException: Private key file is encrypted , alors que l'agent ssh a déjà la clé déchiffrée. Si j'ai bien compris, après une connexion invalide, paramiko utilisera directement la clé, et sans la phrase de passe fournie, cette erreur sera générée.

3) Ce serait bien d'autoriser les fonctions de tâche d'annotation de type (pour une meilleure auto-complétion dans l'IDE). Avez-vous eu le temps de considérer https://github.com/pyinvoke/invoke/pull/458 ?

4) J'aime l'idée de bibliothèque patchwork. Pour fabric 1.x, il y a https://github.com/sebastien/cuisine (qui semble assez mort) qui contient beaucoup de fonctions supplémentaires (je ne l'ai pas utilisé moi-même). L'idée avec patchwork est-elle de construire quelque chose de similaire (donc des fonctions déclaratives de style Chef/Ansible/SaltStack, mais avec une portée réduite) ? J'ai toujours détesté l'approche YAML/DSL multi-répertoires/multi-fichiers suivie par d'autres outils, et j'aimerais simplement rester en python, pour obtenir plus de flexibilité, une syntaxe moins détaillée, une auto-complétion IDE, un débogage facile, etc.

5) Supprimez simplement la prise en charge de py 2.6 et 3.2-3.3 pour fabric 2.0. Les gens ne devraient-ils pas simplement passer à autre chose ?

@tuukkamustonen - merci pour les commentaires ! Réponses :

  1. Les rôles sont en effet couverts sous # 1594 - et je pense qu'il existe un autre ticket pour le problème connexe d'avoir simplement des données de configuration par hôte, à part la façon dont le support ssh_config le fait à son propre niveau.

    Décider comment concilier exactement la configuration au niveau de la structure avec ssh_config , puis également avec tout ce qui concerne les données de groupe ou d'exécution... n'est pas trivial. Bien que cela doive certainement arriver bientôt; Je veux juste avoir une solution à moitié réfléchie au lieu d'une première ébauche.

  2. Encore une fois, oui, c'est le ticket Paramiko que vous avez mentionné, et votre supposition est exacte, la situation de mauvais nom d'utilisateur finira toujours par échouer, et puisque Paramiko ne suit que la dernière erreur rencontrée, il se trouve que la dernière chose qu'il a essayé était la copie chiffrée sur disque de la clé. (Si vous avez déplacé cette clé ailleurs, par exemple, la dernière erreur serait autre chose.)

  3. Je viens de commenter ce ticket, il peut (ou non) dupliquer des tickets existants pour la même fonctionnalité globale. J'ai commenté ces plus anciens et IIRC c'est un "oui je pense que ce serait bien tant qu'il n'encrasse pas Python 2." Cependant, ce n'est pas une priorité aussi élevée que la plupart des plus grandes fonctionnalités manquantes, donc cela tombe dans le seau "a besoin d'un excellent PR, toutes les cases cochées que je peux simplement fusionner" :)

  4. Oui, voir #461 qui est très vieux mais toujours dans ma tête. De nos jours, la grande question est de savoir comment une telle bibliothèque serait écrite pour couvrir à la fois Invoke et Fabric ; dans de nombreux/la plupart des cas, on peut simplement écrire des tâches Invoke génériques qui ne "connaissent" aucun contexte local/distant divisé, qui peut recevoir un contexte de connexion Fabric lorsque l'on veut les exécuter sur un système distant.

    De telles tâches "indépendantes du contexte" voudraient vivre dans la bibliothèque "invocations" (ou dans une autre bibliothèque encore spécifique à Invoke); mais certains (par exemple, tout ce qui concerne le transfert de fichiers et pas seulement les commandes shell) devraient être "conscients de Fabric". Trouver comment combler cet écart est le problème.

    Pourrait suivre la voie de "cette bibliothèque ne nécessite qu'une invocation, ne nécessite pas de tissu, _mais_ un sous-ensemble de tâches se plaindra si vous n'installez pas de tissu et ne leur donnez pas un contexte de connexion." Pourrait se diviser en deux bibliothèques (avec celle orientée Fabric nécessitant la plus générique Invoke.) Etc.

  5. Depuis peu, c'est définitivement dans les cartes, voir paramiko/paramiko#1070 et/ou pyinvoke/invoke#364. Invoke 1.0, Fabric 2.0 et Paramiko 3.0 (ou, _peut-être_, un 2.4/2.5/peu importe) seront tous Python 2.7 / 3.4 et plus.

À propos de (1) :

Je suis sûr que vous le savez déjà, mais vous voudrez peut-être extraire quelques idées des inventaires d'Ansible . Ou peut être pas :).

À propos de (4) :

Je pense que https://github.com/pyinvoke/invocations est bien trop opiniâtre pour cela. Les invocations fournissent des _conventions_ et peuvent s'appuyer sur un package de style patchwork/cuisine, mais je ne mélangerais pas les conventions (comment publier ou doctest) avec des utilitaires (comment copier un fichier ou modifier les autorisations).

Je ne vois aucun problème à placer des utilitaires pour les opérations locales uniquement, distantes uniquement et locales + distantes dans la même bibliothèque (patchwork). Quelle opération prend en charge quel mode peut être abordé comme documentation (comme docstring, généré automatiquement à partir d'une annotation, etc.).

Cela semble mieux que de diviser la logique en 2+ packages. Car que se passe-t-il si vous ajoutez d'abord une opération à votre package "invoke-only" (et il pourrait même y avoir des opérations "remote-only"), puis ajoutez ensuite la prise en charge pour qu'elle fonctionne également sur des serveurs distants ? Déplaceriez-vous, copieriez-vous ou étendriez-vous le code ? Dans les deux cas, c'est plus de travail et l'utilisateur a besoin d'une importation différente, etc., donc cela semble un peu lourd.

Que puis-je faire pour que cela soit suffisamment poli pour aller sur PyPi ?

@haydenflinner Ça se passe au cours de la semaine ou des deux prochaines !! (Le but est de libérer avant de monter dans mon avion pour PyCon, le 10 mai.)

Par exemple, veuillez consulter les documents de mise à jour récemment mis à jour sur lesquels je travaillais cette semaine : http://docs.fabfile.org/en/v2/upgrading.html

En fait, je peux aussi bien fermer ce ticket maintenant, puisque j'accepterai bientôt les vrais pour 2.0.0 et plus 👍

Notez que vous pouvez toujours commenter ici si vous le souhaitez. Notez que j'espère obtenir au moins quelques morceaux de travail sur les fonctionnalités avant la sortie, en plus de toute la préparation de la gestion de projet.

J'ai regardé fabric v2 aujourd'hui et je suis désolé, je ne peux tout simplement pas me résoudre à l'utiliser.

  1. Où est passé roledefs ? Pourquoi ne puis-je plus passer un nom de rôle sur la ligne de commande ? Suis-je censé implémenter cela moi-même ?
  2. Pourquoi ne puis-je plus passer d'arguments aux tâches sur la ligne de commande ? Suis-je censé le mettre en œuvre moi-même également ?
  3. Pourquoi le paramètre -H doit-il précéder le paramètre task ? Il devrait être l'inverse. C'est tellement horrible.

Les tâches prennent des arguments, mais la syntaxe a changé. Voir http://docs.pyinvoke.org/en/1.1/concepts/invoking-tasks.html#task -command-line-arguments

@dgarstang Vous voudrez peut-être envisager de prendre un ton plus neutre ou empathique avec les gens qui vous donnent leur travail gratuitement ! Je dis juste 😉

  1. Voir #1594, auquel IIRC est lié dans la documentation de mise à niveau
  2. @ploxiln vous soutient ici
  3. (En partie) voir #1772 qui est fusionné avec master et qui sortira bientôt ; il ajoute la possibilité d'utiliser @task(hosts=xxx) .

(re : 3 : En termes de don de --hosts et d'amis comme s'il s'agissait d'arguments par tâche, c'est quelque chose que je pourrais ajouter de temps en temps, j'ai été déchiré quant à savoir si cela en valait la peine. Similaire à par tâche --help , plus nous ajoutons d'exclusions "magiques", plus il y a de chances qu'un utilisateur essaie d'utiliser ce même nom pour ses propres arguments de tâche et soit confus lorsqu'il se casse.)

Cette page vous a été utile?
0 / 5 - 0 notes