Hachages Fusion dans les fichiers de conf yaml

31 juillet 2009 par Prashant · Commentaires
Filed under: la technologie

YAML est très pratique pour écrire des fichiers de configuration. Principal avantage est que, il se lit comme fichier texte. Cela fonctionne vraiment bien si votre fichier de configuration est plat (pas de hiérarchie) et n'a pas de répétitions.
Si votre fichier de configuration a répétitions alors il est logique de séparer ces éléments et de les réutiliser. Ce que je veux dire est ceci - disons que vous votre fichier de configuration ressemble à ceci:

  le développement:
   input_location: common_input
   output_location: dev_location
   mail:
     smtp_server: votre_serveur
     login: votre_login
     Mot de passe: top_secret
 la production:
   input_location: common_input
   output_location: dev_location
   mail:
     smtp_server: votre_serveur
     login: votre_login
     Mot de passe: top_secret 

En supposant que le code ci-dessus dans / tmp / test.yml voici comment vous pouvez lire en python et ruby
$cat readyml.py

 #! / Usr / bin / env python
 à partir pprint importation pprint que p
 # Dans le fichier debian besoin d'installer python-yaml
 de la charge d'importation yaml, load_all, d'un dépotoir
 hachage charge = (open ('/ tmp / test.yml'))
 pp (hash ['développement']) 


$ cat readyml.rb

  #! / Usr / bin / ruby
 require 'pp'
 hash = YAML :: load (File.open ('/ tmp / test.yml'). lire)
 hachage pp [«développement»] 

est ici un outil pratique un paquebot pour la version rubis
$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]' ou vous pouvez essayer la même chose à la CISR ou de la console python.

Notez que dans l'extrait de code ci-dessus, tout est autre que l'emplacement de sortie est la même dans le développement et une partie de la production. C'est là identificateur de noeud yml vient à la rescousse. L'idée est simple, un ensemble de valeurs par défaut et les remplacer au lieu différent.
Vous pouvez le séparer comme suit:

  par défaut: par défaut et
   input_location: common_input
   output_location: dev_location
   mail:
     sender_name: l'expéditeur
     smtp_server: votre_serveur
     login: votre_login
     Mot de passe: top_secret
 le développement:
   <<: * Les valeurs par défaut
 la production:
   <<: * Les valeurs par défaut
   output_location: prod_location 


$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]["mail"]["login"]'
"your_login"
$

Grande, il fonctionne (tm)!.
On peut dire que nous avons échangé un peu de clarté pour un peu de magie. Voici une petite explication: &, * et <<: & ce qui est la balise d'ancrage peut être comprise comme identificateur de nœud, * est nœud de référence et <<: synonyme de fusion de hachage.

Pour plus de détails, voir soit spécifications yaml ou wikipedia
Jusqu'ici tout va bien, mais il ya un hic ici, ces fusions de hachage ne sont pas récursives. Qu'est-ce que cela signifie, c'est ceci: disons que vous voulez que le nom d'expéditeur différent pour le courrier dans les deux environnements, vous pouvez être tenté de faire ce qui suit:

  par défaut: par défaut et
   input_location: common_input
   output_location: dev_location
   mail:
     sender_name: l'expéditeur
     smtp_server: votre_serveur
     login: votre_login
     Mot de passe: top_secret
 le développement:
   <<: * Les valeurs par défaut
   mail:
     sender_name: sender_dev
 la production:
   <<: * Les valeurs par défaut
   output_location: prod_location
   mail:
     sender_name: sender_prod 

Permet de vérifier

$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]["mail"]["login"]'
nil
$

Oups, quelque chose n'allait pas, le problème tel que mentionné ci-dessus est que la fusion de hachage n'est pas récursive et lors de la fusion a remplacé e-mail de défaut par courrier de la production qui a une seule touche. Solution / travail autour est de dérouler un niveau de plus:

  common_settings: & common_settings
 input_location: common_input
 output_location: dev_location
 mail_defaults: & mail_defaults
  sender_name: l'expéditeur
   smtp_server: votre_serveur
   login: votre_login
   Mot de passe: top_secret

 par défaut: par défaut et
   <<: * Les common_settings
   mail:
     <<: * Les mail_defaults
 le développement:
   <<: * Les valeurs par défaut
 la production:
   <<: * Les valeurs par défaut
   mail:
     <<: * Les mail_defaults
     sender_name: sender_prod

Permet de vérifier à nouveau

$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]["mail"]["login"]'
"your_login"
$

Avez-vous dit que vous avez le niveau un plus de nidification, ainsi vous pouvez certainement dérouler un niveau de plus, mais alors il devient un gâchis. Donc, si vous n'êtes pas d'essayer d'écrire une solution à des tours de Hanoï dans un fichier de conf, il est préférable de restucture fichier de conf que de creuser dans yaml ou autre chose. Mais c'est votre appel de toute façon.