Fabric: Fabric 2 Alpha/Beta-Feedback-Metaticket!

Erstellt am 21. Apr. 2017  ·  28Kommentare  ·  Quelle: fabric/fabric

Bitte stellen Sie sicher, dass Sie zuerst diesen Blogbeitrag und alle seine Links gelesen haben!: http://bitprophet.org/blog/2017/04/17/fabric-2-alpha-beta


Dies ist der Ort, an dem Sie Feedback zu Problemen hinterlassen können, die von keinem der vorhandenen Tickets abgedeckt werden. Bitte suchen Sie zuerst an den folgenden Orten !!


Nichts Passendes gefunden? Hinterlasse unten einen Kommentar! Ich suche nach Feedback _ähnlich, aber nicht beschränkt auf_:

  • "Ich weigere mich, 2.0 zu verwenden, bis Sie wieder in den magischen, globalen, nicht objektorientierten Modus wechseln!" (obwohl ich Sie nur mit pyinvoke/invoke#186 verlinken und Sie bitten werde, dort eine Begründung anzugeben;))
  • "Ich mag wirklich, was du mit $feature gemacht hast, aber es fehlt $sub-feature, das ich wirklich brauche! Ist das geplant?" (Ich sage entweder 'ja', 'nein' oder 'nein', aber Sie können es jetzt trivialerweise selbst implementieren! Es muss nicht im Kern sein!')
  • "Mir gefällt wirklich, was Sie mit $feature gemacht haben, aber so wie es jetzt eingerichtet ist, ist es schwer/unmöglich, $sub-use-case zu machen!" (Ich werde Sie wahrscheinlich nach Details fragen und möglicherweise nach einer Beispiel-PR der API fragen, die Sie sehen möchten.)

Hilfreichster Kommentar

@haydenflinner Es passiert in den nächsten ein oder zwei Wochen!! (Ziel ist die Veröffentlichung, bevor ich in mein Flugzeug zur PyCon steige, das ist der 10. Mai.)

Sehen Sie sich zum Beispiel die kürzlich aktualisierten Upgrade-Dokumente an, an denen ich gerade diese Woche gearbeitet habe: http://docs.fabfile.org/en/v2/upgrading.html

Tatsächlich kann ich dieses Ticket jetzt genauso gut schließen, da ich bald echte echte Tickets für 2.0.0 und höher akzeptieren werde 👍

Alle 28 Kommentare

Kleiner Fehler in der URL, es sollte http://bitprophet.org/blog/2017/04/17/fabric-2-alpha-beta/ sein

Das zeigt, wie gut ich mich an meine eigene Website erinnere, oder? Danke! Ich habe sogar einen Link-Checker für meinen Beitrag durchgeführt, aber ... nicht gegen dieses Ticket ;)

Ich habe einen Vorschlag, wie das Roledefs-System von Fabric 1 so implementiert werden kann, dass es meiner Meinung nach mit der Philosophie von Fabric 2 übereinstimmt. Jede Collection von Aufgaben kann auch @group eingerichtete Funktionen im selben Namespace haben, die gefüllte Group Objekte zurückgeben, für die Aufgaben ausgeführt werden können. Namespaces würden eine Rolle spielen, wenn also fabfile.py ein Collection namens deploy enthalten würde, das @group s namens web und db hätte , könnte man deploy.web.execute(mytask) oder fab -G deploy.web mytask verwenden, um mytask auf jedem Host in der Gruppe web auszuführen. Diese dekorierten Funktionen würden träge aufgerufen und gespeichert werden, um unnötige API-Aufrufe zu vermeiden, falls eine Hostlistensuche eine langsame Operation ist, wie sie vom Benutzer implementiert wird.

Entspricht das der Designphilosophie für Stoff 2? Wenn ja, würde ich gerne die Umsetzung in Angriff nehmen.

Das ist eine nette Idee, @RedKrieg! Ich habe mein eigenes Brainstorming darauf verschoben, wie "am besten" Gruppenobjekte generiert und/oder auf sie in der Befehlszeilenschnittstelle verwiesen werden kann, aber auf den ersten Blick klingt das nach einem vernünftigen Weg. Ich habe einfach viel zu viele Worte in #1594 geschissen und Ihre Idee dort eingefügt (+ einen Link). Lassen Sie uns die Diskussion dort fortsetzen, aber tl;dr ja, ich würde gerne eine PoC-PR sehen.

Was ist der beste Ansatz, um einen Befehl lokal auszuführen, obwohl das Argument -H vorhanden ist, z. B. wenn ich lokales Build und rsync auf Remote-Host in einer einzigen Aufgabe kombinieren möchte?

@max-arnold Connection-Objekte haben ein .local -Attribut, das sich auf dem lokalen Rechner wie .run verhält: http://docs.fabfile.org/en/v2/api/connection.html#fabric .Verbindung.Verbindung.lokal

Ok, ich denke, ein Beispiel ist besser als Worte:

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

Kombinierte Aufgabe läuft gut:

fab -H host deploy

Nur die lokale Aufgabe schlägt fehl mit AttributeError: No attribute or config key found for 'local':

fab build

Grundsätzlich möchte ich eine Aufgabe haben, die lokal etwas ausführt, egal wie sie aufgerufen wurde (mit oder ohne -H ).

Auf der anderen Seite sind einige Befehle nur für die Remote-Ausführung vorgesehen. Wenn kein Host vorhanden ist, wird ctx.run versuchen, sie lokal auszuführen, was zu unerwarteten Folgen führen kann.

| Benutzer führt Aufgabe | aus Der Autor des Befehls/der Aufgabe möchte, dass er ausgeführt wird | Wie soll es sich verhalten? |
|---------------------|---------------------- ---|----------------|
| lokal | lokal | Das Verhalten von run() ist in Ordnung (verstößt aber gegen die Absicht des Autors, wenn es remote ausgeführt wird) |
| lokal | aus der Ferne | Es sollte fehlschlagen (oder nach Host-String fragen, wie es die alte Fabric getan hat) |
|lokal | lokal oder remote | run() Verhalten ist in Ordnung |
| aus der Ferne | lokal | Es sollte immer lokal ausgeführt werden, aber Context hat keine Methode local(), um dies sicherzustellen |
| aus der Ferne | aus der Ferne | Das Verhalten von run() ist in Ordnung (es werden jedoch Probleme beim lokalen Aufruf erwartet) |
| aus der Ferne | lokal oder remote | run() Verhalten ist in Ordnung |

@max-arnold das ist genau #98! die ich eigentlich noch nicht vollständig gelöst habe. Ein paar moderne Gedanken als Kommentar einfügen ... edit: this one

Mir ist aufgefallen, dass es bei sudo zu Inkonsistenzen kommt.

Wobei connection ein Remote-Server ist, der als Root authentifiziert ist.

Versuch, Tilde als ein anderer Benutzer als root zu erweitern:

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

Dies gelingt, aber anstatt /home/builder/foo zu schreiben, wurde stattdessen /root/foo geschrieben.

Auf der anderen Seite, wenn ich nur versuche, ls:

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

Ich bekomme Permission denied .

Etwas fühlt sich an.

Meine Vermutung, als Dustin das obige Out-of-Band berichtete, war, dass dies eine sudo (der Befehl, nicht die Methode) spezifische Falte ist, da ich das letzte Mal nachgesehen habe, dass wir -H verwenden und anscheinend es verhält sich nicht zu 100 % so, wie wir es erwarten.

Hallo Jeff,
da ich bereits in python 3 arbeite, verwende ich im moment fabric3 (die portierung von fabric 1.x).

Ich war versucht, die Migration zu Fabric 2 zu versuchen, aber ich traf sofort einen Showstopper. Ich mache ausgiebigen Gebrauch von fabric.contrib -Funktionen, aber das Migrationsdokument sagt, dass es nicht mehr existiert.

Natürlich möchte ich den Code nicht aufblähen, indem er zu seinem Shell-Äquivalent zurückkehrt, und da es nach der Anzahl der Probleme auf contrib.* von Fabric 1.x zu urteilen scheint, wird es häufig verwendet, denke ich Mangel könnte für viele andere ein ernsthaftes Hindernis für die Migration sein.
Ich habe ein Patchwork -Projekt gefunden, das anscheinend das Äquivalent von fabric.contrib enthält, aber sein Code wird seit Jahren nicht mehr aktualisiert.
Haben Sie vor, fabric.contrib auf Fabric 2 zu portieren?

Danke,
Gabriele

@ garu57 Ja, im Moment ist geplant, patchwork im Grunde als "Beitrag von 2.0" zu verwenden. Im Moment basiert es auf Fabric 1, aber das wird sich ändern, wenn Fabric 2.0.0 herauskommt. Ich gehe davon aus, dass die am häufigsten verwendeten Beitragsbits schnell portiert werden.

Hallo allerseits,

Manchmal führt mein Programm einen Remote-Befehl aus, z

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'

Ich sehe, dass Skripte so ausgeführt werden:

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

und ich sollte auch meine Debug-Ausgabe "?" nach meinem 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)

