Перейти к содержимому

info.yml

Конфигурация дашборда info.

workspace/info.yml объявляет содержимое дашборда dwe info: секции, элементы, условную видимость и шаблонные выражения. CLI рендерит его на каждом вызове dwe info.

Загружается отдельно. Не участвует в трёхслойном мердже.

sections:
- id: <section-id>
title: "Optional Section Title" # shown as a bordered box header
items:
- type: <item-type>
<item-fields>
footer: true
ПолеТипПо умолчаниюОписание
sectionslistУпорядоченный список определений секций.
footerboolfalseЕсли true, после всех секций рендерится завершающая строка-заголовок таблицы.
ПолеТипПо умолчаниюОписание
idstringУникальный идентификатор секции
titlestringОпциональный заголовок, рендерящийся над списком элементов
itemslistУпорядоченный список определений элементов
hide_on_emptyboolfalseПолностью пропустить секцию (без заголовка, без рамки), если ни один элемент не прошёл when-фильтрацию. Замечание: у subgroup’ов другой дефолт (true).
ТипРендерится какОбязательные поля
definitionСтрока Label — Value, с опциональной иконкойname, value
infoСтрока info-цветаtext
warningСтрока warning-цветаtext
auto-urlsДинамически сгенерированные URL’ы, организованные по сервисам
auto-hostsДинамически сгенерированные имена хостов из сервисов
subgroupКонтейнер с опциональным заголовком и вложенными элементамиitems
separatorПустая строка-разделитель

Все элементы принимают опциональный when: (Go template-выражение). Элементы с falsy when исключаются из рендера. Все элементы поддерживают опциональный булев флаг decorative (см. Декоративные элементы).

Замечание о рендеринге auto-urls и auto-hosts: элементы auto-urls и auto-hosts раскрываются во время рендера (когда выполняется dwe info), а не во время загрузки YAML. Раскрытие учитывает текущий конфиг и итерирует включённые сервисы в deploy-порядке, так что дашборд всегда отражает актуальные определения и состояние сервисов.

Пара label + value, рендерится как Label — Value.

- type: definition
name: Project
value: "{{ .Project.FullName }}"
icon: "🔗"
indent: 2
when: "{{ .State }}"
ПолеОписание
nameТекст метки
valueТекст значения (обычная строка или шаблонное выражение)
iconОпциональная эмодзи или символ, подставляемый перед значением. Предпочитайте кодпойнты с Emoji_Presentation=Yes (например, 📦, 🐳, 💾); text-default кодпойнты вроде 🛢, 🗄, помечаются dwe validate и отбрасываются во время рендера, чтобы сохранить выравнивание колонок — полный комментарий см. в поле icon в справочнике сервисов.
indentОпциональное число ведущих пробелов. Дефолт для definition-элементов — 2; передайте 0, чтобы прижать к левому краю. Отрицательные значения не принимаются.
whenУсловие; элемент скрыт, если falsy

Информационная текстовая строка.

- type: info
text: '127.0.0.1 {{ (index .Services "main").Host "web" }}'
indent: 0
when: '{{ (index .Services "adminer").Enabled }}'
ПолеОписание
textТекст сообщения (обычная строка или шаблонное выражение)
indentОпциональное число ведущих пробелов
whenУсловие; элемент скрыт, если falsy

Строка-предупреждение (рендерится в warning-цвете).

- type: warning
text: "Please add this to your /etc/hosts file:"
ПолеОписание
textТекст предупреждения (обычная строка или шаблонное выражение)
whenУсловие; элемент скрыт, если falsy

Динамически генерирует список URL сервисов из настроенных сервисов проекта. Сервисы объявляют свои хосты и порты в workspace/services/<name>/service.yml; auto-urls рендерит их с опциональной фильтрацией и кастомизацией.

- type: auto-urls
include: [app, tool]
hide: [varnish]
hide_paths:
main: ["SPX profiler"]
port_via: nginx
when: "{{ .Services }}"
ПолеТипПо умолчаниюОписание
includelist[app, tool]Типы сервисов для включения: любая комбинация app, tool, infra.
hidelistКлючи папок сервисов, которые нужно полностью исключить. Неизвестные ключи молча игнорируются.
hide_pathsmapИсключить отдельные суб-пути по ключу сервиса и имени пути (например, main: ["SPX profiler"] скрывает путь “SPX profiler” в сервисе “main”).
port_viastringauto-detectedЗадаёт, какой сервис использовать как front-прокси для генерации основных URL. Если пусто, авто-детект ищет один включённый сервис type: infra, объявляющий либо ports.http: 80 (http-трафик), либо ports.https: 443 (https-трафик). Явно названные отсутствующие сервисы помечаются dwe validate, а не во время рендера. Авто-детект возвращает «без прокси», если найдено ноль или несколько кандидатов (в этом случае рендерятся только прямые URL localhost:<port>).
whenstringУсловие; элемент скрыт, если falsy.

