yq: инструмент YAML, который должен знать каждый специалист DevOps
Это перевод оригинальной статьи yq: The YAML Tool Every DevOps Should Know.
Подписывайтесь на телеграм-канал usr_bin, где я публикую много полезного по Linux, в том числе ссылки на статьи в этом блоге.
Создавайте и редактируйте YAML-файлы без ошибок
YAML стал основой DevOps, но достаточно одной незаметной опечатки, чтобы всё сломать.
YAML захватил современный DevOps. Он лежит в основе Kubernetes, GitHub Actions, CloudFormation, Docker Compose — по сути, почти всего. YAML — мощный инструмент, но его невероятно легко сломать. Один неправильный пробел, один пропущенный дефис — и вся наша система отказывается запускаться.
В этой статье мы подробно рассмотрим yq, суперспособность командной строки, которая предотвращает сбои в работе с YAML. Мы расскажем, как с помощью yq редактировать, проверять и автоматизировать YAML без опасений.
Введение в yq
Что такое yq?
yq — инструмент командной строки, предназначенный для безопасного чтения, редактирования, проверки и преобразования файлов YAML. Представьте jq как мощный, предсказуемый и идеально подходящий для автоматизации инструмент для работы с YAML.
Зачем использовать yq?
- Просматривать и выполнять запросы к глубоко вложенным YAML-файлам
- Безопасно изменять значения, массивы и ключи.
- Объединять несколько YAML-файлов интеллектуально.
- Применять условную логику и автоматизацию.
Начало работы с yq
Установка
Прежде чем использовать yq, нам необходимо установить его в нашей системе. yq доступен для macOS, Linux и Windows, и мы даже можем запускать его непосредственно из Docker без установки чего-либо локально.
# macOS brew install yq # Linux (binary) sudo wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 \ -O /usr/bin/yq && sudo chmod +x /usr/bin/yq # Windows (Scoop) scoop install yq
Проверка
После установки yq убедитесь в работоспособности, проверив версию:
yq --version
Это подтверждает, что yq установлен, доступен для выполнения и работает корректно.
Базовые операции и синтаксис
Базовая структура команды достаточно проста:
yq [flags] '<expression>' [file(s)]
yq— сама командаflags— необязательные параметры, которые изменяют поведениеyq. Например:-i— редактирование на месте,-o=json— вывод в формате JSON.'<expression>'— запрос или операция, которую мы хотим выполнить над файлом YAML.[file(s)]— один или несколько YAML-файлов для чтения (config.yml,*.yml)
В рамках этого руководства мы будем использовать YAML-файл:
app:
name: demo # key/value
version: 1.0 # key/value
ports: # key with a sequence (array) value
- 80
- 443app:
name: other
version: 2.0
ports:
- 3000Чтение и запрос значений.
Мы используем оператор точки (.) для обхода ключей и квадратные скобки ([]) для обращения к индексам массивов.
yq '.' testing.yaml
Чтение конкретного ключа (обход ключа):
yq '.app' testing.yaml
yq '.app.name' testing.yaml
Чтение конкретного элемента массива:
yq '.app.ports[0]' testing.yaml
yq e '.app.version' *.yaml
*.yamlсоответствует нескольким файламyqвыводит результаты по одному файлу.---является разделителем документов в YAML
Вставка/обновление значений (на месте)
Используем для этого оператор присваивания (=) и флаг -i (редактирование на месте).
yq e -i '.app.name = "new-demo"' testing.yaml
-i(редактирование на месте) — изменяет входной файл(ы) напрямую. Использовать с осторожностью!e/eval— вычислить выражение в соответствии с YAML-файлом. Без параметраeфайл может быть не изменен.'app.name'— если ключ существует, он обновляется; в противном случае создаётся.
yq -i '.app.replicas = 5' testing.yaml
Вставка/обновление элемента массива:
yq e -i '.app.ports[0] = 8081' testing.yaml
Использование переменных окружения:
NAME=prod yq -i '.env = strenv(NAME)' config.yaml
`yq -i '.a = 1
До версии v4yqиспользовалась только команда `eval`, поэтому команда была проще. Но теперь в yq v4 есть разные подкоманды, например:e/eval,w,m/merge,d/diff. Всегда используйтеyq eпри чтении или редактировании..
Удаление, объединение и добавление
Удаление ключей или значений массива
yq e -i 'del(.app.replicas)' testing.yaml yq e -i 'del(.app.ports[1])' testing.yaml
yq e -i '.app.ports += [9090]' testing.yaml
.app.ports— путь к массивуportsвнутри ключаapp+= [9090]— добавляет значение9090к существующему массиву
yq e -i '.app.ports += [5000, 5001]' testing.yaml
yq e -i '.services += [{"name": "cache", "port": 6379}]' file.yaml+= [...]— добавляет новые элементы в существующий массив{...}— объект JSON внутри массива — добавляет сложный объект, а не просто число или строку.
yq -n 'load("testing.yaml") * load("other.yaml")'-n— начать с пустого документа вместо чтения из stdinload("testing.yaml")— загрузить файл testing.yaml как объект YAML.*— оператор объединения (overlay merge)load("other.yaml")— загрузить файл 2 и объединить его с файлом 1
- Любые совпадающие ключи из
other.yamlпереопределят значения вtesting.yaml. - Если ключ существует в
other.yaml, но отсутствует вtesting.yaml, он будет добавлен к результату. - Что касается массивов, то
yqполностью заменяет их вместо добавления новых элементов
Объединение двух файлов с добавлением массивов вместо замены:
yq -n 'load("testing.yaml") *+ load("other.yaml")'Объединить и сохранить результат:
yq -n 'load("testing.yaml") * load("other.yaml")' > merged.yamlИспользование переменных окружения в yq
В автоматизации (CI/CD, Docker, Kubernetes) часто возникает необходимость, чтобы yq напрямую подставлял динамические значения (например, переменные окружения) в YAML-файлы. Функция yq позволяет сделать это без проблем env().
Предположим, у нас есть переменная окружения:
export PORT=8088
Значение переменной окружения можно внедрить следующим образом:
yq e -i '.app.ports[0] = env(PORT)' testing.yaml
Мы также можем избежать случайного преобразования числа в строку:
yq e -i '.app.replicas = (env(REPLICAS) | tonumber)' file.yaml
Расширенная фильтрация и логика
yq унаследовал мощные возможности фильтрации и обработки из языка выражений jq.
- выбрать элементы по условию
- обновлять только подходящие поля
- удалить определенные объекты
- динамически преобразовывать значения
- выполнять циклы и вычисления выражений
Давайте отредактируем наш файл testing.yaml, прежде чем переходить к следующему шагу.
app:
name: demo-app
version: 1.0
enabled: true
ports:
- 8080
- 443
replicas: 2
services:
- name: api
url: https://api.demo.local
role: backend
- name: frontend
url: https://demo.local
role: web
- name: db
url: postgresql://db.demo.local
role: database
debug: false
metadata:
environment: staging
owner: devops-teamПоиск элементов по условию
yq '.services[] | select(.role == "database")' testing.yaml
.services[]— перебор каждого элемента массиваservices.select(...)— оставляет только элементы, соответствующие условию.role == "database"(условие) — фильтр: выбираем только те элементы, у которых ключroleравенdatabase
Условные обновления
yq -i '(.app.replicas | select(. < 3)) = 3' testing.yaml
- Обновляет поле
replicasвappтолько в том случае, если его текущее значение меньше 3, и записывает изменение обратно в файл.
Удаление объектов из массива на основе правила
yq -i '.services |= map(select(.role != "web"))' testing.yaml
map(...)— обработка каждого элемента массиваselect(...)— оставляет только элементы, подходящие под условие.role != "web"(Условие) — оставляем всё, кроме элементов сroleравным"web"
Динамическое преобразование значений
yq -i '.services[].url |= . + ":latest"' testing.yaml
.url— целевое полеurlкаждого элемента. + ":latest"— берём текущее значение (.) и добавляем:latest
Логика с использованием конструкции if-then-else
Включение режима отладки только для окружения staging:
yq -i '
if .metadata.environment == "staging" then
.debug = true
else
.
end
' testing.yamlif .metadata.environment == "staging"(Состояние) — проверьте значениеenvironmentthen .debug = true— действие, если условие истинноelse .— оставляем всё без изменений, если условие ложно.end— Конец блока if-then-else
Работа с различными форматами
Одна из самых мощных функций — yq v4 это возможность возможность конвертации между YAML, JSON и даже raw strings. Это особенно полезно в современных конвейерах DevOps, где разные инструменты могут требовать разные форматы.
YAML в JSON
yq eval -o=json testing.yaml > testing.json
JSON в YAML
yq eval -P testing.json > testing.yaml
Чтение из stdin:
cat testing.json | yq eval '.app.name' -
Манипуляции со строками inline:
yq eval '"Hello " + .app.name' testing.yaml
- Объединяет данные
Helloс полемapp.name. Работает также с числами, булевыми значениями и массивами.
Заключительные мысли
Благодаря yq, редактирование YAML-файлов перестаёт быть сложным и чреватым ошибками — он становится безопасным, эффективным и полностью автоматизированным. yq — это не просто парсер YAML, это мощный инструмент, готовый к автоматизации, который позволяет нам:
- Читать, запрашивать и фильтровать глубоко вложенные данные YAML
- Безопасно обновлять, добавлять или удалять ключи и элементы массивов
- Объединять несколько YAML-файлов с возможностью управления массивами и объектами.
- Бесперебойно работать с такими форматами, как YAML и JSON.
- Применять логические и условные преобразования для автоматизации конфигураций.
На этом все! Спасибо за внимание! Если статья была интересна, подпишитесь на телеграм-канал usr_bin, где будет еще больше полезной информации.