Aber es gibt keine "?". Also schlage ich vor, dass es im Lauf hängt ().

Eigentlich ist mein Programm riesig und es gibt Multi-Prozess-Programmierung. Um das Hängen zu fangen, führe ich Remote-Befehle mit dem folgenden Code aus:

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)

Wenn ich fabric2 verwende, hängen einige Befehle, die von untergeordneten Prozessen gestartet werden, von Zeit zu Zeit.
Aktualisiert Eigentlich war es mein Fehler im Code. Stoff2 enthält also kein Hängen

Hallo zusammen,
Ich habe einige Startexperimente durchgeführt und kann meine Erfahrungen teilen.

Zuerst habe ich den Befehl von meiner Konsole aus ausgeführt

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

und das endete perfekt und schnell mit exit=0:

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

Gut.
Dann habe ich einen anderen Befehl ausgeführt:

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

Das war mit exit=0 auch so schnell erledigt:

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

Aber es gibt nicht "Verbindung zu 192.168.0.36 geschlossen". Ich weiß nicht, ob es wichtig ist oder nicht.

Danach habe ich VMs neu erstellt und den Befehl von fabric2 (von IPython) gestartet:

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>

Außerdem lief ich mit 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>

Es gab keine "Verbindung zugeschlossen." bei beiden Tests. Wieder weiß ich nicht, ob es wichtig ist oder nicht.

