Fabric: Autoriser le stockage/l'utilisation des métadonnées sur les hôtes

Créé le 19 août 2011  ·  13Commentaires  ·  Source: fabric/fabric

Mise à jour 2018 : il s'agit d'un vieux ticket et il est prêt à être mis en œuvre maintenant que la version 2.0 est disponible pour créer des fonctionnalités par-dessus.

Le tl;dr est que les utilisateurs ont besoin de moyens de stocker des données riches sur leurs hôtes cibles (et, généralement, des groupes ou des "rôles"), d'abord, puis ont besoin d'un moyen d'adresser ces informations lorsqu'ils font des choses au niveau de l'API ou de la CLI, en second lieu.

Fabric 2 est construit sur Invoke qui dispose d'un système de configuration puissant, qui est ensuite exposé aux tâches via un objet « contexte ». Il semble probable que nous allons construire cette fonctionnalité sur ceux-ci, quelque chose comme (mais pas nécessairement limité à):

  • Standardiser sur un format de style de configuration relativement générique pour représenter les hôtes ; essentiellement les paramètres de connexion (utilisateur, nom d'hôte, port, connect_kwargs, délai d'attente, etc.) et probablement avec un peu plus en plus

    • ou au moins la possibilité pour les utilisateurs de mettre des données arbitraires en haut et de les faire apparaître dans les objets exposés à l'utilisateur lors de l'exécution

  • Mettre à jour le contexte afin qu'il ait un lien léger vers une autre classe ou des classes qui transforment la configuration « brute » en objets API utilisables, en fonction d'une requête ou d'une recherche

    • La question ouverte est de savoir si celles-ci apparaissent en tant que connexions réelles ou s'il existe une classe de représentation intermédiaire comme Host

