需要避免的七個YAML陷阱
譯文?譯者 | 李睿
審校 | 孫淑娟
YAML (“YAML Ain't Markup Language”)配置語言是許多現(xiàn)代應(yīng)用程序的核心,包括Kubernetes、Ansible、CircleCI和Salt。YAML提供了許多優(yōu)勢,例如可讀性、靈活性以及處理JSON文件的能力。但是對于沒有經(jīng)驗或粗心的人來說,YAML也是一種陷阱或是陷阱的來源。
YAML行為的許多方面都考慮到了暫時的便利,但其代價是以后會出現(xiàn)意想不到的曲折或麻煩。即使是具有豐富組裝或部署YAML經(jīng)驗的人也可能會被這些問題所困擾,這些問題通常以看似無害的行為的幌子而浮出水面。
可以采取以下七個步驟來防范YAML中最棘手的問題。
1.如有疑問,請引用字符串?
編寫YAML時可以采用的最強大的防御實踐:引用所有應(yīng)為字符串的內(nèi)容。
YAML最著名的怪癖之一是,可以編寫字符串而無需引用:
- movie:
title: Blade Runner
year: 1982
在這一示例中,鍵movie、title和year將被解釋為字符串,值Blade Runner也將被解釋為字符串。值1982將被解析為數(shù)字。
但是這里會發(fā)生什么?
- movie:
title: 1979
year: 2016
沒錯,電影片名將被解釋為一個數(shù)字。這甚至還不是可能發(fā)生的最糟糕的事情:
- movie:
title: No
year: 2012
這個標題被解釋為布爾值的幾率是多少?
如果想絕對確保鍵和值將被解釋為字符串,并防止任何潛在的歧義(很多歧義可能會潛入YAML),請引用字符串:
- "movie":
"title": "Blade Runner"
"year": 1982
如果由于某種原因無法引用字符串,則可以使用速記前綴來指示類型。這些使YAML比引用的字符串讀起來更嘈雜,但它們與引用一樣明確:
movie: !!str Blade Runner
2.當心多行字符串
YAML有多種方式來表示多行字符串,具體取決于這些字符串的格式。例如,當前綴為“>”時,未加引號的字符串可以簡單地跨多行斷開:
long string: >
This is a long string
that spans multiple lines.
需要注意的是,使用>會自動在字符串末尾附加一個\n。如果不想要尾隨的新行,使用>-而不是>。
如果使用帶引號的字符串,則需要在每個換行符前加上反斜杠:
long string: "This is a long string \
that spans multiple lines."
需要注意的是,換行符后的任何空格都被解釋為YAML格式,而不是字符串的一部分。這就是上例中在反斜杠之前插入空格的原因。
3.小心布爾值
正如上面所暗示的,YAML的另一個大問題之一是布爾值。在YAML中有很多方法可以指定布爾值,因此很容易將預(yù)期的字符串解釋為布爾值。
一個臭名昭著的例子是兩位數(shù)的國家代碼問題。如果你所在的國家/地區(qū)是美國或英國,則是YES。如果所在的國家是挪威,其國家代碼是NO,則它不再是一個字符串,而是一個計算結(jié)果為false的布爾值!
只要有可能,特意使用布爾值和可能被誤解為布爾值的較短字符串。YAML的布爾值速記前綴是!!bool。
4.注意多種形式的八進制
多種形式的八進制是一個不為人知的問題,但它可能很麻煩。YAML 1.1對八進制數(shù)使用了與YAML 1.2不同的符號。在YAML 1.1中,八進制數(shù)看起來像0777。在YAML1.2中,相同的八進制數(shù)變成0o777。這樣就不那么模棱兩可了。
Kubernetes是YAML的最大用戶之一,它使用YAML1.1。如果將YAML與使用規(guī)范1.2版的其他應(yīng)用程序一起使用,特別注意不要使用錯誤的八進制表示法。由于如今八進制通常僅用于文件權(quán)限,因此與其他YAML陷阱相比,這是一個極端情況。盡管如此,如果不小心,YAML八進制可能會帶來麻煩。
5.小心可執(zhí)行的YAML
可執(zhí)行YAML?是的,有許多YAML庫,例如Python的PyYAML,在反序列化YAML時允許執(zhí)行任意命令。令人驚訝的是,這不是一個bug,而是YAML設(shè)計允許的功能。
在PyYAML的情況下,反序列化的默認行為最終被更改為只支持不允許這種事情的安全YAML子集。原始行為可以進行人工恢復(fù),但如果可以,應(yīng)該避免使用這一功能,如果尚未禁用,則應(yīng)默認禁用這一功能。
6.序列化和反序列化時要注意不一致
YAML的另一個潛在問題是, 跨不同編程語言的不同YAML處理庫有時會產(chǎn)生不同的結(jié)果。
需要考慮的是:如果有一個包含表示為true和false的布爾值的YAML文件,并且使用一個不同的庫將其重新序列化為YAML,該庫表示布爾值為y和n或on和off,可能會得到意想不到的結(jié)果。即使代碼在功能上保持不變,它也可能看起來完全不同。
7.不要使用YAML
避免YAML問題的通用方法是什么?不要使用它?;蛘咧辽俨灰苯邮褂盟?/p>
如果必須作為配置過程的一部分編寫YAML,則更安全的做法是使用JSON或原生代碼(例如Python字典)編寫代碼,然后將其序列化為YAML??梢愿玫乜刂茖ο蟮念愋停⑶铱梢愿匀绲厥褂靡呀?jīng)使用過的語言。
如果做不到這一點,可以使用yamllint之類的linter來檢查常見的YAML問題。例如,可以禁止像YES或off這樣的真值,以支持簡單的true和false,或者強制字符串引用。
原文鏈接:https://www.infoworld.com/article/3669238/7-ugly-yaml-gotchas-to-avoid-and-how-to-avoid-them.html