La fusió dels hashes dels arxius de conf YAML

31 juliol 2009 per Prashant · Comentaris
Filed under: la tecnologia

YAML és molt útil per escriure fitxers de configuració. Principal avantatge és que, es llegeix com a fitxer de text. Això funciona molt bé si el seu fitxer de configuració és plana (sense jerarquia) i no té repeticions.
Si el seu fitxer de configuració té repeticions, llavors té sentit per separar els elements i tornar a usar-los. El que vull dir és això - diguem que el seu arxiu de configuració és la següent:

  el desenvolupament:
   input_location: common_input
   output_location: dev_location
   mail:
     smtp_server: su_servidor
     d'inici de sessió: your_login
     contrasenya: top_secret
 producció:
   input_location: common_input
   output_location: dev_location
   mail:
     smtp_server: su_servidor
     d'inici de sessió: your_login
     contrasenya: top_secret 

Suposant que el codi anterior a / tmp / test.yml aquí és com es pot llegir en Python i Ruby
$cat readyml.py

 #! / Usr / bin / python env
 pprint d'importació pprint com pp
 # Debian al d'instal · lar python-YAML
 de la càrrega d'importació YAML, load_all, bolcat
 hash = càrrega (open ('/ tmp / test.yml'))
 pp (hash ['desenvolupament']) 


$ cat readyml.rb

  #! / Usr / bin / env ruby
 requereix 'pp'
 hash = YAML :: load (File.open ('/ tmp / test.yml'). llegir)
 pp hash ['desenvolupament'] 

aquí hi ha una mà un traçador de línies de la versió de Ruby
$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]' o pots intentar el mateix a l'IRB o la consola de python.

Tingueu en compte que en el fragment de codi anterior, tot és diferent d'ubicació de sortida és la mateixa en el desenvolupament i la part de producció. Aquí és on identificador de node yml ve a rescatar. La idea és senzilla té un conjunt de valors predeterminats i reemplaçar ells en lloc diferent.
Vostè podria separar-la de la següent manera:

  per defecte i per defecte:
   input_location: common_input
   output_location: dev_location
   mail:
     sender_name: emissor
     smtp_server: su_servidor
     d'inici de sessió: your_login
     contrasenya: top_secret
 el desenvolupament:
   <<: * Els valors per defecte
 producció:
   <<: * Els valors per defecte
   output_location: prod_location 


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

Gran, que funciona (tm)!.
Es podria dir que negocien una mica de claredat a una mica de màgia. Aquí hi ha una petita explicació: &, * i <<: i que és etiqueta d'ancoratge pot ser entès com a identificador de node, * és la referència de node i <<: és sinònim de fusió de hash.

Per a més detalls vegi bé les especificacions YAML o wikipedia
Fins aquí tot bé, però hi ha un problema aquí, aquestes fusions hash no són recursius. El que significa és el següent: diguem que vostè vol ser el nom del remitent per al correu diferents en dos ambients, vostè pot estar temptat a fer el següent:

  per defecte i per defecte:
   input_location: common_input
   output_location: dev_location
   mail:
     sender_name: emissor
     smtp_server: su_servidor
     d'inici de sessió: your_login
     contrasenya: top_secret
 el desenvolupament:
   <<: * Els valors per defecte
   mail:
     sender_name: sender_dev
 producció:
   <<: * Els valors per defecte
   output_location: prod_location
   mail:
     sender_name: sender_prod 

Permet comprovar

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

Vaja, alguna cosa va sortir malament, el problema com es va esmentar anteriorment és que la combinació hash no és recurrent i si bé la fusió del reemplaçar de correu electrònic per defecte per correu de la producció que té una sola clau. Solució / s treball al voltant de desenrotllar un nivell més:

  common_settings: & common_settings
 input_location: common_input
 output_location: dev_location
 mail_defaults: & mail_defaults
  sender_name: emissor
   smtp_server: su_servidor
   d'inici de sessió: your_login
   contrasenya: top_secret

 per defecte i per defecte:
   <<: * Common_settings
   mail:
     <<: * Mail_defaults
 el desenvolupament:
   <<: * Els valors per defecte
 producció:
   <<: * Els valors per defecte
   mail:
     <<: * Mail_defaults
     sender_name: sender_prod

Anem a comprovar de nou

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

Sabia vostè que tens un nivell de més d'implantació, així que definitivament es pot desenrotllar un nivell més, però llavors es converteix en un desastre. Per tant, si vostè no està tractant d'escriure la solució a les torres de Hanoi en un arxiu de conf, és millor restucture conf a cavar en YAML o alguna altra cosa. Però això és la crida de totes maneres.