Par exemple (encore!: Juste un _off l'exemple cuff_) peut - être que nous allons mettre en place afin que les données hôte obtient son propre fichier de style de configuration qui vit à côté des fichiers de configuration régulière - disons, $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

Alors peut-être qu'il y a quelque chose comme ça (en utilisant des tâches de style Invoke pur pour l'instant, bien que cela voudrait certainement la possibilité d'utiliser -H ou des décorateurs pour sélectionner des hôtes cibles pour « encapsuler » la tâche, comme dans la v1) :

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

Il existe de nombreuses façons différentes de trancher et de découper cela, et de nombreuses directions dans lesquelles cela pourrait être étendu ; l'accent devrait être mis sur le fait de donner aux utilisateurs autant de pouvoir et de contrôle que raisonnablement possible, puis de s'écarter de leur chemin. Idéalement, tout ce que nous ferons est de standardiser sur une manière très basique de pelleter des données dans des objets de connexion et d'ajouter la prise en charge du framework d'exécution CLI principal pour arriver à quelque chose qui ressemble à Fabric 1 re: sélectionner les cibles d'exécution.

Tout en exposant publiquement ces mécanismes afin que les utilisateurs avancés puissent prendre les choses en main - encore une fois, je m'attends à ce que quiconque au-delà des cas d'utilisation les plus basiques soit très susceptible de se rabattre sur des "tâches de style Invoke régulières + faire les appels d'API nécessaires dans ces tâches approche des corps".


Descriptif d'origine

À l'heure actuelle, un "hôte" est uniquement limité à l'utilisateur/au nom d'hôte/au port. Ce serait bien, même pour les fabfiles des utilisateurs, de stocker des informations supplémentaires telles que le système d'exploitation, les paramètres par hôte comme env.shell, etc.

Notez que cela peut (ou non) être le bon moment pour reconsidérer la modification de la valeur par défaut de shell en /bin/sh .


Présentée à l' origine par Jeff Forcier ( bitprophet ) sur 2009-07-20 à 17:02 EDT

Rapports

  • Dupliqué par #43 : /bin/bash n'est pas toujours disponible - par configuration de shell hôte ?
  • Lié à #97 : Dans certaines situations, appuyer sur Entrée ne réutilise _pas_ le mot de passe précédent
  • Lié à #138 : env.port non honoré si la chaîne hôte n'a pas de spécification de port
  • Lié à n°3 : utilisez ssh_config dans la mesure du possible
  • Lié à #76 : Utiliser le décorateur pour définir les tâches
Core Feature

Commentaire le plus utile

Salut!

Après de nombreuses lectures, je ne comprends toujours pas comment cela fonctionne vraiment. Par exemple, si j'ai un fichier de configuration hosts.yml comme celui-ci :

hosts.yml :

server1:
  host: serverip
  user: username

Comment dois-je l'utiliser pour créer une connexion ? J'ai dû renommer hosts.yml en fabric.yml pour accéder à ces données, via la variable de contexte, par exemple :

<strong i="12">@task</strong>
def do(ctx):
    ctx['server1']

Et il restituera un DataProxy, que je ne peux pas utiliser pour créer une connexion, ou que je n'ai tout simplement pas trouvé dans la documentation

Mon autre problème : comment est-il possible de spécifier ces hôtes déclarés dans le fichier hosts.yml avec la bascule -H ? Cela ne fonctionne que si je crée un alias dans le fichier _~/.ssh/config_ qui n'est pas du tout génial.

Hors sujet : l'invite a été supprimée de l'API ? Je n'ai pas trouvé de méthode correspondante.

J'ai la même question. Je n'ai pas trouvé un seul exemple ou tutoriel sur la façon de créer et d'utiliser des fichiers de configuration. La documentation de l'API est très insuffisante à cet égard.

Tous les 13 commentaires

Silas Sewell ( silas ) a posté :


En ce qui concerne le shell par défaut, même si vous ne changez pas en /bin/sh , il peut être utile d'utiliser /usr/bin/env bash pour corriger les situations où l'utilisateur a installé bash.

Exemple de correctif : http://github.com/silas/fabric/commit/6f7d33c1a3180fbba21c89447bb9a32b84e839ba

PS J'ai posté ici parce que "Support #43" a été marqué comme un doublon.


le 2009-11-09 à 23h13 HNE

Erich Heine ( sophacles ) a posté :


J'ai trouvé un moyen de créer ces métadonnées d'hôte qui fonctionne plutôt bien pour les cas simples. Les bits de code pertinents sont ici http://paste.pocoo.org/show/173964/ mais il y a quelques idées que je n'ai pas encore eu le temps de mettre en œuvre -- à savoir que ce type d'interface pour héberger des métadonnées pourrait être mieux défini en tant que « protocole ». J'entends par là, avoir une interface définie à une extrémité, de sorte que divers backends puissent être implémentés, par exemple un client LDAP et un client redis, etc. Cela permettrait aux gens de mieux s'intégrer aux outils existants (par exemple, buildbot).


le 04-02-2010 à 15h33 HNE

Ceci est fortement lié à certaines choses que j'expérimentais dans #563, où avoir un véritable objet Host aiderait beaucoup avec host_string BS, et ouvrirait également la voie à ce type de remplacement des paramètres par hôte.

Cela a été botté à 2.x donc c'est aussi.

Nous stockons actuellement des métadonnées supplémentaires sur l'hôte distant dans env.server , que nous extrayons d'un inventaire des configurations de serveur enregistrées sur le disque en tant que JSON. Mais cela ne fonctionne que lorsque nous exécutons des tâches sur un seul serveur, ou lorsque chaque tâche qui devrait être exécutée avec plusieurs serveurs contient du code pour mettre à jour env.server fonction de la valeur de env.host_string .

Une chose qui nous faciliterait la tâche serait que le tissu fournisse un crochet pour le changement de env.host_string . Ensuite, nous pourrions simplement avoir un morceau de code qui s'y rattache et met env.server jour env.host_string est modifié.

Cela pourrait-il être mis en œuvre facilement, sans avoir à tout mettre en œuvre et à refactoriser host_string en un objet Host complet ?

En copiant les commentaires pertinents du #1748, @peteruhnak a commenté :

"""
Salut! Est-il possible de spécifier des hôtes dans un fichier de configuration ou dans le fabfile lui-même ?

Je sais que je peux les fournir via CLI (-H), mais si le fabfile est conçu pour communiquer avec un serveur spécifique, cela oblige simplement l'utilisateur à faire des choses supplémentaires sans raison valable.

La "meilleure" solution que j'ai pu trouver était de créer la connexion à la main, par exemple

@tâche
def my_ls(c):
conn = Connexion('monhôte')
conn.run('ls')
mais cela semble assez sale car je dois (1) le dupliquer partout et (2) cela rend l'argument de contexte inutile.
"""

Et j'ai suivi avec :

"""
D'accord avec tout ce qui précède. L'ancien paramètre env.hosts me manque vraiment. C'était magnifiquement simple.

-1 pour avoir besoin d'un autre fichier de configuration comme invoke.yaml ou autre. Je préférerais de loin un patch singe ou une sorte de crochet d'importation qui me permette d'indiquer les hôtes.

Il m'a également fallu un certain temps pour comprendre que ctx.local n'est pas présent si aucun hôte n'est spécifié :(
"""

Je comprends que Invoke fournit un support de configuration riche. J'espère que cela inclut la configuration à partir des fichiers fab de Python.

Dans fabric1, j'ai ajouté la possibilité de charger des listes d'hôtes avec --set list=somelistfile.txt. Dans le fabfile, j'analyserais ensuite le fichier et modifierais env.hosts et env.passwords avec les paramètres de ce fichier. Cela m'a permis de faire par exemple fab task --set list=datacenter1.txt . J'avais alors des dizaines de tâches générales que je pouvais exécuter sur des listes prédéfinies, dans certains cas une liste par centre de données ou une liste par fonction logique. Je me rends compte que cela peut être un peu un hack, mais cela me convient bien depuis de nombreuses années dans ma carrière professionnelle.

Je n'ai pas trouvé de moyen de le faire dans fab2 car les hôtes sont chargés à l'intérieur de l'exécuteur. J'aimerais beaucoup faire quelque chose de similaire dans fab2. Cependant, il semble que le paradigme de fab2 m'oblige à spécifier les hôtes dans les tâches. Cela rend impossible d'avoir mes tâches à usage général et de l'utiliser sur une grande variété de serveurs (sans utiliser fab2 -H).

Avoir une sorte de fichier de configuration hôte avancé et pouvoir le spécifier sur la ligne de commande, je pense que ce serait un excellent ajout à fabric2.

comme @grantjenks l'a mentionné, il existe une prise en charge de la configuration avancée dans invoke : http://docs.pyinvoke.org/en/1.1/concepts/configuration.html - nous aurions donc juste besoin de créer un fichier yaml, et c'est parti. cela pourrait/pourrait être étendu (à la main, chacun seul pour le moment), pour prendre en charge quelque chose comme le concept env , comme dans Fabric One. Si l'on n'aime pas yaml, cela peut être complètement fait en code python, si j'ai bien compris.

@benzkji Absolument vrai ; les utilisateurs peuvent, dès maintenant, mettre des données arbitraires dans leurs fichiers de configuration (py, yml, json, éventuellement d'autres) et extraire ces données dans leurs tâches pour construire des connexions et des groupes et ainsi de suite. C'est intentionnel ; nous ne voulons jamais qu'il n'y ait qu'une seule façon de gérer ce genre de configuration, c'est pourquoi les objets sont tous publics et autres.

Voir aussi tout en haut du ticket ; J'ai modifié la description avec une vision moderne de ce à quoi cette fonctionnalité pourrait ressembler dans la v2, en termes d'aides de base communes "pour les utilisateurs sans opinion". En fait, je suis en train de bricoler cela dans un dépôt privé (client de tissu, pas de fourchette) ces jours-ci pour voir quels modèles émergent.

Salut!

Après de nombreuses lectures, je ne comprends toujours pas comment cela fonctionne vraiment. Par exemple, si j'ai un fichier de configuration hosts.yml comme celui-ci :

hosts.yml :

server1:
  host: serverip
  user: username

Comment dois-je l'utiliser pour créer une connexion ? J'ai dû renommer hosts.yml en fabric.yml pour accéder à ces données, via la variable de contexte, par exemple :

<strong i="11">@task</strong>
def do(ctx):
    ctx['server1']

Et il restituera un DataProxy, que je ne peux pas utiliser pour créer une connexion, ou que je n'ai tout simplement pas trouvé dans la documentation

Mon autre problème : comment est-il possible de spécifier ces hôtes déclarés dans le fichier hosts.yml avec la bascule -H ? Cela ne fonctionne que si je crée un alias dans le fichier _~/.ssh/config_ qui n'est pas du tout génial.

Hors sujet : l'invite a été supprimée de l'API ? Je n'ai pas trouvé de méthode correspondante.

Salut!

Après de nombreuses lectures, je ne comprends toujours pas comment cela fonctionne vraiment. Par exemple, si j'ai un fichier de configuration hosts.yml comme celui-ci :

hosts.yml :

server1:
  host: serverip
  user: username

Comment dois-je l'utiliser pour créer une connexion ? J'ai dû renommer hosts.yml en fabric.yml pour accéder à ces données, via la variable de contexte, par exemple :

<strong i="12">@task</strong>
def do(ctx):
    ctx['server1']

Et il restituera un DataProxy, que je ne peux pas utiliser pour créer une connexion, ou que je n'ai tout simplement pas trouvé dans la documentation

Mon autre problème : comment est-il possible de spécifier ces hôtes déclarés dans le fichier hosts.yml avec la bascule -H ? Cela ne fonctionne que si je crée un alias dans le fichier _~/.ssh/config_ qui n'est pas du tout génial.

Hors sujet : l'invite a été supprimée de l'API ? Je n'ai pas trouvé de méthode correspondante.

J'ai la même question. Je n'ai pas trouvé un seul exemple ou tutoriel sur la façon de créer et d'utiliser des fichiers de configuration. La documentation de l'API est très insuffisante à cet égard.

Fabric 2 est génial, mais de mon point de vue d'utilisateur final, c'est plus un effort pour le mettre en place et le faire fonctionner (par rapport à Fabric 1), par exemple en tant qu'outil de déploiement simple pour les applications Web Django (dans mon cas).

Y a-t-il des nouvelles sur cette question? Je suppose qu'un paquet pypi "django/quel que soit le déploiement" aurait du sens, pour bricoler avec les choses de base dont on aurait besoin, donc l'intégration peut être beaucoup plus facile. Y a-t-il quelque chose comme ça connu/en préparation ?

Dans tous les cas, je vais devoir bricoler avec le tissu 2, et partager quelques réflexions ici, si elles en valent la peine ;-)

Quelle est la manière appropriée de stocker plusieurs hôtes/types d'hôtes ? C'est à dire:

gpu_workers:
  - [email protected]
cpu_workers:
  - [email protected]
fab --FLAG gpu_workers do_some_task

Nous pouvons créer un décorateur task qui remplace l'argument de contexte :

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

ou le mettre dans un module externe

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')
Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

haydenflinner picture haydenflinner  ·  5Commentaires

peteruhnak picture peteruhnak  ·  4Commentaires

SamuelMarks picture SamuelMarks  ·  3Commentaires

TimotheeJeannin picture TimotheeJeannin  ·  3Commentaires

Grazfather picture Grazfather  ·  4Commentaires