Пакет шаблона — это директория с файлами будущего репозитория микросервиса, манифестом и схемой параметров. Портал отрисовывает файлы пакета Go-шаблонизатором с параметрами, которые пользователь заполняет при создании микросервиса. Пакет публикуется в хранилище образов контейнеров утилитой ddp-template.

Структура пакета

Пакет содержит три служебных файла и файлы репозитория:

  • template.yaml — манифест: идентификатор, название, язык и правила обновления;
  • values.yaml — схема параметров шаблона;
  • .templateignore — пути, которые копируются в репозиторий без шаблонизации;
  • остальные файлы и директории — содержимое репозитория микросервиса.

Пример структуры пакета Go-сервиса:

go-service/
  template.yaml
  values.yaml
  .templateignore
  .gitlab-ci.yml
  cmd/{{ .slug }}/main.go
  go.mod
  deploy/helm/Chart.yaml

Файлы template.yaml, values.yaml и .templateignore в репозиторий микросервиса не копируются. Директория .git в пакет не включается.

Не размещайте в пакете директорию .ddp/: портал создаёт в ней lock-файл .ddp/template.lock.yaml при создании и обновлении репозитория.

Манифест template.yaml

Манифест описывает шаблон и правила его обновления. Пример манифеста:

id: go-service
name: Go service
description: Go HTTP service with CI and Helm chart
language: Go
tags:
  - http
  - helm
