Додаток: Техніки YAML

Більшість цього посібника зосереджена на написанні мови шаблонів. Тут ми розглянемо формат YAML. YAML має кілька корисних функцій, які ми, як автори шаблонів, можемо використовувати для того, щоб зробити наші шаблони менш схильними до помилок і легшими для читання.

Масиви та Колекції

Згідно зі специфікацією YAML, існують два типи колекцій та багато типів скалярів.

Два типи колекцій — це map та послідовності:

map:
  one: 1
  two: 2
  three: 3

sequence:
  - one
  - two
  - three

Скалярні значення – це окремі значення (на відміну від колекцій).

Типи скалярів у YAML

У діалекті YAML Helm тип даних значення визначається складним набором правил, включаючи схему Kubernetes для ресурсних визначень. Але при визначенні типів, наступні правила зазвичай є правильними.

Якщо ціле число або десяткове число є без лапок, це зазвичай трактуватиметься як числовий тип:

count: 1
size: 2.34

Але якщо вони укладені в лапки, вони трактуються як рядки:

count: "1" # <-- рядок, не int
size: '2.34' # <-- рядок, не float

Те ж саме стосується булевих значень:

isGood: true   # bool
answer: "true" # рядок

Слово для пустого значення — null (не nil).

Зверніть увагу, що port: "80" є дійсним YAML і пройде через рушій шаблонів та парсер YAML, але зазнає невдачі, якщо Kubernetes очікує, що port буде цілим числом.

У деяких випадках ви можете примусово визначити певний тип, використовуючи теґи вузлів YAML:

coffee: "yes, please"
age: !!str 21
port: !!int "80"

У наведеному вище прикладі !!str говорить парсеру, що age є рядком, навіть якщо він виглядає як int. А port трактуватиметься як int, навіть якщо він укладений в лапки.

Рядки в YAML

Більшість даних, які ми розміщуємо в документах YAML, є рядками. YAML має кілька способів представлення рядків. Цей розділ пояснює способи та демонструє, як використовувати деякі з них.

Існують три "вбудовані" способи оголошення рядка:

way1: просто слова
way2: "рядки в подвійних лапках"
way3: 'рядки в одинарних лапках'

Всі вбудовані стилі мають бути в одному рядку.

  • Невкладені слова не мають лапок і не екрановані. Тому потрібно бути обережним із символами, які ви використовуєте.
  • Рядки в подвійних лапках можуть мати спеціальні символи екрановані за допомогою \. Наприклад, "\"Hello\", she said". Можна екранувати розриви рядка за допомогою \n.
  • Рядки в одинарних лапках є "літеральними" рядками та не використовують \ для екранування символів. Єдине екранування — це '', яке декодується як один символ '.

Окрім рядків в один рядок, можна оголосити багаторядкові рядки:

coffee: |
  Latte
  Cappuccino
  Espresso  

Вищенаведене буде трактувати значення coffee як один рядок, еквівалентний Latte\nCappuccino\nEspresso\n.

Зверніть увагу, що перший рядок після | повинен мати вірний відступ. Тому ми можемо зламати приклад вище, зробивши це:

coffee: |
         Latte         
  Cappuccino
  Espresso

Оскільки Latte має неправильний відступ, ми отримаємо помилку на кшталт:

Error parsing file: error converting YAML to JSON: yaml: line 7: did not find expected key

У шаблонах іноді безпечніше помістити несправжній "перший рядок" у багаторядковому документі лише для захисту від цієї помилки:

coffee: |
  # Коментований перший рядок
         Latte
  Cappuccino
  Espresso  

Зауважте, що яким би не був цей перший рядок, його буде збережено у виведенні рядка. Тому, якщо ви, наприклад, використовуєте цю техніку для вливання вмісту файлу в ConfigMap, коментар має бути типу, який очікується тим, хто читає цей запис.

Керування пробілами в багаторядкових рядках

У наведеному вище прикладі ми використовували |, щоб позначити багаторядковий рядок. Але зверніть увагу, що вміст нашого рядка завершувався з кінцевим \n. Якщо ми хочемо, щоб обробник YAML видалив кінцевий перенос рядка, ми можемо додати - після |:

coffee: |-
  Latte
  Cappuccino
  Espresso  

Тепер значення coffee буде: Latte\nCappuccino\nEspresso (без кінцевого \n).

В інших випадках ми можемо захотіти зберегти весь кінцевий пробіл. Ми можемо зробити це за допомогою позначення |+:

coffee: |+
  Latte
  Cappuccino
  Espresso  


another: value

Тепер значення coffee буде Latte\nCappuccino\nEspresso\n\n\n.

Відступи всередині текстового блоку зберігаються, що призводить до збереження переносу рядків:

coffee: |-
  Latte
    12 oz
    16 oz
  Cappuccino
  Espresso  