Примеры авто-детекта port_via:

С авто-детектом (дефолт — без поля port_via:):

# Auto-detects if exactly one infra service has ports.http: 80
- type: auto-urls
include: [app, tool]

В этом случае, если сервис nginx имеет ports: {http: 80}, type: infra и включён, он выбирается автоматически. App- и tool-сервисы тогда рендерятся как proxied URL | localhost:port (если они объявляют собственные порты) или просто proxied URL (если есть только host). Остальные сервисы без авто-детектированного прокси рендерятся только как localhost:port.

С явным переопределением port_via::

# Always use named service as proxy, even if it's not type: infra
- type: auto-urls
include: [app, tool]
port_via: api_gateway

Если port_via задан явно, но указывает на несуществующий сервис, dwe info молча рендерит без прокси (прямые/host-only URL); отсутствующий сервис помечается только dwe validate (SeverityError). Названный сервис используется для построения прокси-URL независимо от его type:.

Если авто-детект находит ноль или несколько infra-сервисов с целевым портом, прокси не выбирается и сервисы рендерятся только со своими прямыми портами (или только с хостами, если порт отсутствует):

# No eligible infra service found → app/tool with only localhost:<port> URLs
- type: auto-urls
include: [app, tool]

Сервисы участвуют в auto-urls через свой блок info: в service.yml (схема — в services/index.md). Каждый сервис может объявить:

  • title — переопределяет заголовок сервиса (по умолчанию — title-cased имя папки)
  • primary_host — какую запись hosts поднимать как основной URL (дефолт: web)
  • primary_port — какую запись ports поднимать (дефолт: http)
  • paths — упорядоченный список суб-путей под основным URL

Сервисы без блока info включаются в типы include, но рендерят только свой основной URL, если присутствуют хосты и порты.

Правила сборки URL:

  • hosts[primary_host] и ports[primary_port] (прямой биндинг) → <proxied URL> | <direct URL>
  • только hosts[primary_host]<proxied URL> (если port_via доступен)
  • только ports[primary_port]http://localhost:<port>
  • ни того, ни другого → строка молча пропускается

<proxied URL> использует порты сервиса port_via для выбора схемы/порта, но info.scheme самого маршрутизируемого сервиса (если задан) имеет более высокий приоритет и также задаёт, какой listener прокси (http или https) будет использован — полная цепочка приоритета описана в URL’ы через reverse-proxy в services/fields.md. <direct URL> использует собственный порт сервиса. Внутри <proxied URL> порты :80 (http) и :443 (https) опускаются; <direct URL> всегда показывает свой порт.

Динамически генерирует список всех имён хостов из сервисов для конфигурации /etc/hosts.

- type: auto-hosts
include: [app, tool, infra]
ip: 127.0.0.1
hide: [varnish]
when: "{{ .Services }}"
ПолеТипПо умолчаниюОписание
includelist[app, tool, infra]Типы сервисов для включения: любая комбинация app, tool, infra.
ipstring127.0.0.1IP-адрес, ассоциируемый со всеми именами хостов. Значения здесь не валидируются на формат IP; dwe validate выдаёт предупреждение, если парсинг падает.
hidelistКлючи папок сервисов для полного исключения. Неизвестные ключи молча игнорируются.
whenstringУсловие; элемент скрыт, если falsy.

Рендерит каждую запись hosts из включённых сервисов в двухколоночной таблице (IP Hostname), сохраняя deploy-порядок, дедуплицируя имена хостов и пропуская пустые значения, литеральный localhost и любой хост *.localhost (они автоматически резолвятся в 127.0.0.1 и не требуют записи в /etc/hosts).

Элемент-контейнер, группирующий связанные элементы и опционально показывающий заголовок.

