Ich möchte Fabric verwenden, um meinen Web-App-Code auf Entwicklungs-, Staging- und Produktionsservern bereitzustellen. Mein Fabfile:
def deploy_2_dev():
deploy('dev')
def deploy_2_staging():
deploy('staging')
def deploy_2_prod():
deploy('prod')
def deploy(server):
print 'env.hosts:', env.hosts
env.hosts = [server]
print 'env.hosts:', env.hosts
Beispielausgabe:
host:folder user$ fab deploy_2_dev
env.hosts: []
env.hosts: ['dev']
No hosts found. Please specify (single) host string for connection:
Wenn ich eine set_hosts()
Aufgabe erstelle, wie in den Fabric-Dokumenten gezeigt , ist env.hosts richtig eingestellt. Dies ist jedoch keine praktikable Option, ebenso wenig wie ein Dekorateur. Das Übergeben von Hosts über die Befehlszeile würde letztendlich zu einer Art Shell-Skript führen, das die Fabfile aufruft. Ich würde es vorziehen, wenn ein einziges Tool die Aufgabe ordnungsgemäß erledigt.
In den Fabric-Dokumenten heißt es, dass 'env.hosts einfach ein Python-Listenobjekt ist'. Nach meinen Beobachtungen ist dies einfach nicht wahr.
Kann jemand erklären, was hier los ist? Wie kann ich den Host für die Bereitstellung festlegen?
Antworten:
Ich mache das, indem ich eine tatsächliche Funktion für jede Umgebung deklariere. Beispielsweise:
Mit den oben genannten Funktionen würde ich Folgendes eingeben, um es in meiner Testumgebung bereitzustellen:
... und Folgendes für die Bereitstellung in der Produktion:
Das Schöne an es auf diese Weise tun , ist , dass die
test
undprod
Funktionen können , bevor sie verwendet werden , jede fab Funktion, nicht nur bereitstellen. Es ist unglaublich nützlich.quelle
code.fabfile.org
Domain haben solche Antworten.fab A B C
Stil aus, ohne dass sie als Aufgaben definiert sind.Verwenden Sie roledefs
Wählen Sie die Rolle mit -R:
quelle
roledef
? Ein weiterer Wörterbucheintrag'password': 'some_password'
scheint ignoriert zu werden und führt zur Laufzeit zu einer Eingabeaufforderung.Hier ist eine einfachere Version der Antwort von Serverhorror :
quelle
env
Variablen und nicht zum anfänglichen Festlegen. Ich denke, die Verwendung von Roledefs ist , wie von Thomie vorgeschlagen, besser geeignet, um Hosts wie Stage, Dev und Test zu definieren.War selbst dabei festgefahren, habe es aber endlich herausgefunden. Sie können die env.hosts-Konfiguration einfach nicht von innen festlegen einer Aufgabe . Jede Aufgabe wird N-mal ausgeführt, einmal für jeden angegebenen Host, sodass die Einstellung grundsätzlich außerhalb des Aufgabenbereichs liegt.
Wenn Sie sich Ihren Code oben ansehen, können Sie einfach Folgendes tun:
Was scheint, als würde es tun, was Sie beabsichtigen.
Oder Sie können benutzerdefinierten Code in den globalen Bereich schreiben, der die Argumente manuell analysiert und env.hosts festlegt, bevor Ihre Aufgabenfunktion definiert wird. Aus ein paar Gründen habe ich meine so eingerichtet.
quelle
from fabric.api import env
;env.host_string = "dev"
Seit Fab 1.5 ist dies eine dokumentierte Möglichkeit, Hosts dynamisch festzulegen.
http://docs.fabfile.org/en/1.7/usage/execution.html#dynamic-hosts
Zitat aus dem Dokument unten.
quelle
Im Gegensatz zu einigen anderen Antworten, es ist möglich , die zu modifizieren
env
Umgebungsvariablen innerhalb einer Aufgabe. Diesenv
wird jedoch nur für nachfolgende Aufgaben verwendet, die mit derfabric.tasks.execute
Funktion ausgeführt werden .Ohne Unteraufgaben einzuschließen
execute(...)
, werden Ihreenv
Einstellungen auf Modulebene oder was auch immer von derfab
CLI übergeben wird, verwendet.quelle
Sie müssen
host_string
ein Beispiel geben, wäre:quelle
Um zu erklären, warum es überhaupt ein Problem ist. Der Befehl fab Stoff die Bibliothek nutzt die Aufgaben auf den Host - Listen laufen. Wenn Sie versuchen, die Hostliste innerhalb einer Aufgabe zu ändern, versuchen Sie im Wesentlichen, eine Liste zu ändern, während Sie darüber iterieren. Wenn Sie keine Hosts definiert haben, durchlaufen Sie eine leere Liste, in der der Code, in dem Sie die Liste für die Schleife festgelegt haben, niemals ausgeführt wird.
Die Verwendung von env.host_string ist eine Problemumgehung für dieses Verhalten, da nur direkt für die Funktionen angegeben wird, mit welchen Hosts eine Verbindung hergestellt werden soll. Dies führt zu einigen Problemen, da Sie die Ausführungsschleife neu erstellen, wenn Sie mehrere Hosts ausführen möchten.
Die einfachste Möglichkeit für die Benutzer, Hosts zur Laufzeit festzulegen, besteht darin, die Env-Auffüllung als eigenständige Aufgabe beizubehalten, die alle Host-Zeichenfolgen, Benutzer usw. einrichtet. Anschließend führen sie die Bereitstellungsaufgabe aus. Es sieht aus wie das:
oder
Wo Inszenierung und Produktion wie die Aufgaben sind, die Sie gegeben haben, aber nicht die nächste Aufgabe selbst aufrufen. Der Grund, warum es so funktionieren muss, ist, dass die Aufgabe beendet werden und aus der Schleife ausbrechen muss (von Hosts, im Env-Fall None, aber es ist zu diesem Zeitpunkt eine Schleife von eins), und dann die Schleife beendet haben muss die Hosts (jetzt durch die vorhergehende Aufgabe definiert) neu.
quelle
Sie müssen env.hosts auf Modulebene ändern, nicht innerhalb einer Taskfunktion. Ich habe den gleichen Fehler gemacht.
quelle
Es ist sehr einfach. Initialisieren Sie einfach die Variable env.host_string und alle folgenden Befehle werden auf diesem Host ausgeführt.
quelle
Fabric ist für mich völlig neu, aber um Fabric dazu zu bringen, dieselben Befehle auf mehreren Hosts auszuführen (z. B. auf mehreren Servern in einem Befehl bereitzustellen), können Sie Folgendes ausführen:
Dabei sind Staging-Server und Produktionsserver zwei Server, für die Sie die Bereitstellungsaktion ausführen möchten. Hier ist eine einfache fabfile.py, die den Namen des Betriebssystems anzeigt. Beachten Sie, dass sich die Datei fabfile.py in demselben Verzeichnis befinden sollte, in dem Sie den Befehl fab ausführen.
Dies funktioniert mindestens mit Stoff 1.8.1.
quelle
Um die Hosts festzulegen und die Befehle auf allen Hosts ausführen zu lassen, müssen Sie zunächst Folgendes ausführen:
Sobald diese definiert sind, führen Sie den Befehl in der Befehlszeile aus:
Was führt die Bereitstellungsaufgabe auf allen in der PROD-Funktion aufgelisteten Servern aus, da die env.hosts vor dem Ausführen der Aufgabe festgelegt werden?
quelle
Sie können zuweisen
env.hoststring
vor dem Ausführen einer Unteraufgabe zuweisen. Weisen Sie dieser globalen Variablen in einer Schleife zu, wenn Sie über mehrere Hosts iterieren möchten.Leider ist Stoff für Sie und mich nicht für diesen Anwendungsfall ausgelegt. Überprüfen Sie die
main
Funktion unter http://github.com/bitprophet/fabric/blob/master/fabric/main.py, um zu sehen, wie sie funktioniert.quelle
Hier ist ein weiteres "Summersault" -Muster, das die
fab my_env_1 my_command
Verwendung ermöglicht :Mit diesem Muster müssen wir Umgebungen nur einmal mithilfe eines Wörterbuchs definieren.
env_factory
Erstellt Funktionen basierend auf den Schlüsselnamen vonENVS
. Ich habeENVS
ein eigenes Verzeichnis und eine eigene Datei erstelltsecrets.config.py
, um die Konfiguration vom Fabric-Code zu trennen.Der Nachteil ist, dass, wie geschrieben, das Hinzufügen des
@task
Dekorateurs es brechen wird .Hinweise: Wir verwenden
def func(k=k):
anstelledef func():
der Fabrik wegen verspäteter Bindung . Wir erhalten das laufende Modul mit dieser Lösung und patchen es, um die Funktion zu definieren.secret.config.py
fabfile.py
quelle
Die Verwendung von Rollen wird derzeit als die "richtige" und "richtige" Methode angesehen und ist das, was Sie tun sollten.
Das heißt, wenn Sie wie die meisten von dem sind, was Sie "möchten" oder "wünschen", ist die Fähigkeit, eine "verdrehte Syster" durchzuführen oder Zielsysteme im laufenden Betrieb zu wechseln.
Nur zu Unterhaltungszwecken (!) Veranschaulicht das folgende Beispiel, was viele für ein riskantes und dennoch irgendwie durchaus befriedigendes Manöver halten, das ungefähr so aussieht:
Dann laufen:
quelle