Додаток: Техніки 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, якорі будуть втрачені.