fix(hindsight): tenant_users собирается шаблоном из api_key_<имя> #62

Merged
hermes merged 1 commit from refs/pull/62/head into main 2026-09-20 12:57:14 +00:00
hermes commented 2026-09-20 12:56:35 +00:00 (Migrated from git.grachevko.ru)

Зачем срочно

В Vault ключи людей разнесены на отдельные свойства api_key_<имя>, а свойство tenant_users удалено. ExternalSecret/hindsight всё ещё ссылался на него (remoteRef.property: tenant_users), поэтому на ближайшем обновлении (refreshInterval 1h) он ушёл бы в ошибку синхронизации и hindsight-secret перестал бы обновляться (текущее значение в Secret живёт до ошибки, поэтому API пока работает — окно до ~13:50 UTC).

Что в правке

HINDSIGHT_API_TENANT_USERS теперь собирается шаблоном ESO (engineVersion: v2) из свойств api_key_*:

{{- $pairs := list -}}
{{- range $name := (keys . | sortAlpha) -}}
  {{- if hasPrefix "api_key_" $name -}}
    {{- $pairs = append $pairs (printf "%s:%s" (trimPrefix "api_key_" $name) (index . $name)) -}}
  {{- end -}}
{{- end -}}
{{- join "," $pairs -}}

Две вещи, которые тут принципиальны:

  1. sortAlpha обязателен. Порядок обхода карты в Go случаен — без сортировки содержимое Secret менялось бы при каждом refresh (раз в час), и reloader перезапускал бы поды каждый час. Сортированные байты стабильны.
  2. mergePolicy по умолчанию Replace — в Secret попадает ровно вывод шаблона, поэтому остальные ключи (postgres-password, HINDSIGHT_API_LLM_API_KEY) перечислены в шаблоне явно.

Добавить человека теперь = добавить свойство api_key_<имя> в Vault и одну строку в data.

Проверено

  • flate test all — 77 passed, exit 0; в рендере видны api_key_grachevko и сам шаблон.
  • Файл в ветке побайтово равен локальному; diff против main — 1 файл, +42/−13.

Проверка после мёржа

  • kubectl -n ai get externalsecret hindsight → SecretSynced.
  • В секрете HINDSIGHT_API_TENANT_USERS — три пары вида имя:ключ (значения не печатаем: kubectl -n ai get secret hindsight-secret -o jsonpath='{.data.HINDSIGHT_API_TENANT_USERS}' | base64 -d | tr ',' '\n' | cut -d: -f1 → три имени).
  • Поды API не перекатываются лишний раз вне изменения содержимого.
## Зачем срочно В Vault ключи людей разнесены на отдельные свойства `api_key_<имя>`, а свойство `tenant_users` удалено. `ExternalSecret/hindsight` всё ещё ссылался на него (`remoteRef.property: tenant_users`), поэтому на ближайшем обновлении (refreshInterval 1h) он ушёл бы в ошибку синхронизации и `hindsight-secret` перестал бы обновляться (текущее значение в Secret живёт до ошибки, поэтому API пока работает — окно до ~13:50 UTC). ## Что в правке `HINDSIGHT_API_TENANT_USERS` теперь собирается шаблоном ESO (`engineVersion: v2`) из свойств `api_key_*`: ``` {{- $pairs := list -}} {{- range $name := (keys . | sortAlpha) -}} {{- if hasPrefix "api_key_" $name -}} {{- $pairs = append $pairs (printf "%s:%s" (trimPrefix "api_key_" $name) (index . $name)) -}} {{- end -}} {{- end -}} {{- join "," $pairs -}} ``` Две вещи, которые тут принципиальны: 1. **`sortAlpha` обязателен.** Порядок обхода карты в Go случаен — без сортировки содержимое Secret менялось бы при каждом refresh (раз в час), и `reloader` перезапускал бы поды каждый час. Сортированные байты стабильны. 2. **`mergePolicy` по умолчанию `Replace`** — в Secret попадает ровно вывод шаблона, поэтому остальные ключи (`postgres-password`, `HINDSIGHT_API_LLM_API_KEY`) перечислены в шаблоне явно. Добавить человека теперь = добавить свойство `api_key_<имя>` в Vault и одну строку в `data`. ## Проверено - `flate test all` — **77 passed**, exit 0; в рендере видны `api_key_grachevko` и сам шаблон. - Файл в ветке побайтово равен локальному; diff против main — 1 файл, +42/−13. ## Проверка после мёржа - `kubectl -n ai get externalsecret hindsight` → `SecretSynced`. - В секрете `HINDSIGHT_API_TENANT_USERS` — три пары вида `имя:ключ` (значения не печатаем: `kubectl -n ai get secret hindsight-secret -o jsonpath='{.data.HINDSIGHT_API_TENANT_USERS}' | base64 -d | tr ',' '\n' | cut -d: -f1` → три имени). - Поды API не перекатываются лишний раз вне изменения содержимого.
Sign in to join this conversation.
No reviewers
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!62
No description provided.