iac/apps/documentations/pdm.CONFIGURATION.md

242 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Конфигурация проекта pdm
Документ описывает все переменные окружения и способы конфигурирования сервиса **pdm** (Go). Сервис деплоится в namespace `documentations` как деплоймент `pdm` (образ `pdmv2`). Это шлюз/агрегатор поверх Postgres и множества внутренних сервисов Sarex (документации, ресурсы, ремарки, вложения, состояния, подписки, EAV, инспекции, релизы, BIM, трансмитталы и др.).
## Способы конфигурирования
Сервис настраивается **только через переменные окружения**. Разбор выполняется в `config/config.go` (функция `NewConfig`) через библиотеку [`cleanenv`](https://github.com/ilyakaznacheev/cleanenv) — вызовом `cleanenv.ReadEnv(cfg)`.
Особенности разбора:
- **Плоские имена переменных без общего префикса** — каждое поле помечено тегом `env:"..."` (напр. `POSTGRES_ADDRESS`, `RESOURCES_URL`). Вложенности/делимитера, как в pydantic-settings, здесь нет.
- **Обязательность** задаётся тегом `env-required:"true"` — при отсутствии такой переменной приложение не стартует (`config error`). В таблицах ниже дефолт `—` означает обязательное поле.
- **Значения по умолчанию** задаются тегом `env-default:"..."`.
- `cleanenv.ReadEnv` читает **только переменные окружения процесса** — конфиг-файла (yaml/toml) и авто-загрузки `.env` нет. Единственный файловый источник — JSON сервисного аккаунта S3 (`S3_SERVICE_ACCOUNT`).
Отдельно от env читается JSON-файл доступа к S3 — путь берётся из `S3_SERVICE_ACCOUNT`, разбор в `pkg/s3` (`NewFromConfigFile`). Формат файла (`.example.s3config.json`):
```json
{ "endpoint": "", "access_key_id": "", "secret_access_key": "", "use_ssl": true }
```
Источники переменных по способам запуска:
| Способ запуска | Откуда берутся переменные |
| --- | --- |
| Локально (бинарник) | Переменные окружения процесса. `make config` копирует `.example.env``.env` и `.example.s3config.json``.s3config.json` (только если файлов ещё нет), но приложение **не загружает `.env` автоматически**его нужно экспортировать самому. В репозитории для этого есть `.envrc` (`use flake` + `dotenv`) под direnv |
| Локально (live-reload) | `make run-dev``air` (`.air.toml`), пересборка `./cmd/httpserver/main.go` |
| Kubernetes (Helm) | `.helm/values.yaml`: блок `services.api.envs` (обычные значения, ключ `_default` и переопределения по окружениям `stage`/`preprod`/`production`) и `services.api.secretEnvs` (значения из k8s-секретов через `secretKeyRef`). Используется зонтичный `universal-chart` |
| CI/CD (GitLab) | `.gitlab-ci.yml`: переменные пайплайна в `workflow.rules` (по ветке/тегу), общие шаблоны из `generic/common-ci` |
Точки входа (`cmd/`):
| Команда | Точка входа | Назначение |
| --- | --- | --- |
| `make run` / `make build` | `cmd/httpserver/main.go` | HTTP API (Fiber). Читает конфиг и вызывает `internal/app/http.New(cfg).Run()` |
| — | `cmd/example/main.go`, `cmd/test/main.go` | Вспомогательные утилиты (не участвуют в деплое) |
Порядок инициализации в `internal/app/http/httpserver.go` (`App.Run`): трейсер (при `TRACER_USE=true`) → подключение к Postgres → инициализация HTTP-клиентов внешних сервисов → репозитории/usecase/сервисы → опциональный Valkey → сборка Fiber-приложения (`internal/controller/http/v1.Setup`) → `app.Listen(":8080")`.
## Переменные приложения
Все переменные читаются `config/config.go`. Дефолт `—` означает, что значение обязательно (`env-required:"true"`) и его отсутствие приводит к ошибке старта.
### App / Log
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `APP_NAME` | string | — | Имя приложения |
| `APP_VERSION` | string | — | Версия приложения |
| `LOG_LEVEL` | string | — | Уровень логирования (`pkg/logging`, напр. `DEBUG`/`INFO`) |
### Postgres (`POSTGRES`)
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `POSTGRES_ADDRESS` | string | — | Хост PostgreSQL |
| `POSTGRES_DB` | string | — | Имя базы данных |
| `POSTGRES_USER` | string | — | Пользователь БД |
| `POSTGRES_PASSWORD` | string | — | Пароль пользователя БД |
| `POSTGRES_PORT` | string | — | Порт PostgreSQL |
| `POSTGRES_POOL_SIZE` | int32 | — | Размер пула соединений (pgxpool) |
| `ENABLE_OBSERVABILITY` | bool | `false` | Инструментирование пула Postgres трейсингом (`otelpgx`) |
> DSN собирается в `Config.GetPostgresConnectionUrl()` как `postgres://user:password@address:port/db` — **без параметра `sslmode`**. Отдельный флаг `ENABLE_SSL` из Helm кодом не читается (см. «Замечания»).
### HTTP (`HTTP`)
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `HTTP_PORT` | string | — | Порт HTTP. **Обязателен по тегу, но фактически не используется** — сервер слушает `:8080` (хардкод в `httpserver.go`) |
| `PUBLIC_KEY` | string (PEM) | `""` | Публичный ключ (PKIX) для проверки JWT. Формально необязателен, но при пустом/некорректном значении приложение падает (`panic` в `v1.Setup`) |
| `HTTP_BODY_LIMIT` | int | `268435456` (256 MB) | Максимальный размер тела запроса, байт |
| `HTTP_READ_BUFFER_SIZE` | int | `98304` (96 KB) | Размер буфера чтения запроса, байт |
### Auth и хосты внешних сервисов
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `DJANGO_BASIC_AUTH` | string | — | Basic-токен для авторизации в бэкенде Sarex/Django (клиенты `targets`, `users`) |
| `DJANGO_HOST` | string | — | Базовый URL Django/бэкенда. Используется сразу двумя секциями — `USERS.UserHost` и `SA.SAHost` (accounts/companies/django-клиенты) |
| `NOTES_URL` | string | — | Сервис заметок (`notes`) |
| `FLOWS_URL` | string | — | Сервис процессов (`flows`) |
| `RESOURCES_URL` | string | — | Сервис ресурсов/IAM (`resources`) |
| `REMARKS_URL` | string | — | Сервис замечаний (`remarks`) |
| `ATTACHMENTS_URL` | string | — | Сервис вложений (`attachments`) |
| `STATES_URL` | string | — | Сервис состояний/рабочих областей (`workspaces`) |
| `SUBSCRIPTIONS_URL` | string | — | Сервис подписок (`subscriptions`) |
| `EAV_URL` | string | — | Сервис атрибутов EAV |
| `INSPECTIONS_URL` | string | — | Сервис инспекций |
| `SYSTEM_LOG_URL` | string | — | Сервис системного лога |
| `TARGET_URL` | string | — | Сервис таргетов |
| `DOCUMENTATION_URL` | string | — | Сервис документаций (documentation-api-v2) |
| `BIM_V2_HOST` | string | — | BIM core API v2 |
| `NOTES_URL` | string | — | (см. выше) |
| `DRAWINGS_INTERNAL_URL` | string | — | Внутренний URL сервиса чертежей |
| `RELEASES_URL` | string | — | URL GitLab для получения релизов |
| `RELEASES_TOKEN` | string | — | Токен доступа к GitLab (`RELEASES_URL`) |
### Ресурсы и фильтр разрешений (`RESOURCES`)
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `ENABLE_PERMISSIONS_FILTER` | bool | `false` | Включить фильтрацию по разрешениям на уровне сервиса документов |
| `PERMISSIONS_FILTER_COMPANIES` | string (JSON-массив) | `[133, 256, 247, 219, 248, 194, 242, 260, 252, 255, 239, 125, 116, 92, 311, 170]` | Список ID компаний, к которым применяется фильтр. Парсится `json.Unmarshal` в `[]uint64` |
### Thumbnails (`ATTACHMENTS`, `STATES`)
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `WIDTH_THUMB_ATTACHMENTS` | int | `100` | Ширина превью вложений |
| `HEIGHT_THUMB_ATTACHMENTS` | int | `100` | Высота превью вложений |
| `WIDTH_THUMB_STATES` | int | `100` | Ширина превью состояний |
| `HEIGHT_THUMB_STATES` | int | `100` | Высота превью состояний |
### Subscriptions / System log — доп. поля
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `USE_SUBSCRIPTIONS` | bool | `true` | Включить интеграцию с подписками в сервисе документов |
| `API_HOST_PREFIX` | string | `""` | Префикс хоста API (напр. `/gateway`), используется сервисом системного лога |
### S3 (`S3`)
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `S3_SERVICE_ACCOUNT` | string | — | Путь к JSON-файлу с доступом к S3 (`endpoint`, `access_key_id`, `secret_access_key`, `use_ssl`). Разбирается в `pkg/s3` |
### Transmittals (`Transmittals`)
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `TRANSMITTALS_ENABLE` | bool | `true` | Включить клиент трансмитталов; при `false` используется stub-реализация |
| `TRANSMITTALS_BASE_URL` | string | — | Базовый URL сервиса трансмитталов. Обязателен даже при `TRANSMITTALS_ENABLE=false` |
### Observability / Tracer
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `OBSERVABILITY_COLLECTOR_ENDPOINT` | string | `""` | Эндпоинт OTLP-коллектора (метрики/наблюдаемость) |
| `TRACER_USE` | bool | `false` | Включить трейсинг OpenTelemetry (`golang-fiber-otel-tools`) |
| `TRACER_HOST` | string | `localhost:4317` | Адрес OTLP-коллектора трейсов |
| `TRACER_USE_INSECURE` | bool | `true` | Небезопасное (без TLS) подключение к коллектору |
| `SERVICE_NAME` | string | `Pdm` | Имя сервиса в трейсах |
| `TRACER_LOGGER_NAME` | string | `tracer_logger` | Имя логгера OTel |
### Valkey (`VALKEY`) — кэш пользователей
Подключение опционально: если `VALKEY_ADDR` пуст — клиент не создаётся (кэш пользователей отключён). Ошибки подключения/пинга не фатальны (лог `Warn`).
| Переменная | Тип | Значение по умолчанию | Назначение |
| --- | --- | --- | --- |
| `VALKEY_ADDR` | string | `""` | Адрес Valkey (при пустом — кэш выключен) |
| `VALKEY_LOGIN` | string | `""` | Логин |
| `VALKEY_HOST` | string | `""` | Хост |
| `VALKEY_PASSWORD` | string | `""` | Пароль |
| `VALKEY_DB` | int | `0` | Номер БД |
| `VALKEY_SSL` | bool | `false` | Использовать TLS |
| `VALKEY_SSL_CA_CERTS` | string | `""` | Путь к CA-сертификату для TLS |
## Переменные инфраструктуры и сборки
Не читаются кодом приложения (`config/config.go`), но участвуют в сборке/деплое:
| Переменная | Где используется | Назначение |
| --- | --- | --- |
| `GITLAB_CREDENTIALS` | `Dockerfile` (build-arg), `.gitlab-ci.yml` (`BUILD_ARGS`) | Учётные данные для доступа к приватным Go-модулям `gitlab.sarex.io` при сборке |
| `SERVICE_NAME` (CI) | `.gitlab-ci.yml` | `pdmv2` — имя сервиса в пайплайне (не путать с `SERVICE_NAME` трейсера) |
| `DOCKERFILE_PATH`, `CI_TRIGGER_SOURCE` | `.gitlab-ci.yml` | Путь к Dockerfile, источник триггера |
| `ENABLE_LINTER`, `ENABLE_BUILD_CHART`, `ENABLE_BUILD_IMAGE`, `ENABLE_STATE_UPDATE`, `ENABLE_DEPLOY` | `.gitlab-ci.yml` | Флаги стадий пайплайна |
| `STAND`, `NAMESPACE`, `RELEASE_NAME`, `CHART_NAME`, `CHART_VERSION`, `K8S_HUSTLER_BRANCH`, `HELM_SET_ARGS`, `IMAGE_NAME` | `.gitlab-ci.yml` | Параметры окружения/деплоя Helm |
## Переменные из Helm-чарта (`.helm/values.yaml`)
Обычные значения задаются в `services.api.envs` (ключ `_default` + переопределения по `stage`/`preprod`/`production`) и содержат переменные приложения, описанные выше, различаясь адресами БД/сервисов, `LOG_LEVEL`, доменами и т.п.
Значения из секретов (`services.api.secretEnvs`, монтируются как env через `secretKeyRef`):
| Переменная | Секрет (`secretName`, prod/по умолчанию) | Ключ (`secretKey`) |
| --- | --- | --- |
| `POSTGRES_DB` | `documentations-postgresql-secret` (preprod: `ya-pg-secret`) | `database` |
| `POSTGRES_PORT` | `documentations-postgresql-secret` | `port` |
| `POSTGRES_ADDRESS` | `documentations-postgresql-secret` | `host` |
| `POSTGRES_USER` | `documentations-postgresql-secret` | `username` |
| `POSTGRES_PASSWORD` | `documentations-postgresql-secret` | `password` |
| `YC-PG-CERTIFICATE` | `documentations-postgresql-secret` (preprod: `yc-pg-certificate`) | `ca.crt` |
| `DJANGO_BASIC_AUTH` | `django-auth` | `key` |
| `PUBLIC_KEY` | `public-key` | `key` |
| `RELEASES_TOKEN` | `releases-token` | `key` |
| `VALKEY_ADDR` | `valkey-secret` | `url` |
| `VALKEY_LOGIN` | `valkey-secret` | `login` |
| `VALKEY_PASSWORD` | `valkey-secret` | `password` |
| `VALKEY_HOST` | `valkey-secret` | `host` |
| `VALKEY_PORT` | `valkey-secret` | `port` |
| `VALKEY_CA_CERTS` | `valkey-secret` | `cert` |
Помимо env, чарт монтирует секрет `documentations-yc-s3` как том в `/etc/sarex/yc-s3-storage` (readOnly). Именно на файл `/etc/sarex/yc-s3-storage/yc-s3-service-account.json` указывает `S3_SERVICE_ACCOUNT` в prod-конфигурации.
Прочие значения чарта (не переменные приложения): `deployment.*` (имя `pdm-api`, реплики `stage=3`/`preprod=2`/`production=8`, ресурсы `cpu=1`, `memory=2Gi`), `image.name` (`cr.yandex/.../pdm_v2`), `service.*` (порт `8080`), `imagePullSecrets` (`dockerhub`), `probes.*` (startup/liveness/readiness по `/internal/healthz/*` на порту `8080`).
## Переменные в CI (`.gitlab-ci.yml`)
Пайплайн подключает общие шаблоны из `generic/common-ci` (`common-security-scan.yaml`, `universal-pipeline.yaml` ref `apps-business`) и переключает окружение по ветке/тегу через `workflow.rules`:
| Условие | STAND | Namespace | `universal-chart.global.env` |
| --- | --- | --- | --- |
| ветка `stage` | `stage` | `documentations` | `stage` |
| ветка `master` | `preprod` | `documentations-preprod` | `preprod` |
| тег (`CI_COMMIT_TAG`) | `prod` | `documentations-prod` | `production` |
| merge request | — | — | сборка образа отключена (`ENABLE_BUILD_IMAGE=false`) |
Общие переменные: `SERVICE_NAME=pdmv2`, `RELEASE_NAME=pdmv2`, `CHART_NAME=pdmv2`, `CHART_VERSION=0.0.1-<env>`, `DOCKERFILE_PATH=Dockerfile`.
## Замечания и потенциальные проблемы
- **`HTTP_PORT` фактически игнорируется.** Поле обязательно (`env-required`), но сервер жёстко слушает `:8080` (`app.Listen(":8080")` в `httpserver.go`). Реальный порт задаётся только этим хардкодом; в Helm `HTTP_PORT` и `service.port` совпадают со `8080`, поэтому расхождение незаметно.
- **`PUBLIC_KEY` де-факто обязателен.** По тегам он необязателен (`env:"PUBLIC_KEY"`), но `v1.Setup` при пустом/битом PEM вызывает `panic` (`failed to parse PEM block...`). Для локального запуска нужен валидный публичный ключ.
- **SSL к Postgres в коде не настраивается.** DSN формируется без `sslmode` (`GetPostgresConnectionUrl`). Helm-переменные `ENABLE_SSL` и секрет `YC-PG-CERTIFICATE` кодом **не читаются** — подключение к БД идёт без TLS-параметров на уровне DSN.
- **Множество Helm-переменных не читается приложением.** В `services.api.envs`/`secretEnvs` присутствуют переменные, отсутствующие в `config/config.go`, — вероятно, унаследованы от `documentation-api`: `API_ADDRESS`, `API_ADDRESS_FILE`, `ENABLE_SSL`, `ENABLE_S3`, `FILE_URL_EXTERNAL`, `WORKFLOW_URL`, `WORKSPACE_URL`, `BIM_API_URL`, `BIM_API_V2_URL`, `BIM_API_URL_EXTERNAL`, `WORKSPACE_BUNDLE_VERSION`, `WORKFLOW_IMAGES_VERSION`/`WORKFLOWS_IMAGES_VERSION`, `NAMESPACE`, `DJANGO_ORIGINATOR`, `USE_EXPERIMENTAL`, `READ_WRITE_TIMEOUT_FILE_STREAM`, `CACHE_DEFAULT_EXPIRATION`, `CACHE_CLEANUP_INTERVAL`, `USE_CACHE_IN_FILE_STREAMER`, `SENTRY_DSN`, `SENTRY_DEBUG`, `ENVIRONMENT`, `YC-PG-CERTIFICATE`. Они не влияют на работу pdm.
- **Несовпадение имён Valkey.** Код ждёт `VALKEY_SSL_CA_CERTS` (`config.go`), а Helm-секрет прокидывает `VALKEY_CA_CERTS`; также Helm задаёт `VALKEY_PORT`, который код не читает (адрес берётся целиком из `VALKEY_ADDR`). В результате CA-сертификат и порт из секрета до приложения не доходят.
- **Секции `USERS`/`SA` используют один и тот же env `DJANGO_HOST`.** Оба поля (`UserHost`, `SAHost`) читают одну переменную.
- **`config.env` в репозитории содержит реальные учётные данные** (пароль Postgres, `DJANGO_BASIC_AUTH`, токены) — это конфигурация для отладки, не шаблон. Для примеров использовать `.example.env`; `config.env` не должен попадать в окружения и подлежит ротации секретов.
- **`ENABLE_SQL_QUERY` из `config.env` кодом не читается** — в `config/config.go` такого поля нет.
- **`cleanenv.ReadEnv` не загружает `.env` автоматически.** `make config` лишь создаёт файлы-шаблоны (`.env`, `.s3config.json`) при их отсутствии; переменные нужно экспортировать вручную (например, через `direnv`/`.envrc`).
- **v0-роутер (echo) не подключён.** В `cmd/httpserver/main.go` используется только `internal/controller/http/v1.Setup` (Fiber). Пакет `internal/controller/http/v0` (на `labstack/echo`) в рантайме не задействован.
## Минимальный набор для локального запуска
Приложение поднимается через `make run` (или `make run-dev` с `air`). Минимально необходимо задать (обязательные поля `config/config.go`):
- `APP_NAME`, `APP_VERSION`, `LOG_LEVEL`;
- `POSTGRES_ADDRESS`, `POSTGRES_DB`, `POSTGRES_USER`, `POSTGRES_PASSWORD`, `POSTGRES_PORT`, `POSTGRES_POOL_SIZE`;
- `HTTP_PORT` (любой — фактически используется `:8080`), а также **валидный** `PUBLIC_KEY` (иначе `panic`);
- `DJANGO_BASIC_AUTH`, `DJANGO_HOST`;
- хосты внешних сервисов: `NOTES_URL`, `FLOWS_URL`, `RESOURCES_URL`, `REMARKS_URL`, `ATTACHMENTS_URL`, `STATES_URL`, `SUBSCRIPTIONS_URL`, `EAV_URL`, `INSPECTIONS_URL`, `SYSTEM_LOG_URL`, `TARGET_URL`, `DOCUMENTATION_URL`, `BIM_V2_HOST`, `DRAWINGS_INTERNAL_URL`;
- `RELEASES_URL`, `RELEASES_TOKEN`;
- `S3_SERVICE_ACCOUNT` (путь к `.s3config.json`) и заполненный сам JSON-файл;
- `TRANSMITTALS_BASE_URL` (обязателен даже при выключенных трансмитталах).
Необязательные (есть дефолты): `ENABLE_OBSERVABILITY`, `HTTP_BODY_LIMIT`, `HTTP_READ_BUFFER_SIZE`, `ENABLE_PERMISSIONS_FILTER`, `PERMISSIONS_FILTER_COMPANIES`, `USE_SUBSCRIPTIONS`, `WIDTH_THUMB_*`/`HEIGHT_THUMB_*`, `API_HOST_PREFIX`, `TRANSMITTALS_ENABLE`, `TRACER_*`, `SERVICE_NAME`, `VALKEY_*`, `OBSERVABILITY_COLLECTOR_ENDPOINT`.
Готовые значения-примеры приведены в `pdm.env.example` (на основе `.example.env` репозитория).