- type: subgroup
title: "Tools"
hide_on_empty: false
items:
- type: definition
name: Adminer
icon: "🛢"
value: '{{ appURL ((index .Services "adminer").Host "web") ((index .Services "main").Port "http") .Runtime.UseHTTPS }}'
when: '{{ (index .Services "adminer").Enabled }}'
- type: definition
name: RedisInsight
icon: "📊"
value: '{{ appURL ((index .Services "redis_insight").Host "web") ((index .Services "main").Port "http") .Runtime.UseHTTPS }}'
when: '{{ (index .Services "redis_insight").Enabled }}'
ПолеТипПо умолчаниюОписание
titlestringОпциональный заголовок subgroup’а (обычная строка или шаблонное выражение). Если пуст, subgroup рендерится без заголовка.
itemslistОбязательное. Упорядоченный список определений дочерних элементов. Может содержать любой тип элемента, включая вложенные subgroup’ы.
whenstringУсловие; если falsy, весь subgroup (включая все вложенные элементы) пропускается. Если truthy, каждый дочерний элемент вычисляется по собственному when.
hide_on_emptybooltrueПолностью пропустить subgroup, если ни один дочерний элемент не прошёл when-фильтрацию. (Противоположно дефолту секций; у subgroup’ов дефолт — true.)
decorativeboolfalseЕсли true, subgroup никогда не считается контентом для родительской проверки hide_on_empty, даже если он производит вывод.

Subgroup’ы могут быть вложены произвольно.

Пустая строка для разделения контента внутри секции.

- type: separator

Без полей. Полезен, когда между соседними элементами нужен визуальный отступ без введения новой секции.

По умолчанию элементы делятся на две категории: content-элементы, которые засчитываются для видимости секции, и декоративные — нет.

ТипДефолт decorative
definitionfalse
infofalse
warningfalse
subgroupfalse
separatortrue

Флаг decorative на любом типе элемента переопределяет дефолт:

- type: warning
text: "Only informational"
decorative: true # Makes this warning not count as content
- type: separator
decorative: false # Makes this separator count as content, keeping the section visible

Когда hide_on_empty: true на секции или subgroup, блок полностью пропускается, если ни один элемент не прошёл и when-фильтрацию, и проверку content-vs-decorative. Блок только с декоративными элементами (или без элементов) всё равно может отрендериться, если у него есть title и hide_on_empty: false.

Все поля text, value и when поддерживают синтаксис Go template, вычисляемый поверх разрешённой конфигурации проекта.

ВыражениеТипОписание
{{ .Project.Name }}stringИмя проекта
{{ .Project.FullName }}stringОбъединённый префикс + имя
{{ .State }}stringАктивное состояние (пусто, если нет)
{{ .Runtime.UseHTTPS }}boolHTTPS включён.
{{ .Runtime.SPX.Path }}stringПуть SPX-профайлера.
{{ (index .Services "main").Enabled }}boolВключён ли сервис main (обязательные сервисы всегда true).
{{ (index .Services "main").Container }}stringИмя контейнера сервиса main.
{{ (index .Services "main").Port "http" }}intПоиск порта по имени. Port(name) — метод на ServiceConfig (возвращает 0, если отсутствует).
{{ (index .Services "main").Host "web" }}stringПоиск хоста по имени. Host(name) возвращает "", если отсутствует.
{{ (index .Services "main").PortScheme "http" }}stringPer-port переопределение схемы из развёрнутой формы записи. Возвращает "", если переопределение не задано.
{{ (index .Services "main").EffectiveScheme "http" .Runtime.UseHTTPS }}stringРезолвит эффективную схему URL ("http" / "https") по цепочке: per-port → info.schemeruntime.use_https.
{{ .AppServices }} / {{ .ToolServices }} / {{ .InfraServices }}map[string]ServiceConfigПодмножества, отфильтрованные по type: — удобно для {{ range }} по одной категории.

Info-шаблонам доступен стандартный набор хелперов DWE-шаблонов: доменный хелпер appURL плюс реестры sprout (std, strings, numeric, slices, maps, regexp, conversion, time, filesystem, semver). Полный справочник хелперов — в Шаблонах.

Пример использования appURL:

value: '{{ appURL ((index .Services "main").Host "web") ((index .Services "main").Port "http") .Runtime.UseHTTPS }}'
# → http://laravel.localhost (or https://… when use_https is true)

Поля when принимают любое шаблонное выражение, которое вычисляется в truthy/falsy-значение. Пустая строка, false и 0 — falsy; всё остальное — truthy.

when: "{{ .State }}" # show only when state is non-empty
when: '{{ (index .Services "adminer").Enabled }}' # show only when adminer is enabled
when: "{{ .Runtime.SPX.Path }}" # show only when SPX path is set
footer: true

Если true, под всеми секциями рендерится строка-футер (обычно показывает help-подсказку).

Поведение по умолчанию при отсутствии info.yml

Заголовок раздела «Поведение по умолчанию при отсутствии info.yml»