Zweitens habe ich entschieden, dass dies keine gute Umgebung für meinen Stand ist, da ich den Start eines untergeordneten Prozesses benötige. Also habe ich die VMs erneut erstellt und das Skript mit dem nächsten Code ausgeführt:

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

In der Ausgabe dieses Laufs stand "Verbindung zu 192.168.0.34 geschlossen".

Auf der anderen Seite

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

Beide wurden nicht gehängt.

Heute Abend werde ich meine Skripte mit fabric2 auf dem Prozess starten, der gegabelt wurde, und ich werde schreiben.
Aktualisiert Eigentlich war es mein Fehler im Code. Stoff2 enthält also kein Hängen.

Wäre gut, use_sudo Unterstützung für Transfer.put zu bekommen.

Ich denke, die einfachste Problemumgehung ist im Moment, einfach ein put irgendwo zu machen, wo ich Berechtigungen habe, dann ein sudo mv ?

@ned2 das ist sowieso alles, was use_sudo wirklich in get / put tun kann, zB so macht es v1. Soweit mir bekannt ist, ist es eigentlich nicht möglich, eine Datei "mit sudo" hochzuladen! (Nicht ohne sich als root zu verbinden, was eine schlechte Idee ist und im Idealfall nicht einmal erlaubt ist.)

Angesichts des Versuchs, eine etwas sauberere API in v2 zu haben, ist es fast wahrscheinlicher, dass ich einen Wrapper implementiere, anstatt dieses Verhalten in get / put selbst zu bündeln. Vielleicht nur so etwas wie Transfer.sudo_put (was self.put würde). Auf diese Weise wird das "reine" put minimal gehalten.

@bitprophet Ich möchte damit beginnen, Ihnen für einige ziemlich stabile und nützliche Software mit Fabric1 und Ihren Ansatz zur Veröffentlichung von Fabric2 zu danken.

Ich habe angefangen, mit v2 herumzuspielen, aber ich habe ein Problem mit Connection. Ich verwende meine SSH-Konfiguration von Fabric 1, Fabric 1 würde mich zur Eingabe eines Passworts auffordern, wenn ich versuche, eine Verbindung herzustellen. Fabric 2 tut dies nicht und gibt an, dass die Authentifizierung fehlgeschlagen ist. Ich kann in den v2-Dokumenten nirgendwo sehen, dass der Authentifizierungsmechanismus für Connection erwähnt wird. Es gibt eine Erwähnung von Passwörtern mit sudo, aber soweit ich das beurteilen kann, ist dies sowieso nachdem die Verbindung erfolgreich war.

