Fabric: Speichern/Verwenden von Metadaten zu Hosts zulassen

Erstellt am 19. Aug. 2011  ·  13Kommentare  ·  Quelle: fabric/fabric

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

  • Standardisieren Sie ein relativ allgemeines Format im Konfigurationsstil zum Darstellen von Hosts; im Wesentlichen die Parameter von Connection (Benutzer, Hostname, Port, connect_kwargs, Timeout usw.) und wahrscheinlich mit etwas mehr obendrauf

    • oder zumindest die Möglichkeit für Benutzer, beliebige Daten darüber zu legen und diese in den Objekten anzeigen zu lassen, die dem Benutzer zur Laufzeit zugänglich sind

  • Aktualisieren Sie den Kontext, sodass er einen leichten Link zu einer oder mehreren anderen Klassen hat, die die "rohe" Konfiguration basierend auf einer Abfrage oder Suche in verwendbare API-Objekte verwandeln

    • Offene Frage ist, ob diese als tatsächliche Verbindungen angezeigt werden oder ob es eine intermediäre Repräsentationsklasse wie Host . gibt

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.


Originalbeschreibung

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

Beziehungen

  • Dupliziert von #43: /bin/bash ist nicht immer verfügbar – pro Host-Shell-Konfiguration?
  • Bezogen auf #97: In manchen Situationen wird durch Drücken der Eingabetaste _nicht_ das vorherige Passwort wiederverwendet
  • Bezogen auf #138: env.port wird nicht berücksichtigt, wenn der Host-String keine Portspezifikation enthält
  • Bezogen auf #3: Verwenden Sie nach Möglichkeit ssh_config
  • Bezogen auf #76: Verwenden Sie Decorator, um Aufgaben zu definieren
Core Feature

Hilfreichster Kommentar

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.

Alle 13 Kommentare

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')
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

Grazfather picture Grazfather  ·  4Kommentare

bitprophet picture bitprophet  ·  4Kommentare

omzev picture omzev  ·  6Kommentare

26huitailang picture 26huitailang  ·  3Kommentare

TimotheeJeannin picture TimotheeJeannin  ·  3Kommentare