minDdpVersion: "1.7.0"
update:
  strategy: selective_additive
  overwrite:
    - .gitlab-ci.yml
    - deploy/**
    - go.mod
  addIfMissing:
    - .dockerignore
    - .editorconfig

Поля манифеста:

ПолеОбязательноеОписание
idДаИдентификатор шаблона: строчные латинские буквы, цифры и дефис. Совпадает с именем репозитория в хранилище образов
nameДаНазвание шаблона в галерее
descriptionНетОписание шаблона в галерее
languageДаЯзык шаблона: Go, Vue, TypeScript, Python, Java или Other
tagsНетТеги для поиска в галерее
minDdpVersionНетМинимальная версия DDP в формате semver. На более ранней версии DDP версия шаблона получает статус «недоступна»
updateДаПравила обновления репозитория до новой версии шаблона: поля strategy, overwrite и addIfMissing
update.strategyНетСтратегия обновления: selective, additive, selective_additive, full или merge. Если не задана, используется selective, и тогда update.overwrite обязателен. Для стратегии full списки путей не нужны: update: {strategy: full}
update.overwriteЗависит от стратегииGlob-шаблоны путей, которые перезаписываются при обновлении
update.addIfMissingЗависит от стратегииGlob-шаблоны путей, которые добавляются при обновлении, если их нет в репозитории

Другие поля в манифесте не допускаются. Стратегии и требования к спискам путей описаны в разделе «Стратегии обновления».

Параметры values.yaml

Файл values.yaml — схема параметров шаблона в формате OpenAPI Schema Object. По схеме портал строит форму шага «Параметры» мастера создания микросервиса.

Пример схемы параметров:

type: object
required:
  - slug
  - name
  - port
properties:
  slug:
    type: string
    title: Service slug
    description: Identifier used in paths and module name
    x-ddp-from: context.microservice.slug
  name:
    type: string
    title: Display name
    x-ddp-from: context.microservice.name
  port:
    type: integer
    title: HTTP port
    default: 8080
  database:
    type: string
    title: Database
    enum:
      - postgres
      - none
    default: none
  metrics:
    type: boolean
    title: Expose Prometheus metrics
    default: true

Портал использует свойства верхнего уровня properties для построения формы:

  • title — подпись поля, при отсутствии — ключ параметра;
  • description — подсказка поля;
  • required — обязательность поля в форме;
  • default — начальное значение. Если значение по умолчанию не задано, используется пустое значение типа: пустая строка, 0, false, пустой список или объект.

Тип поля формы определяется типом параметра:

Тип параметраПоле формы
string с enumВыпадающий список
stringТекстовое поле
booleanПереключатель
integerЧисловое поле с шагом 1
numberЧисловое поле с шагом 0,1
object, array, схемы с oneOf, anyOf, allOf, $refПоле для ввода JSON

Перед отрисовкой пакета портал проверяет итоговые значения по схеме. При несоответствии создание завершается ошибкой values_invalid: values do not match values.yaml schema: ....

При отрисовке пакета незаданные параметры получают пустые значения типа, поэтому required не гарантирует непустое значение. Чтобы запретить пустую строку, используйте ограничения схемы, например minLength: 1.

Схема задаётся объектом. Список параметров в values.yaml не поддерживается.

Связь параметров с контекстом запуска

Аннотация x-ddp-from заполняет параметр из контекста запуска процесса создания микросервиса. Такой параметр не отображается в форме мастера: пользователь не вводит повторно данные, которые уже указал на шаге «Сервис».

Значение аннотации — путь в контексте запуска, начинающийся с context.:

ПутьЗначение
context.microservice.slugИдентификатор микросервиса
context.microservice.nameНазвание микросервиса
context.system.slugИдентификатор системы, в которую входит микросервис
context.system.nameНазвание системы
context.repository.default_branchВетка по умолчанию
context.repository.descriptionОписание репозитория
context.template.versionВерсия шаблона

Полный состав контекста создания описан в разделе «Процессы главной».

Правила применения аннотации:

  • значение из контекста заменяет значение, переданное в параметрах процесса;
  • если пути нет в контексте или значение по пути null, создание завершается ошибкой values_invalid: values.yaml property "k": x-ddp-from "context.x": path not found in launch context;
  • если аннотация пустая, создание завершается ошибкой values_invalid: values.yaml property "k": x-ddp-from is empty;
  • аннотация применяется только при создании репозитория. При обновлении используются значения из lock-файла.

Шаблонизация файлов

Файлы пакета отрисовываются шаблонизатором Go text/template. Параметры шаблона доступны в корне: {{ .slug }}, {{ .port }}.

Пример файла пакета:

package main

// {{ .name }} listens on port {{ .port }}.
const port = {{ .port }}
{{- if .metrics }}

const metricsPath = "/metrics"
{{- end }}

Правила шаблонизации:

  • обращение к отсутствующему параметру завершает отрисовку ошибкой;
  • в шаблонах доступны функции шаблонизации портала и функции библиотеки Sprig, кроме env, expandenv и getHostByName;
  • шаблонизируются имена файлов и директорий, например cmd/{{ .slug }}/main.go. Путь, который после отрисовки выходит за пределы репозитория, завершает отрисовку ошибкой;
  • файл, который после отрисовки пуст или содержит только пробельные символы, в репозиторий не записывается. Так в пакете задаются необязательные файлы.

Файлы без шаблонизации

Файл .templateignore перечисляет пути, которые копируются в репозиторий как есть, без шаблонизации. Используйте его для файлов с собственным синтаксисом {{ }}, например шаблонов Helm.

Пример .templateignore:

# Helm templates use their own {{ .Values }} syntax.
deploy/helm/templates/**

Каждая строка — glob-шаблон пути относительно корня пакета, поддерживается синтаксис **. Строки, начинающиеся с #, — комментарии. Шаблоны путей в .templateignore сами могут содержать выражения {{ }}.

Версии

Версия пакета — тег артефакта в хранилище образов в формате strict semver без префикса v, например 1.2.0 или 2.0.0-rc.1.

Правила версионирования:

  • опубликованную версию перезаписать нельзя: для исправления опубликуйте новую версию;
  • увеличивайте major-версию при несовместимых изменениях структуры репозитория;
  • предварительные версии, например 2.0.0-rc.1, не устанавливаются автоматическим обновлением и видны в карточке микросервиса только пользователям с разрешением read:template-registries.

Перед публикацией версии с несовместимыми изменениями проверьте:

  • файлы, переименованные или перемещённые в новой версии, остаются в старых путях репозиториев микросервисов: обновление не удаляет файлы. Опишите ручную очистку в описании версии;
  • новые обязательные файлы добавлены в update.overwrite или в update.addIfMissing, если у пользователей уже могут быть свои копии этих файлов;
  • update.overwrite содержит только файлы, которыми владеет платформа, например CI и манифесты развёртывания. Файлы, которые редактируют разработчики, перенесите в update.addIfMissing или оставьте вне списков.

Утилита ddp-template

Утилита ddp-template проверяет, собирает, публикует и локально отрисовывает пакеты шаблонов.

Команды утилиты:

КомандаНазначение
ddp-template lint <path>Проверка template.yaml, values.yaml, .templateignore, списков путей обновления и пробная отрисовка пакета
ddp-template pack <path>Сборка архива пакета без директории .git
ddp-template publish <path> --version <VERSION>Проверка, сборка и публикация пакета в хранилище образов. Выводит JSON с полями templateId, version, ociRef, sha256
ddp-template pull <TEMPLATE_ID> --version <VERSION>Загрузка и распаковка опубликованного пакета
ddp-template render <path>Локальная отрисовка пакета, в том числе с имитацией стратегии обновления

Коды завершения ddp-template lint: 0 — ошибок нет, 1 — есть ошибки, 2 — есть предупреждения. Флаг --strict превращает предупреждения в ошибки, флаг --render-smoke выполняет только отрисовку со значениями по умолчанию.

Подключение к хранилищу

Параметры подключения к хранилищу задаются флагами, переменными окружения или файлом конфигурации. Флаги имеют приоритет над переменными окружения, переменные окружения — над профилем из файла конфигурации.

ПараметрФлагПеременная окружения
Файл конфигурации--configDDP_TEMPLATE_CONFIG
Профиль--profileDDP_TEMPLATE_PROFILE
Хост хранилища--registryDDP_TEMPLATE_REGISTRY
Префикс репозиториев--repository-prefixDDP_TEMPLATE_REPOSITORY_PREFIX
Имя пользователя--registry-userDDP_TEMPLATE_REGISTRY_USER
Пароль или токен--registry-tokenDDP_TEMPLATE_REGISTRY_TOKEN

Если имя пользователя не задано, пароль используется как Bearer-токен.

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

default: company
registries:
  company:
    registry: registry.example.com
    repositoryPrefix: ddp-templates
    auth:
      username: <REGISTRY_USER>
      password: <REGISTRY_TOKEN>

Где:

  • <REGISTRY_USER> — имя пользователя хранилища;
  • <REGISTRY_TOKEN> — пароль или токен хранилища.

Если задан параметр default или профиль один, он используется, когда профиль не указан.

Публикация из CI

Версии публикуются из CI по Git-тегу. Пример задачи GitLab CI, которая публикует шаблон go-service по тегу go-service/vX.Y.Z:

publish-go-service:
  rules:
    - if: $CI_COMMIT_TAG =~ /^go-service\/v\d+\.\d+\.\d+$/
  script:
    - VERSION="${CI_COMMIT_TAG#go-service/v}"
    - ddp-template publish ./template-packs/go-service
        --version "$VERSION"
        --registry "$REGISTRY"
        --repository-prefix ddp-templates

После публикации версия появляется в портале при следующей синхронизации реестра шаблонов или после нажатия «Синхронизировать» на вкладке «Запуски синхронизации». Если в подключении заполнено поле «Идентификаторы репозиториев», добавьте в него идентификатор нового шаблона.

Локальная проверка обновления

Утилита отрисовывает новую версию пакета со значениями существующего микросервиса без обращения к GitLab. Так проверяется, какие файлы изменит обновление.

Команды загружают опубликованную версию и отрисовывают её с имитацией стратегии обновления:

ddp-template pull go-service --version 1.1.0 \
  --registry registry.example.com \
  --repository-prefix ddp-templates \
  --output ./packs/go-service-1.1.0
ddp-template render ./packs/go-service-1.1.0 \
  --values ./values.yaml \
  --use-overwrite \
  --output ./render-out

Где ./values.yaml — файл со значениями параметров из раздела values lock-файла микросервиса.

Команда ddp-template render не применяет аннотации x-ddp-from: передайте значения таких параметров в файле --values.