Meine Frage ist, ob ich etwas in den Dokumenten übersehen habe oder ob dies eine fehlende Funktion oder ein Problem ist.

Der Code:

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

        cxn.run('ls -l')

Der Fehler:

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

Meine SSH-Konfiguration (Ersetzte Werte zum Posten hier):

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

Ich bin auf der neuesten v2-Version: https://github.com/fabric/fabric/commit/fec3a22ee89900500ae731913fd33f9b56e89f46

Hoffentlich hilft die Lösung allen anderen mit dem gleichen Problem.

Vielen Dank für Ihre Zeit.

@ Aiky30 Sie sind es wahrscheinlich nicht, das Auth-Zeug muss noch bearbeitet werden (zum großen Teil, weil einige laufende Paramiko-Arbeiten erforderlich sind, sodass Auth-Ausnahmen nicht schrecklich schwer richtig zu interpretieren sind.) Ich denke, in diesem Fall kann es einfach so sein Fab 2 interpretiert IdentityFile nicht - wir greifen auf Host, Benutzer, Port und eine Reihe anderer Einstellungen zu, aber IdentityFile ist immer noch ein TODO.

Das liegt teilweise daran, dass wir uns im Moment auch nicht mit Passphrasen befassen (siehe oben – wir wollen einen großen Fabric 1-Kludge vermeiden, bei dem wir wild raten müssen, ob ein bestimmter Authentifizierungsfehler bedeutet, dass ein Passwort oder eine Passphrase benötigt wird). Sie würden danach wahrscheinlich nur zu einem Fehler "Ich kann diese Datei nicht entsperren" wechseln. Und beides liegt daran, dass ich die meiste Zeit einen ssh-Agenten verwende - was mein erster Vorschlag für eine sofortige Problemumgehung wäre.

Abgesehen davon denke ich, dass es sich wahrscheinlich lohnt, sowohl in IdentityFile als auch in die Unterstützung der expliziten Passphrase-Konfiguration zu hacken, da Nicht-Agent-Schlüssel wahrscheinlich die am häufigsten verwendete Authentifizierungskonfiguration sind. Wenn sie also fehlt, bedeutet dies wahrscheinlich, dass die meisten Alpha- / Beta-Benutzer im Stich gelassen werden . Mal sehen, ob ich das heute hinbekomme.

Nahm 2.0a für eine Spritztour.

1) Ich bin auch ein bisschen verloren, wie man Hosts tatsächlich definiert und verwendet. Ich kann rennen:

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

Aber wenn ich nicht jedes Mal Hostdetails (Benutzer, Host, Port) übergeben möchte, bin ich mir nicht sicher, wie ich Hosts in fabfile.py ( Connection s oder Group konfigurieren soll https://github.com/fabric/fabric/issues/1591#issuecomment -296343613 richtig verstanden habe, wird es im Moment einfach nicht unterstützt (und in https://github.com/fabric/fabric/issues/1594 verfolgt )?

2) Außerdem treffe ich auf ein Problem, bei dem ich einen verschlüsselten SSH-Schlüssel habe (bei ~/.ssh/id_rsa ) und ich habe ssh-add das zu ssh-agent . Es wird angezeigt, wenn ich die Schlüssel über ssh-add -l . Wenn ich eine Aufgabe ausführe und den richtigen Benutzernamen ausgebe:

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

Die Dinge funktionieren gut. Aber wenn ich einen falschen Benutzer verwende, zB fab -H bad_user<strong i="23">@host</strong> sometask , dann bekomme ich:

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

Aber ich gehe davon aus, dass das unter https://github.com/paramiko/paramiko/issues/387 fällt und nicht wirklich spezifisch für Fabric 2.0 ist. Aber ja, es fühlt sich komisch an, einen PasswordRequiredException: Private key file is encrypted -Fehler zu bekommen, wenn der ssh-Agent bereits den entschlüsselten Schlüssel hat. Wenn ich es richtig verstanden habe, wird paramiko nach einer ungültigen Anmeldung auf die direkte Verwendung des Schlüssels zurückgreifen, und ohne die angegebene Passphrase wird dieser Fehler ausgegeben.

3) Es wäre schön, Aufgabenfunktionen zum Kommentieren von Typen zuzulassen (für eine bessere automatische Vervollständigung in der IDE). Hatten Sie Zeit, https://github.com/pyinvoke/invoke/pull/458 in Betracht zu ziehen?

