Формат конфигураций с отступами стал языком описания всего: манифесты платформы контейнеров, инвентари автоматизации, сборки контейнеров, конвейеры непрерывной поставки. Читать его глазами приятно, обрабатывать строковыми утилитами мучительно: значимы отступы, вложенность, списки и многострочные документы, и одна неточная правка ломает структуру целиком. Обработчик этого формата для командной строки закрывает потребность так же, как его родственник закрыл её для формата с фигурными скобками. Статья разбирает чтение значений, правку на месте, выборки по фильтрам, многодокументные файлы, подстановку переменных и сценарии применения в непрерывной поставке и служебных скриптах.

Формат конфигураций с отступами и почему он сложнее для командной строки

Формат построен на показе структуры: отступы обозначают вложенность, дефисы обозначают элементы списков, двоеточия разделяют ключи и значения. Для человека это читается почти как проза, для строковых утилит это лес: регулярное выражение, уверенно вырезающее поле из плоской строки, спотыкается на вложенности и отступах, потому что смысл несёт позиция, а не только текст.

Отсюда классические раны автоматизации: скрипт правит строку по образцу, а структура документ в этот момент была с другим отступом; скрипт вставляет строку, а соседний блок из-за этого меняет владельца отступа; скрипт читает значение, а получает его вместе с комментарием и хвостом. Каждый, кто правил такие конфиги через поиск и замену, знает этот набор лично.

Обработчик формата решает задачу структурно: он разбирает документ в дерево, ходит по дереву путями и печатает результат обратно с соблюдением всех правил формата. Правка по адресу не зависит от текущих отступов и соседних строк, а результат обязан быть либо валидным документом, либо понятной ошибкой.

Отдельная ценность для командной строки: инструмент читает и пишет документ сам, без промежуточных файлов и ручной сборки строк. Скрипт оперирует путями и значениями, вся экзотика формата остаётся внутри инструмента, и это то самое разделение труда, ради которого утилиты командной строки и существуют.

Чтение значений из файлов конфигурации одной командой

Первая потребность скрипта это узнать значение: какая версия образца в манифесте, сколько реплик заявлено, какой адрес склада в инвентаре. Обработчик отвечает коротким фильтром с путём:

yq '.spec.replicas' deployment.yaml
yq '.all.hosts.web1.ansible_host' inventory.yaml

Путь читается как адрес: корень, поле, вложенное поле, элемент списка по номеру. Ответ приходит чистым значением, без кавычек и хвостов, и скрипт принимает его в переменную без чистки. Служебный ключ сырого вывода снимает кавычки со строковых значений, а без него значения печатаются в исходном виде формата.

Проверки условий строятся на тех же путях: значение сравнивается с ожиданием прямо в скрипте, и ветвление логики поставки идёт от фактов, а не от предположений. Значение отсутствует, путь ведёт в пустоту, и обработчик честно отвечает пустотой, не падая и не сочиняя, что отличает его от разбора регулярными выражениями, где пустота и ошибка неразличимы.

Чтение в конвейерах работает так же естественно: документы проходят из команды в команду, фильтр вырезает поле, следующее звено получает чистое значение. Разбор выгрузок и ответов инструментов строится без временных файлов, и цепочка из трёх команд читается быстрее, чем один скрипт на тяжёлом языке.

Чтение списков дополняет картину: перебор элементов, число элементов, выборка поля из каждого элемента. Инвентарь автоматизации превращается в список машин одной командой, список образов в манифесте в список версий, и скрипты обхода парк серверов начинают свою работу с одного вызова.

Отдельная дисциплина чтения это проверка структуры: наличие поля, его тип, ожидаемая вложенность. Защитные проверки в начале конвейера ловят кривые документы до того, как они доехали до применения, и одна минута проверки экономит вечер разбора.

Изменение полей с записью на месте и параметризация манифестов

Вторая потребность это правка: поставить номер версии из конвейера, поднять количество реплик, переключить склад инвентаря. Обработчик меняет значение по адресу и записывает документ на место:

yq -i '.spec.template.spec.containers[0].image = "app:42"' deployment.yaml
yq -i '.web.replicas = 6' values.yaml

Ключ записи на месте переворачивает культуру модификации: скрипт не строит копию командой поиска и замены, а делает адресную правку с гарантией формата. Комментарии и порядок полей сохраняются по возможностям формата, документ остаётся читаемым после тысячи автоматических правок, и это отличие важно там, где конфиги читают люди.

Удаление и добавление полей живут теми же путями: удаление по адресу снимает ключ вместе с веткой, добавление строит путь до несуществующего поля и создаёт его. Скрипт параметризации собирает нужную форму документа из входных значений, а не перебирает шаблоны под каждый случай.

Пакетные правки по набору файлов работают из цикла оболочки: список манифестов, фильтр по имени образа, единая правка всем. Массовое обновление версии по каталогу занимает минуту и не требует ни редактора, ни ручной выверки по файлам, и повторяемость правки одинаково работает на пятом файле и на пятидесятом.

Осторожность записи на месте обычная для разрушительных операций: копия перед правкой в важных местах, проверка документа после, привычный откат. Автоматизация освобождает руки, но не отменяет ответственности, и самая дешёвая страховка это строка с копией в скрипте.

Списки условия и выборка по фильтру

Реальные документы это не только плоские поля, но и списки объектов с внутренней структурой: контейнеры манифеста, хосты инвентаря, тома сборки. Обработчик ходит по спискам и выбирает нужное условием: элемент, где поле равно значению, элементы, где поле удовлетворяет шаблону. Выборка одного контейнера по имени из манифеста с несколькими это самая частая операция конвейеров поставки.

