Flette hashes i YAML KonFerAnSeGUIde filer

31 juli 2009 ved Prashant · Kommentarer
Arkivert under: teknologi

YAML er ganske hendig for å skrive konfigurasjonsfiler. Primær fordel er at, leser det som tekstfil. Dette fungerer veldig bra hvis config-filen er flat (noe hierarki) og har ingen repetisjoner.
Hvis konfigurasjoner filen har repetisjoner så det er fornuftig å skille ut disse elementene og bruke dem. Hva jeg mener er dette - la oss si at du config-filen ser slik ut:

  utvikling:
   input_location: common_input
   output_location: dev_location
   mail:
     smtp_server: din_server
     login: your_login
     Passord: top_secret
 produksjon:
   input_location: common_input
   output_location: dev_location
   mail:
     smtp_server: din_server
     login: your_login
     Passord: top_secret 

Forutsatt ovenfor koden i / tmp / test.yml her er hvordan du kan lese i python og ruby
$cat readyml.py

 #! / Usr / bin / env python
 fra pprint import pprint som pp
 # I debian må installere python-YAML
 fra YAML import belastning, load_all, dump
 hash = last (open ('/ tmp / test.yml'))
 pp (hash ['utvikling']) 


$ cat readyml.rb

  #! / Usr / bin / env rubin
 kreve 'pp'
 hash = YAML :: belastning (File.open ('/ tmp / test.yml'). lest)
 pp hash ['utvikling'] 

Her er en hendig en liner for ruby ​​versjon
$ ruby -rpp -e 'pp YAML::load(File.open("/tmp/a.yml"))["development"]' eller du kan prøve det samme i IRB eller Python-konsollen.

Merk at i ovennevnte kodebiten, er alt annet enn utskuff er samme i utvikling og produksjon del. Det er der yml node identifikator kommer til unnsetning. Ideen er enkel ha et sett med standardverdier og overstyre dem på forskjellig sted.
Du kan trekke den fra hverandre som følger:

  standardverdier og mislighold
   input_location: common_input
   output_location: dev_location
   mail:
     SENDER_NAME: avsender
     smtp_server: din_server
     login: your_login
     Passord: top_secret
 utvikling:
   <<: * Mislighold
 produksjon:
   <<: * Mislighold
   output_location: prod_location 


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

Flott, det fungerer (tm)!.
Man kan hevde vi handlet litt klarhet for litt magi. Her er en liten forklaring: &, * og <<: & som er ankerkode kan forstås som node identifikator, er * node referanse og <<: står for hasj flettingen.

For flere detaljer se enten YAML specs eller wikipedia
Så langt så bra, men det er en hake her, disse hash fusjonerer er ikke rekursiv. Hva det betyr er dette: La oss si at du vil ha ulik avsender for e-post i to miljøer, kan du bli fristet til å gjøre følgende:

  standardverdier og mislighold
   input_location: common_input
   output_location: dev_location
   mail:
     SENDER_NAME: avsender
     smtp_server: din_server
     login: your_login
     Passord: top_secret
 utvikling:
   <<: * Mislighold
   mail:
     SENDER_NAME: sender_dev
 produksjon:
   <<: * Mislighold
   output_location: prod_location
   mail:
     SENDER_NAME: sender_prod 

Lar sjekk

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

Oops, noe gikk galt, problemer som nevnt ovenfor er at hasj flettingen er ikke rekursiv og samtidig flette den erstattet post mislighold post av produksjon som har kun én tast. Løsning / arbeid rundt er å rulle en mer nivå:

  common_settings: & common_settings
 input_location: common_input
 output_location: dev_location
 mail_defaults: & mail_defaults
  SENDER_NAME: avsender
   smtp_server: din_server
   login: your_login
   Passord: top_secret

 standardverdier og mislighold
   <<: * Common_settings
   mail:
     <<: * Mail_defaults
 utvikling:
   <<: * Mislighold
 produksjon:
   <<: * Mislighold
   mail:
     <<: * Mail_defaults
     SENDER_NAME: sender_prod

Lar sjekk igjen

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

Sa du at du har en mer nivå av hekkende, godt du kan definitivt rulle en mer nivå, men så blir det et rot. Så hvis du ikke prøver å skrive løsningen på tårnene i Hanoi i en conf fil, er det bedre å restucture conf fil enn å grave i YAML eller noe annet. Men det er samtalen uansett.