4) Mir gefällt die Idee der Patchwork-Bibliothek. Für Fabric 1.x gibt es https://github.com/sebastien/cuisine (das scheint ziemlich tot zu sein), das viele zusätzliche Funktionen enthält (habe es selbst nicht verwendet). Ist die Idee mit Patchwork, etwas Ähnliches zu bauen (also deklarative Funktionen im Stil von Chef/Ansible/SaltStack, allerdings mit reduziertem Umfang)? Ich habe den Multi-Dir/Multi-File-YAML/DSL-Ansatz, dem andere Tools folgen, immer gehasst und möchte einfach in Python bleiben, um mehr Flexibilität, weniger ausführliche Syntax, automatische IDE-Vervollständigung, einfaches Debugging usw. zu erhalten.

5) Lassen Sie einfach die Unterstützung von py 2.6 und 3.2-3.3 für Fabric 2.0 fallen. Sollten die Leute nicht einfach weitermachen?

@tuukkamustonen - danke für das Feedback! Antworten:

  1. Rollen werden tatsächlich unter #1594 behandelt - und ich denke, es gibt da draußen ein weiteres Ticket für das damit verbundene Problem, nur Konfigurationsdaten pro Host zu haben, abgesehen davon, wie ssh_config dies auf seiner eigenen Ebene tut.

    Die Entscheidung, wie genau die Konfiguration auf Fabric-Ebene mit ssh_config und dann auch mit Gruppen- oder Laufzeitdaten in Einklang gebracht werden soll, ist nicht trivial. Obwohl es definitiv bald passieren muss; Ich möchte nur eine halb durchdachte Lösung statt eines ersten Entwurfs haben.

  2. Nochmals, ja, dies ist das Paramiko-Ticket, das Sie erwähnt haben, und Ihre Vermutung ist richtig, die Situation mit dem schlechten Benutzernamen wird immer irgendwann fehlschlagen, und da Paramiko nur den letzten Fehler verfolgt, auf den es gestoßen ist, ist es zufällig, dass das letzte, was es versucht hat, war die verschlüsselte Kopie des Schlüssels auf der Festplatte. (Wenn Sie diesen Schlüssel beispielsweise an eine andere Stelle verschoben haben, wäre der letzte Fehler etwas anderes.)

  3. Ich habe dieses Ticket gerade kommentiert, es kann vorhandene Tickets für dieselbe Gesamtfunktion duplizieren (oder auch nicht). Ich habe diese älteren kommentiert und IIRC es ist ein "Ja, ich denke, es wäre nett, solange es Python 2 nicht verschmutzt." Es hat jedoch nicht so hohe Priorität wie die meisten der größeren fehlenden Funktionen, sodass es in den Eimer "braucht eine großartige, alle Kästchen aktivierte PR, die ich einfach zusammenführen kann" fällt :)

  4. Ja, siehe Nr. 461, der sehr alt ist, aber immer noch in meinen Gedanken ist. Heutzutage ist die große Frage, wie eine solche Bibliothek geschrieben werden würde, um sowohl Invoke als auch Fabric zu umfassen. In vielen/den meisten Fällen kann man einfach generische Invoke-Tasks schreiben, die keine geteilten lokalen/entfernten Kontexte "kennen", denen ein Fabric-Verbindungskontext übergeben werden kann, wenn man sie auf einem entfernten System ausführen möchte.

    Solche "kontextunabhängigen" Aufgaben würden in der Bibliothek "Aufrufe" (oder einer anderen noch Invoke-spezifischen Bibliothek) leben wollen; aber einige (z. B. alles, was mit Dateiübertragung zu tun hat und nicht nur Shell-Befehle) müssten "Fabric-bewusst" sein. Herauszufinden, wie diese Kluft überbrückt werden kann, ist das Problem.

    Könnte den Weg gehen, "dass lib nur Aufrufe erfordert, Fabric nicht zwingend erfordert, _aber_ eine Teilmenge von Tasks sich beschwert, wenn Sie Fabric nicht installieren und ihnen keinen Connection-Kontext übergeben." Könnte in zwei Bibliotheken aufgeteilt werden (wobei die Fabric-orientierte Bibliothek die allgemeinere Invoke-Bibliothek erfordert.) usw.

  5. Seit kurzem ist dies definitiv in Sicht, siehe paramiko/paramiko#1070 und/oder pyinvoke/invoke#364. Invoke 1.0, Fabric 2.0 und Paramiko 3.0 (oder _vielleicht_ ein 2.4/2.5/was auch immer) werden alle Python 2.7 / 3.4 und höher sein.