У наведеному вище випадку значення coffee буде Latte\n 12 oz\n 16 oz\nCappuccino\nEspresso.

Відступи та шаблони

Коли ви пишете шаблони, ви можете захотіти вставити вміст файлу в шаблон. Як ми бачили в попередніх розділах, є два способи зробити це:

  • Використовуйте {{ .Files.Get "FILENAME" }}, щоб отримати вміст файлу в чартах.
  • Використовуйте {{ include "TEMPLATE" . }}, щоб відобразити шаблон, а потім вставити його вміст у чарти.

Коли ви вставляєте файли в YAML, корисно розуміти правила багаторядкових рядків. Найчастіше найпростіший спосіб вставити статичний файл — зробити щось на кшталт цього:

myfile: |
{{ .Files.Get "myfile.txt" | indent 2 }}

Зверніть увагу, як ми виконуємо відступ вище: indent 2 говорить шаблонному двигуну відступити кожен рядок у "myfile.txt" на два пробіли. Зверніть увагу, що ми не відступаємо сам рядок шаблону. Це тому, що якщо ми це зробимо, вміст файлу першого рядка буде відступлений двічі.

Згортання багаторядкових рядків

Іноді вам потрібно представити рядок у вашому YAML на кількох рядках, але ви хочете, щоб він трактувався як один довгий рядок під час інтерпретації. Це називається "згортанням". Щоб оголосити згортання блоку, використовуйте > замість |:

coffee: >
  Latte
  Cappuccino
  Espresso  

Значення coffee буде Latte Cappuccino Espresso\n. Зверніть увагу, що всі, крім останнього переносу рядка, будуть перетворені на пробіли. Ви можете поєднувати контроль пробілів із позначкою згортання тексту, тому >- замінить або обрізає всі нові рядки.

Зверніть увагу, що в згортанні синтаксису відступ тексту призведе до збереження рядків.

coffee: >-
  Latte
    12 oz
    16 oz
  Cappuccino
  Espresso  

Наведене вище створить Latte\n 12 oz\n 16 oz\nCappuccino Espresso. Зверніть увагу, що і пробіли, і нові рядки все ще присутні.

Вбудовування кількох документів в один файл

Можливо розмістити більше одного YAML-документа в одному файлі. Це робиться шляхом префіксації нового документа --- і закінчення документа ...


---
document: 1
...
---
document: 2
...

У багатьох випадках можна опустити --- або ....

Деякі файли в Helm не можуть містити більше одного документа. Якщо, наприклад, у файлі values.yaml надано більше одного документа, буде використано лише перший.

Однак файли шаблонів можуть мати більше одного документа. Коли це трапляється, файл (і всі його документи) обробляється як один обʼєкт під час рендерингу шаблонів. Але потім отриманий YAML розділяється на кілька документів, перш ніж він буде переданий Kubernetes.

Ми рекомендуємо використовувати кілька документів у файлі лише в разі крайньої потреби. Наявність кількох документів у файлі може ускладнити налагодження.

YAML є надмножиною JSON

Оскільки YAML є надмножиною JSON, будь-який дійсний JSON-документ повинен бути дійсним YAML.

{
  "coffee": "yes, please",
  "coffees": [
    "Latte", "Cappuccino", "Espresso"
  ]
}

Вищенаведене є іншим способом представлення цього:

coffee: yes, please
coffees:
- Latte
- Cappuccino
- Espresso

І їх можна змішувати (з обережністю):

coffee: "yes, please"
coffees: [ "Latte", "Cappuccino", "Espresso"]

Усі три повинні перетворюватись в однакове внутрішнє подання.

Це означає, що файли, такі як values.yaml, можуть містити дані JSON, але Helm не трактує розширення файлу .json як дійсний суфікс.

Якорі YAML

Специфікація YAML надає спосіб зберігати посилання на значення і пізніше посилатися на це значення за допомогою посилання. YAML називає це "якорінням":

coffee: "yes, please"
favorite: &favoriteCoffee "Cappuccino"
coffees:
  - Latte
  - *favoriteCoffee
  - Espresso

У наведеному вище прикладі &favoriteCoffee встановлює посилання на Cappuccino. Пізніше це посилання використовується як *favoriteCoffee. Таким чином, coffees стає Latte, Cappuccino, Espresso.

Хоча є кілька випадків, коли якорі корисні, існує один аспект їх використання, який може спричинити тонкі помилки: під час першого використання YAML посилання розширюється і потім видаляється.

Тому, якщо ми декодуємо і потім повторно кодуємо приклад вище, отриманий YAML буде таким:

coffee: yes, please
favorite: Cappuccino
coffees:
- Latte
- Cappuccino
- Espresso

Оскільки Helm і Kubernetes часто читають, змінюють і потім переписують файли YAML, якорі будуть втрачені.