2018-Update: Dies ist ein altes, altes Ticket und es ist darauf vorbereitet, tatsächlich implementiert zu werden, da 2.0 verfügbar ist, um Funktionen darauf aufzubauen.
Das tl; dr ist, dass Benutzer erstens Möglichkeiten zum Speichern umfangreicher Daten über ihre Zielhosts (und normalerweise Gruppen oder "Rollen") benötigen und zweitens eine Möglichkeit benötigen, diese Informationen zu adressieren, wenn sie Dinge auf API- oder CLI-Ebene tun.
Fabric 2 basiert auf Invoke, das über ein leistungsstarkes Konfigurationssystem verfügt, das dann über ein 'Kontext'-Objekt für Aufgaben verfügbar gemacht wird. Es ist wahrscheinlich, dass wir diese Funktion auf diesen aufbauen werden, etwa (aber nicht unbedingt beschränkt auf):
Zum Beispiel (nochmals: nur ein _aus dem Ärmel_ Beispiel!) Vielleicht richten wir es so ein, dass Hostdaten ihre eigene Konfigurationsdatei bekommen, die neben den regulären Konfigurationsdateien existiert - sagen wir $PROJECT/hosts.(yml|json|py|etc)
:
web1:
host: web1
# Implicit local user, as with Connection
web2:
host: web2
user: admin2
port: 2223
db:
# Implicit dict-key-is-the-host-value, i.e. implicit "host: db"
user: dbadmin
Dann gibt es vielleicht so etwas (vorerst mit reinen Aufgaben im Invoke-Stil, obwohl dies sicherlich die Möglichkeit erfordern würde, -H
oder Dekoratoren zu verwenden, um Zielhosts auszuwählen, um die Aufgabe wie in v1 einzupacken):
<strong i="27">@task</strong>
def deploy_webs(c):
# Assuming auto-creation of Connection objects...
for cxn in [c.find_host('web1'), c.find_host('web2')]:
cxn.run("hostname")
Es gibt viele verschiedene Möglichkeiten, dies zu schneiden und zu würfeln, und viele Richtungen, in die es erweitert werden könnte; Der Schwerpunkt sollte darauf liegen, den Benutzern so viel Macht und Kontrolle wie möglich zu geben und ihnen dann aus dem Weg zu gehen. Im Idealfall standardisieren wir nur eine sehr grundlegende Methode zum Einschieben von Daten in Connection-Objekte und fügen dem zentralen CLI-Exec-Framework Unterstützung hinzu, um etwas zu erreichen, das Fabric 1 ähnelt: Auswahl von Ausführungszielen.
Während diese Mechanismen öffentlich zugänglich gemacht werden, damit fortgeschrittene Benutzer die Angelegenheit selbst in die Hand nehmen können - ich erwarte wieder, dass jeder, der über die grundlegendsten Anwendungsfälle hinausgeht, mit hoher Wahrscheinlichkeit auf "reguläre Aufgaben im Invoke-Stil + die erforderlichen API-Aufrufe innerhalb dieser Aufgaben" zurückgreift Körper"-Ansatz.
Im Moment ist ein "Host" ausschließlich auf Benutzer/Hostname/Port beschränkt. Wäre schön, auch nur für Benutzer-Fabfiles, um zusätzliche Informationen wie Betriebssystem, Einstellungen pro Host wie env.shell usw. zu speichern.
Beachten Sie, dass dies ein guter Zeitpunkt sein kann (oder auch nicht), den Standardwert von shell
in /bin/sh
zu ändern.
Ursprünglich eingereicht von Jeff Forcier ( Bitprophet ) am 20.07.2009 um 17:02 Uhr EDT
Silas Sewell ( silas ) hat gepostet:
In Bezug auf die Standard-Shell kann es sinnvoll sein, /usr/bin/env bash
zu verwenden, um Situationen zu beheben, in denen der Benutzer bash installiert hat, auch wenn Sie nicht zu /bin/sh
wechseln.
Beispiel-Patch: http://github.com/silas/fabric/commit/6f7d33c1a3180fbba21c89447bb9a32b84e839ba
PS Ich habe hier gepostet, weil "Support #43" als Duplikat markiert war.
am 2009-11-09 um 23:13 Uhr EST
Erich Heine ( Sophakles ) schrieb:
Ich habe mir eine Methode ausgedacht, diese Host-Metadaten zu erstellen, die für die einfachen Fälle ziemlich gut funktioniert. Die relevanten Code-Bits sind hier http://paste.pocoo.org/show/173964/ Es gibt jedoch einige Ideen, für die ich noch keine Zeit hatte, um sie umzusetzen -- nämlich, dass diese Art von Schnittstelle zum Hosten von Metadaten besser definiert werden könnte als „Protokoll“. Damit meine ich, auf der einen Seite eine definierte Schnittstelle zu haben, so dass verschiedene Backends implementiert werden können, zB ein LDAP-Client und ein Redis-Client usw. Dies würde eine bessere Integration mit bestehenden Tools (zB Buildbot) ermöglichen.
am 04.02.2010 um 15:33 Uhr EST
Dies hängt stark mit einigen Dingen zusammen, mit denen ich in #563 experimentiert habe, wo ein echtes Host-Objekt bei host_string BS sehr hilfreich wäre und auch den Weg für diese Art von Überschreibungen von Einstellungen pro Host ebnen würde.
Das wurde auf 2.x gestochen, also ist dies auch so.
Derzeit speichern wir zusätzliche Metadaten über den Remote-Host in env.server
, die wir aus einem Inventar der Serverkonfigurationen ziehen, die als JSON auf der Festplatte gespeichert sind. Dies funktioniert jedoch nur, wenn wir Aufgaben auf einem einzelnen Server ausführen oder wenn jede Aufgabe, die mit mehreren Servern ausgeführt werden soll, Code enthält, um env.server
basierend auf dem Wert von env.host_string
zu aktualisieren.
Eine Sache, die uns dies erleichtern würde, wäre, wenn der Stoff einen Haken hätte, wenn env.host_string
geändert wird. Dann könnten wir nur ein Stück Code haben, das sich darin einklinkt und env.server
mit dem zusätzlichen Kontext aktualisiert, wenn env.host_string
geändert wird.
Könnte dies leicht implementiert werden, ohne alles daran setzen zu müssen, host_string
in ein ausgewachsenes Host
Objekt umzugestalten?
Kopieren der relevanten Kommentare von #1748, kommentierte @peteruhnak :
"""
Hallo! Ist es möglich, Hosts entweder in einer Konfigurationsdatei oder in der Fabfile selbst anzugeben?
Ich weiß, dass ich sie über CLI (-H) bereitstellen kann, aber wenn die Fabfile für die Kommunikation mit einem bestimmten Server ausgelegt ist, zwingt sie den Benutzer einfach ohne triftigen Grund dazu, zusätzliche Dinge zu tun.
Die "beste" Lösung, die ich finden konnte, war, die Verbindung von Hand herzustellen, z
@Aufgabe
def my_ls(c):
conn = Verbindung('meinhost')
conn.run('ls')
aber das scheint ziemlich schmutzig zu sein, da ich es (1) überall duplizieren muss und (2) es das Kontextargument sinnlos macht.
"""
Und ich folgte mit:
"""
Mit allem oben einverstanden. Ich vermisse wirklich die alte env.hosts-Einstellung. Es war schön einfach.
-1, wenn eine andere Konfigurationsdatei wie invoke.yaml oder so weiter benötigt wird. Ich würde viel lieber Monkey-Patch oder eine Art Import-Hook verwenden, mit dem ich die Hosts angeben kann.
Es hat auch eine Weile gedauert, bis ich herausgefunden habe, dass ctx.local nicht vorhanden ist, wenn keine Hosts angegeben sind :(
"""
Soweit ich weiß, bietet Invoke umfangreiche Konfigurationsunterstützung. Ich würde hoffen, dass dies die Konfiguration aus den Fab-Dateien von Python beinhaltet.
In Fabric1 habe ich die Möglichkeit hinzugefügt, Hostlisten mit --set list=somelistfile.txt zu laden. In der Fabfile würde ich dann die Datei analysieren und env.hosts und env.passwords mit Einstellungen aus dieser Datei ändern. Dadurch konnte ich zB fab task --set list=datacenter1.txt
tun. Ich hatte dann Dutzende von Allzweckaufgaben, die ich gegen vordefinierte Listen ausführen konnte, in einigen Fällen eine Liste pro Rechenzentrum oder eine Liste pro logischer Funktion. Mir ist klar, dass dies vielleicht ein bisschen ein Hack ist, aber es passt mir seit vielen Jahren in meiner beruflichen Karriere gut.
Ich habe in fab2 keine Möglichkeit dazu gefunden, da die Hosts in den Executor geladen werden. Ich würde sehr gerne etwas Ähnliches in fab2 machen. Es scheint jedoch, dass das Paradigma in fab2 erfordert, dass ich die Hosts in den Tasks angeben muss. Dies macht es unmöglich, meine allgemeinen Aufgaben zu erfüllen und auf einer Vielzahl von Servern zu verwenden (ohne fab2 -H zu verwenden).
Eine Art erweiterte Host-Konfigurationsdatei zu haben und diese in der Befehlszeile angeben zu können, wäre meiner Meinung nach eine großartige Ergänzung zu Fabric2.
Wie @grantjenks erwähnte, gibt es in http://docs.pyinvoke.org/en/1.1/concepts/configuration.html - wir müssten also nur eine yaml-Datei erstellen und los gehts. dies würde/könnte erweitert werden (von Hand, jeder für sich allein), um so etwas wie das env
Konzept zu unterstützen, wie in Fabric eins. Wenn man Yaml nicht mag, kann dies, wie ich es verstehe, vollständig in Python-Code erfolgen.
@benzkji Absolut wahr; Benutzer können jetzt beliebige Daten in ihre Konfigurationsdateien (py, yml, json, eventuell andere) einfügen und diese Daten in ihre Aufgaben ziehen, um Verbindungen und Gruppen und so weiter zu erstellen. Dies ist beabsichtigt; Wir wollen nie, dass es nur eine Möglichkeit gibt, mit dieser Art von Einrichtung umzugehen, deshalb sind die Objekte alle öffentlich und so.
Siehe auch ganz oben auf dem Ticket; Ich habe die Beschreibung mit einem modernen Ausblick darauf bearbeitet, wie diese Funktion in v2 aussehen könnte, in Bezug auf einige grundlegende allgemeine Helfer "für uneinsichtige Benutzer". Ich bastle derzeit tatsächlich in einem privaten (Client-of-Stoff-, nicht Fork-) Repo daran herum, um zu sehen, welche Muster entstehen.
Hallo!
Nach langem Lesen verstehe ich immer noch nicht, wie das wirklich funktioniert. Wenn ich beispielsweise eine hosts.yml-Konfigurationsdatei wie diese habe:
hosts.yml:
server1:
host: serverip
user: username
Wie soll ich dies verwenden, um eine Verbindung herzustellen? Ich musste die hosts.yml in Fabric.yml umbenennen, um über die Kontextvariable auf diese Daten zuzugreifen, z.
<strong i="11">@task</strong>
def do(ctx):
ctx['server1']
Und es gibt einen DataProxy zurück, den ich nicht zum Herstellen einer Verbindung verwenden kann oder den ich einfach nicht in der Dokumentation gefunden habe
Mein anderes Problem: Wie ist es möglich, diese in der Datei hosts.yml deklarierten Hosts mit -H toggle anzugeben? Es funktioniert nur, wenn ich in der Datei _~/.ssh/config_ einen Alias erstelle, was gar nicht so toll ist.
Off-Topic: Eingabeaufforderung wurde aus der API entfernt? Ich habe keine entsprechende Methode gefunden.
Hallo!
Nach langem Lesen verstehe ich immer noch nicht, wie das wirklich funktioniert. Wenn ich beispielsweise eine hosts.yml-Konfigurationsdatei wie diese habe:
hosts.yml:
server1: host: serverip user: username
Wie soll ich dies verwenden, um eine Verbindung herzustellen? Ich musste die hosts.yml in Fabric.yml umbenennen, um über die Kontextvariable auf diese Daten zuzugreifen, z.
<strong i="12">@task</strong> def do(ctx): ctx['server1']
Und es gibt einen DataProxy zurück, den ich nicht zum Herstellen einer Verbindung verwenden kann oder den ich einfach nicht in der Dokumentation gefunden habe
Mein anderes Problem: Wie ist es möglich, diese in der Datei hosts.yml deklarierten Hosts mit -H toggle anzugeben? Es funktioniert nur, wenn ich in der Datei _~/.ssh/config_ einen Alias erstelle, was gar nicht so toll ist.
Off-Topic: Eingabeaufforderung wurde aus der API entfernt? Ich habe keine entsprechende Methode gefunden.
Ich habe die gleiche Frage. Ich habe kein einziges Beispiel oder Tutorial zum Erstellen und Verwenden von Konfigurationsdateien gefunden. Die API-Dokumentation fehlt diesbezüglich sehr.
Fabric 2 ist großartig, aber aus meiner Sicht des Endbenutzers ist es ziemlich aufwendig, es zum Laufen zu bringen (im Vergleich zu Fabric 1), zum Beispiel als einfaches Bereitstellungstool für Django-Webapps (in meinem Fall).
Gibt es Neuigkeiten zu diesem Thema? Ich denke, ein oppiniertes pypi-Paket mit "django/was auch immer Bereitstellung" wäre sinnvoll, um an den grundlegenden Dingen herumzubasteln, die man braucht, damit das Onboarding viel einfacher sein kann. Ist so etwas bekannt/in Arbeit?
Auf jeden Fall muss ich an Stoff 2 basteln und hier ein paar Gedanken teilen, wenn sie sich lohnen ;-)
Was ist der geeignete Weg, um mehrere Hosts/Hosttypen zu speichern? Dh:
gpu_workers:
- [email protected]
cpu_workers:
- [email protected]
fab --FLAG gpu_workers do_some_task
Wir können einen benutzerdefinierten task
Dekorator erstellen, der das Kontextargument ersetzt:
import fabric
from functools import wraps
def task(f, *args, **kwargs):
@wraps(f)
def wrapper(c, *args, **kwargs):
c = fabric.Connection('host')
f(c, *args, **kwargs)
return fabric.task(wrapper, *args, **kwargs)
<strong i="7">@task</strong>
def deploy(c):
with c.forward_remote(9418):
c.run('git pull http://localhost/app')
oder in ein externes Modul stecken
fabutil.py
import inspect
import fabric
from functools import wraps
class Connection(fabric.Connection):
# add helper methods
def exists(self, path):
return not self.run(f'test -e "{path}").failed
def task(f, *args, **kwargs):
caller = inspect.getmodule(inspect.currentframe().f_back)
host = caller.HOST
user = caller.USER
@wraps(f)
def wrapper(c, *args, **kwargs):
c = Connection(host, user=user, connect_kwargs={'key_filename': os.path.expanduser('~/.ssh/id_rsa.pub')})
f(c, *args, **kwargs)
return fabric.task(wrapper, *args, **kwargs)
fabfile.py
from fabutil import task
HOST = 'host'
USER = 'user'
<strong i="17">@task</strong>
def deploy(c):
with c.forward_remote(9418):
c.run('git pull http://localhost/app')
Hilfreichster Kommentar
Ich habe die gleiche Frage. Ich habe kein einziges Beispiel oder Tutorial zum Erstellen und Verwenden von Konfigurationsdateien gefunden. Die API-Dokumentation fehlt diesbezüglich sehr.