Über (1):

Ich bin sicher, Sie wissen das bereits, aber vielleicht möchten Sie sich einige Ideen aus Ansibles Inventaren holen. Oder vielleicht nicht :).

Über (4):

Ich denke, https://github.com/pyinvoke/invocations ist dafür viel zu eigensinnig. Invocations bietet _Konventionen_ und kann auf Patchwork-/Cuisine-Style-Paketen aufbauen, aber ich würde Konventionen (wie man veröffentlicht oder doctestet) nicht mit Dienstprogrammen mischen (wie man Dateien kopiert oder Berechtigungen ändert).

Ich sehe kein Problem darin, Dienstprogramme für Nur-Lokal-, Nur-Fern- und Lokal+Remote-Operationen in dieselbe Bibliothek (Patchwork) zu packen. Welche Operation welchen Modus unterstützt, kann als Dokumentation angegangen werden (als Docstring, automatisch aus Annotation generiert usw.).

Das fühlt sich besser an, als die Logik in 2+ Pakete aufzuteilen. Denn was wäre, wenn Sie Ihrem "Nur-Aufruf"-Paket zuerst eine Operation hinzufügen (und es könnte sogar "Remote-Only"-Operationen geben) und dann später Unterstützung dafür hinzufügen, dass sie auch auf Remote-Servern funktioniert? Würden Sie den Code verschieben, kopieren oder erweitern? In beiden Fällen ist es mehr Arbeit, und der Benutzer benötigt einen anderen Import usw., daher klingt es etwas umständlich.

Was kann ich tun, um das so zu polieren, dass es auf PyPi läuft?

@haydenflinner Es passiert in den nächsten ein oder zwei Wochen!! (Ziel ist die Veröffentlichung, bevor ich in mein Flugzeug zur PyCon steige, das ist der 10. Mai.)

Sehen Sie sich zum Beispiel die kürzlich aktualisierten Upgrade-Dokumente an, an denen ich gerade diese Woche gearbeitet habe: http://docs.fabfile.org/en/v2/upgrading.html

Tatsächlich kann ich dieses Ticket jetzt genauso gut schließen, da ich bald echte echte Tickets für 2.0.0 und höher akzeptieren werde 👍

Beachten Sie, dass Sie hier immer noch Kommentare abgeben können, wenn Sie möchten. Beachten Sie, dass ich hoffe, neben der gesamten Projektmanagement-Vorbereitung zumindest ein paar Brocken Feature-Arbeit vor der Veröffentlichung erledigt zu haben.

Ich habe mir heute Fabric v2 angesehen und es tut mir leid, ich kann mich einfach nicht dazu bringen, es zu benutzen.

  1. Wo sind Roledefs geblieben? Warum kann ich keinen Rollennamen mehr in der Befehlszeile übergeben? Soll ich das selbst umsetzen?
  2. Warum kann ich auf der Befehlszeile keine Argumente mehr an Tasks übergeben? Soll ich das auch selber umsetzen?
  3. Warum muss der Parameter -H vor dem Task-Parameter stehen? Es sollte umgekehrt sein. Das ist so schrecklich.

Tasks akzeptieren Argumente, aber die Syntax hat sich geändert. Siehe http://docs.pyinvoke.org/en/1.1/concepts/invoking-tasks.html#task -command-line-arguments

@dgarstang Vielleicht möchten Sie einen neutraleren oder einfühlsameren Ton gegenüber Leuten anschlagen, die Ihnen ihre kostenlose Arbeitskraft zur Verfügung stellen! Sag nur 😉

  1. Siehe #1594, welches IIRC im Upgrade-Dokument verlinkt ist
  2. @ploxiln hat dir hier den Rücken freigehalten
  3. (Teilweise) siehe Nr. 1772, das mit dem Master zusammengeführt wird und bald erscheinen wird; es fügt die Möglichkeit hinzu, @task(hosts=xxx) zu verwenden.

(zu 3: In Bezug darauf, --hosts und Freunde so zu geben, als wären sie Argumente pro Aufgabe, das ist etwas, das ich irgendwann hinzufügen könnte, wurde hin und her gerissen, ob es das wert ist. Ähnlich wie bei --help pro Aufgabe

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen