ci: валидировать CR по схемам CRD — ловить невалидные значения полей (пример: driftDetection.mode) #56

Open
opened 2026-09-20 09:50:52 +00:00 by hermes · 0 comments
hermes commented 2026-09-20 09:50:52 +00:00 (Migrated from git.grachevko.ru)

Что произошло

В PR #55 уехало driftDetection.mode: Disabled — значение с заглавной буквы. У helm-controller enum строчный (проверено по исходнику, не по памяти):

  • api/v2/helmrelease_types.go: // +kubebuilder:validation:Enum=enabled;warn;disabled на поле Mode и DriftDetectionDisabled DriftDetectionMode = "disabled".
  • В кластере установлена helm-controller v1.6.4 (Flux v2.9.5, flux-system/helm-controller).

CRD отбрасывает такое значение на приёме: HelmRelease не создаётся, Kustomization падает — но CI этого не увидел: flate test all (73 passed) валидирует рендер и реконсиляцию, а значения полей CR по схемам CRD не проверяет. Ошибку поймал владелец вручную (коммит 164587e).

Что нужно

Добавить в CI валидацию манифестов по JSON-схемам CRD, чтобы невалидные enum/типы/обязательные поля ловились до мёржа.

Варианты:

  1. kubeconform по дереву репо + схемы datreeio/CRDs-catalog (рекомендую) — шаг рядом с текущим job'ом Flate:
    kubeconform -strict -ignore-missing-schemas \
      -schema-location default \
      -schema-location 'https://raw.githubusercontent.com/datreeio/CRDs-catalog/<COMMIT-SHA>/{{.Group}}/{{.ResourceKind}}_{{.ResourceAPIVersion}}.json' \
      kubernetes/
    
    Ловит enum/типы у Flux, Gateway API, CNPG, ESO и всего, что есть в каталоге. Каталог пинить по commit SHA, а не main — по нашему правилу сверяться с установленной версией, а main каталога плавает.
    Грабли: в манифестах есть плейсхолдеры Flux (${SECRET_DOMAIN}), а у hostnames/URL в схемах есть pattern — перед валидацией подставлять фиктивные значения (sed 's/${SECRET_DOMAIN}/example.com/g'), иначе будут ложные падения.
  2. Локальный снапшот схем под установленные версии (helm-controller v1.6.4, gateway-api, CNPG, ESO, Dragonfly, ToolHive) в репо + kubeconform офлайн: без сети и без плавающих ссылок, но снапшот надо обновлять руками при апгрейдах.
  3. Феча в flate (home-operations/flate): заставить flate test валидировать Flux-CR по CRD-схемам версии дистрибутива — тогда существующий прогон начнёт ловить и это; путь дольше, но без внешних зависимостей и плейсхолдеров.
  4. То же локально в .lefthook.toml (pre-push), чтобы не гонять CI ради опечатки.

Критерий готовности

  • В CI есть шаг валидации CR по схемам; PR с заведомо невалидным значением (driftDetection.mode: Disabled, pathType: PathPrefixX, опечатка в имени поля) падает.
  • Проверено на живом PR: статус красный, сообщение указывает файл и поле.

Связанное

  • PR #55 (Zitadel) — где ошибка и появилась; фикс значения — 164587e.
  • Найденная этим же разбором вторая грабля того же класса (значения по умолчанию, а не схема): у чарта Zitadel 10.0.6 replicaCount/resources/pdb — ключи верхнего уровня, вложенные в zitadel: молча игнорируются. Схемой не ловится, только рендером.
## Что произошло В PR #55 уехало `driftDetection.mode: Disabled` — значение с заглавной буквы. У helm-controller enum **строчный** (проверено по исходнику, не по памяти): - `api/v2/helmrelease_types.go`: `// +kubebuilder:validation:Enum=enabled;warn;disabled` на поле `Mode` и `DriftDetectionDisabled DriftDetectionMode = "disabled"`. - В кластере установлена helm-controller **v1.6.4** (Flux v2.9.5, `flux-system/helm-controller`). CRD отбрасывает такое значение на приёме: HelmRelease не создаётся, Kustomization падает — но **CI этого не увидел**: `flate test all` (73 passed) валидирует рендер и реконсиляцию, а значения полей CR по схемам CRD не проверяет. Ошибку поймал владелец вручную (коммит 164587e). ## Что нужно Добавить в CI валидацию манифестов по JSON-схемам CRD, чтобы невалидные enum/типы/обязательные поля ловились до мёржа. Варианты: 1. **kubeconform по дереву репо + схемы `datreeio/CRDs-catalog`** (рекомендую) — шаг рядом с текущим job'ом Flate: ``` kubeconform -strict -ignore-missing-schemas \ -schema-location default \ -schema-location 'https://raw.githubusercontent.com/datreeio/CRDs-catalog/<COMMIT-SHA>/{{.Group}}/{{.ResourceKind}}_{{.ResourceAPIVersion}}.json' \ kubernetes/ ``` Ловит enum/типы у Flux, Gateway API, CNPG, ESO и всего, что есть в каталоге. Каталог пинить по commit SHA, а не `main` — по нашему правилу сверяться с установленной версией, а `main` каталога плавает. Грабли: в манифестах есть плейсхолдеры Flux (`${SECRET_DOMAIN}`), а у hostnames/URL в схемах есть `pattern` — перед валидацией подставлять фиктивные значения (`sed 's/${SECRET_DOMAIN}/example.com/g'`), иначе будут ложные падения. 2. **Локальный снапшот схем** под установленные версии (helm-controller v1.6.4, gateway-api, CNPG, ESO, Dragonfly, ToolHive) в репо + kubeconform офлайн: без сети и без плавающих ссылок, но снапшот надо обновлять руками при апгрейдах. 3. **Феча в flate** (home-operations/flate): заставить `flate test` валидировать Flux-CR по CRD-схемам версии дистрибутива — тогда существующий прогон начнёт ловить и это; путь дольше, но без внешних зависимостей и плейсхолдеров. 4. То же локально в `.lefthook.toml` (pre-push), чтобы не гонять CI ради опечатки. ## Критерий готовности - В CI есть шаг валидации CR по схемам; PR с заведомо невалидным значением (`driftDetection.mode: Disabled`, `pathType: PathPrefixX`, опечатка в имени поля) падает. - Проверено на живом PR: статус красный, сообщение указывает файл и поле. ## Связанное - PR #55 (Zitadel) — где ошибка и появилась; фикс значения — 164587e. - Найденная этим же разбором вторая грабля того же класса (значения по умолчанию, а не схема): у чарта Zitadel 10.0.6 `replicaCount`/`resources`/`pdb` — ключи верхнего уровня, вложенные в `zitadel:` молча игнорируются. Схемой не ловится, только рендером.
Sign in to join this conversation.
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
grachevko/home-ops#56
No description provided.