Если workspace/info.yml не существует, используется встроенная конфигурация по умолчанию. Она рендерит две секции:

  1. Секция URLs с элементом auto-urls (дефолт include: [app, tool]; без фильтрации)
  2. Секция Hosts с warning и элементом auto-hosts (дефолт include: [app, tool, infra])

Это позволяет проектам без info.yml сразу видеть осмысленный дашборд со связями всех сервисов, целиком построенный из определений сервисов в workspace/services/*/service.yml. Сервисы вносят детали через свои блоки info: (title, paths, ключи host/port). Редактировать info.yml для старта не требуется.

Пустой или полностью закомментированный workspace/info.yml — тот, из которого не декодируется ни один ключ верхнего уровня — трактуется точно как отсутствующий, поэтому встроенный дефолт остаётся активным. Именно на это опирается сгенерированный (целиком закомментированный) info.yml.

Чтобы кастомизировать дашборд, создайте workspace/info.yml со своими sections и items. Как только из файла декодируется любой ключ верхнего уровня, он считается авторским, и встроенный дефолт не используется: намеренный sections: [] рисует пустой дашборд, а не возвращает дефолт, а файл с одним лишь footer: true применяется как написан.

dwe validate различает эти три состояния в config.info — инертный файл (дефолт молча активен) и sections: [] с уровнем Info, авторский дашборд с реальным содержимым — с OK.

sections:
- id: dwe_info
items:
- type: subgroup
title: DWE
hide_on_empty: false
items:
- type: definition
name: Project
value: "{{ .Project.FullName }}"
- type: definition
name: State
value: "{{ .State }}"
when: "{{ .State }}"
- id: urls
title: URLs
items:
# Automatically render all app and tool services with their hosts/ports
- type: auto-urls
include: [app, tool]
hide: [varnish]
hide_paths:
main: ["SPX profiler"]
port_via: nginx
- id: credentials
title: Credentials
items:
- type: subgroup
title: Database
hide_on_empty: true
items:
- type: definition
name: User
value: "{{ .Project.Name }}_user"
- type: subgroup
title: API Key
hide_on_empty: true
items:
- type: warning
text: "Check .env for sensitive credentials"
- id: hosts
title: Hosts
items:
- type: warning
text: "Add these to your /etc/hosts:"
# Automatically render all service hostnames
- type: auto-hosts
include: [app, tool, infra]
footer: true
  • Голые значения when: без шаблонного синтаксисаwhen: .State невалидно; должно быть when: "{{ .State }}".
  • Отсутствие кавычек вокруг шаблонных выражений — YAML парсит {{ ... }} как flow-маппинг, если оно без кавычек. Всегда заключайте шаблонные строки в кавычки.
  • Синтаксис поиска сервиса — Go text/template требует index для доступа к map по строковому ключу: (index .Services "main") возвращает ServiceConfig. Дальше поля структуры идут в PascalCase (.Container, .Enabled), а порты / хосты используют методы-аксессоры Port / Host с именем порта/хоста в качестве аргумента: (index .Services "main").Port "http". Скобки вокруг index-выражения обязательны, чтобы метод вызывался на возвращённом ServiceConfig.
  • Использование конфигурационных ключей, не выставленных на верхнем уровне — как прямые шаблонные пути вроде .Project.Name доступны только поля, выставленные разрешённой конфигурацией проекта (см. таблицу выше). Пользовательские ключи, добавленные в defaults.yml, лежат под .Raw и достаются через index или точечные пути к Raw (например, index .Raw "myKey").
  • Порядок аргументов appURL — порядок такой: host, port, useHTTPS, затем опциональный path. Перестановка port и useHTTPS молча даёт неправильные URL. При линковке инструмента, маршрутизируемого через основной reverse-прокси, комбинируйте имя хоста инструмента с портом основного сервиса: appURL ((index .Services "adminer").Host "web") ((index .Services "main").Port "http") .Runtime.UseHTTPS.
  • hide_on_empty с декоративными элементами — по умолчанию content-элементы вроде definition, info и warning засчитываются для видимости секции, а separator — нет. Используйте флаг decorative, чтобы переопределить: задайте decorative: true на content-элементе, чтобы исключить его из расчёта видимости, или decorative: false на separator’е, чтобы он засчитывался как контент. Секция с hide_on_empty: true полностью скрыта, если ни один content-элемент (после when-фильтрации) не прошёл.
  • Рендеринг футера с hide_on_empty — при footer: true футер рендерится только если хотя бы одна секция произвела вывод. Если все секции скрыты через hide_on_empty, футер тоже подавляется.
  • dwe info — рендер полного дашборда
  • dwe (без аргументов) — показывает встроенную компактную сводку (не из info.yml)