Фильтры комбинируются: перебор элементов, условие на каждом, извлечение поля, и результат это список значений или единственный объект. Скрипт спрашивает обработчик о конкретном контейнере, о конкретном хосте, о конкретном томе, и получает точный ответ без обхода документа циклом с переменными.

Преобразование списков дополняет выборки: изменение поля во всех элементах, отбор элементов в новый список, сборка нового документа из выбранных. Инвентарь с десятком групп превращается в выбранный список машин одной группы, и скрипт работает с адресами, а не с границами отступов.

Практический пример выборки из инвентаря: скрипт обслуживания собирает адреса машин выбранной группы, обработчик отдаёт их списком, цикл оболочки обходит. Список машин больше не хранится в двух местах, источником правды остаётся инвентарь, и рассинхронизация списков исчезает как класс проблем.

Условная логика работает и на запись: изменить только элементы, удовлетворяющие условию, оставить остальные нетронутыми. Массовая правка с фильтром это стандартная операция: поднять память у контейнеров с определённым именем, сместить порт у сервисов с устаревшим значением, и правка с условием различает, кому она предназначалась.

Многодокументные файлы и работа с их потоками

Формат допускает несколько документов в одном файле, разделённых служебной строкой из дефисов, и это стандарт для манифестов платформы контейнеров: один файл, в нём описание службы, счётчика и правила входа. Обработчик видит поток документов и ходит по каждому, применяя фильтр ко всем или выбирая по условию.

Выборка по типу документа это классика конвейеров: из общего файла выбираются документы с заданным видом, и к каждому применяется своя правка. Скрипт развёртывания параметризует образ только в документах с контейнерами, не трогая счётчики и правила, и различение это делает по структуре, а не по подсчёту строк.

Слияние и разделение дополняют работу с потоками: документы объединяются в поток для передачи, поток развёртывается в отдельные файлы по документу. Сценарии упаковки и распаковки конфигураций строятся на этих операциях, и каталог с мелкими файлами превращается в единый поток одной командой.

Многодокументность встречается и в неожиданных местах: журналы в этом формате, выгрузки инструментов, ответы интерфейсов с постраничной выдачей. Навык одинаков: видеть поток, уметь выбрать документ по условию, уметь применить фильтр к каждому, и вся экзотика превращается в рутину.

Подстановка переменных окружения вместо ручной сборки строк

Скрипт параметризации упирается в вопрос: как вставить значение из окружения в документ. Ручная сборка строки командой подстановки работает до первого спецсимвола, а значения конвейера сплошь из тегов, адресов и путей. Обработчик подставляет значение из окружения сам, внутри фильтра:

export APP_TAG="2.4.1"
yq -i '.image.tag = env(APP_TAG)' values.yaml

Подстановка изнутри гарантирует экранирование: кавычки, двоеточия и дефисы в значении не ломают структуру документа, потому что значение приходит значением, а не текстом фильтра. Скрипты параметризации сокращаются до пары строк: приняли переменные, применили фильтр, передали документ дальше.

Связка с конвейером поставки прямая: сборка вычисляет номер версии, окружение несёт его в переменной, скрипт подставляет в манифест, следующий шаг применяет документ к системе. Никаких промежуточных файлов, никаких правок по образцу, и версия в документе совпадает с версией в артефакте по построению.

То же работает в обратную сторону: скрипт читает значение из документа в переменную и использует в логике. Двустороннее движение между документом и окружением покрывает все сценарии параметризации, и ручная сборка строк уходит из скриптов как класс.

Обратная подстановка закрывает цикл: скрипт читает текущее значение из документа, сравнивает с целевым, меняет при отличии и пишет короткую строку о действии. Идемпотентность на уровне конвейера: повторный запуск ничего не меняет и тихо завершается, и это свойство ценится в любых регламентных заданиях.

Рабочие сценарии yq от непрерывной поставки до служебных скриптов

Сценарии, в которых обработчик становится незаменимым, выглядят так:

  1. Подстановка номера версии из конвейера в манифест перед развёртыванием;
  2. Параметризация количества реплик и ресурсов по окружениям;
  3. Правка инвентарей автоматизации скриптами миграции и обслуживания;
  4. Выборка машин из инвентаря для обхода парка в служебных скриптах;
  5. Проверка структуры документов до передачи в следующие звенья;
  6. Массовые правки по каталогам манифестов с фильтрами по типу.

За списком стоит экономика: каждый сценарий без обработчика это либо ручная работа с файлами, либо хрупкий разбор строк. Обработчик переносит эти сценарии из ремесла в автоматизацию, и цена ошибки падает с испорченного конфигурации до понятного отказа с описанием.

Итоговое суждение практичное. Обработчик формата с отступами это недостающий кусок пазла командной строки: там, где для формата с фигурными скобками давно работает его родственник, для конфигураций с отступами годами держалась дыра, и скрипты страдали молча. Инструмент закрывает дыру зрелым языком фильтров, и скрипты параметризации, которые раньше писались с опаской и правились с ужасом, теперь пишутся за минуты и работают годами. Для конвейеров поставки, инвентарей и всякой автоматизации вокруг конфигураций это ровно тот инструмент, которого не хватало.
Мелкая привычка с большим эффектом: после каждой автоматической правки важного документа скрипт прогоняет проверку структуры и печатает короткую строку результата. Две строки кода превращают молчаливую порчу в громкое уведомление, и доверие к автоматизации растёт с каждым зелёным прогоном.