diff --git a/doc/errors/log.md b/doc/errors/log.md index 33dcac4..a73acb3 100644 --- a/doc/errors/log.md +++ b/doc/errors/log.md @@ -4,6 +4,85 @@ --- +## 2026-03-20 — Баг: неверный hostname в api_endpoint провайдера nubes + +### Симптом +`terraform apply` на `examples/POSTGRES` падал с HTTP 404 на обоих ресурсах: `nubes_postgres.npg` и `nubes_s3bucket.baba_bucket`. + +### Причина +В `examples/POSTGRES/main.tf` был указан UI-домен вместо API-домена: +```hcl +# НЕПРАВИЛЬНО (UI облака, не API): +api_endpoint = "https://deck-test.ngcloud.ru/api/v1" + +# ПРАВИЛЬНО (API Dashboard): +api_endpoint = "https://deck-api-test.ngcloud.ru/api/v1/index.cfm" +``` +Аналогично для `nubes_endpoint` в провайдере `sless`. + +### Фикс +`deck-test` → `deck-api-test` в обоих провайдерах, добавлен `/index.cfm`. +Найдено через `git show cca3a8c:examples/POSTGRES/main.tf`. + +### Правило +> `deck-api-test.ngcloud.ru` — API (для Terraform) +> `deck-test.ngcloud.ru` — UI облака (только браузер) + +--- + +## 2026-03-20 — Баг платформы: nubes_postgres_user/database зависают при destroy + +### Симптом +`terraform destroy` завершается, но в UI облака операция `delete_user` возвращает: +> "Не удалось удалить пользователя из CRD. Производится откат" + +После этого повторный `terraform apply` падает с: +> "Нарушена консистентность: Операция вернула duplicate/exist, но объект не найден в state_out" + +### Причина +Платформенный баг: delete_user не удаляет CRD в кластере Kubernetes PG-оператора. +База `db0` остаётся "мёртвой" — API не видит, но в кластере CRD есть. +`adopt_existing_on_create = true` не помогает — провайдер получает `duplicate` но не может прочитать объект обратно. + +### Решение (workaround) +Удалить PG-инстанс вручную через UI облака → почистить state → пересоздать через `terraform apply`. + +```bash +cd ~/terra/sless/examples/POSTGRES +terraform state rm nubes_postgres_database.db +terraform state rm nubes_postgres_user.pg_user +terraform state rm nubes_postgres.npg +terraform apply -auto-approve +``` + +### Статус +Зафиксировано как баг платформы. Передано девопсам для исправления в CRD-операторе PG. + +--- + +## 2026-03-20 — Invalid index: vault_secrets["users"] на первом apply + +### Симптом +``` +Error: Invalid index + on postgres.tf line 7, in locals: + 7: pg_creds_map = jsondecode(nubes_postgres.npg.vault_secrets["users"]) +The given key does not identify an element in this collection value. +``` + +### Причина +`vault_secrets["users"]` появляется только **после** создания первого пользователя. +На первом `plan/apply` ключ ещё не существует. + +### Фикс +```hcl +pg_creds_map = try(jsondecode(lookup(nubes_postgres.npg.vault_secrets, "users", "{}")), {}) +pg_password = try(local.pg_creds_map[local.pg_username]["password"], "") +``` +Пароль подтягивается при следующем `apply` после создания пользователя. + +--- + ## 2026-03-17 — Баг 3: PodLogOptions compile error (v0.1.31) **Проблема:** Оператор не компилировался. Ошибка: diff --git a/doc/infrastructure/overview.md b/doc/infrastructure/overview.md index 67755a9..fe9afce 100644 --- a/doc/infrastructure/overview.md +++ b/doc/infrastructure/overview.md @@ -51,6 +51,15 @@ | `naeel/sless-runtime-python3.11:latest` | Base runtime для python3.11 функций | | `naeel/sless-default-hello:latest` | Пример собранной функции (kaniko) | +## Nubes Cloud endpoints + +> **Не путать** — оба домена похожи, но разные назначения: + +| URL | Назначение | +|-----|------------| +| `https://deck-api-test.ngcloud.ru/api/v1/index.cfm` | **API Dashboard** — используется в Terraform-провайдерах (`nubes`, `sless → nubes_endpoint`). Без `/index.cfm` — 404. | +| `https://deck-test.ngcloud.ru/` | **UI облака** — только браузер, в Terraform не использовать | + ## Мониторинг - Victoria Metrics — в кластере diff --git a/doc/progress.md b/doc/progress.md index e703439..eba2a35 100644 --- a/doc/progress.md +++ b/doc/progress.md @@ -1,9 +1,36 @@ # Прогресс разработки -Последнее обновление: 2026-03-20 17:00 +Последнее обновление: 2026-03-20 21:30 --- +## 2026-03-20 — Восстановление PostgreSQL и отладка провайдера nubes + +### Что произошло +1. Старый PG-инстанс (`teststand-pg-2`) был удалён. Девопсы позднее вернули PG под именем `pg-sless-demo`. +2. Обнаружен неверный `api_endpoint` в провайдере nubes: `deck-test` вместо `deck-api-test` → 404 на всех ресурсах. +3. Исправлен `nubes_endpoint` в провайдере `sless` — та же проблема. +4. Обнаружен баг платформы: `delete_user` не удаляет CRD → база/пользователь зависают в кластере → повторный `apply` падает с "нарушена консистентность". +5. Workaround: ручное удаление PG через UI + `terraform state rm` + пересоздание. + +### Изменения в файлах +| Файл | Что изменено | +|------|-------------| +| `examples/POSTGRES/main.tf` | Исправлен `api_endpoint` и `nubes_endpoint` → `deck-api-test.ngcloud.ru` в обоих провайдерах | +| `examples/POSTGRES/postgres.tf` | `try()`-обёртка для `vault_secrets["users"]`; `resource_name = "pg-sless-demo"` | +| `examples/POSTGRES/stress_destroy_apply.sh` | Новый скрипт: 5 итераций destroy+apply с логами и остановкой при ошибке | +| `doc/infrastructure/overview.md` | Добавлена таблица Nubes endpoints (API vs UI) | +| `doc/errors/log.md` | Задокументированы 3 новые ошибки | + +### Статус +- ✅ Провайдер nubes работает с правильным endpoint +- ✅ PG пересоздан и managed через terraform +- ⏳ Стресс-тест (stress_destroy_apply.sh) — в процессе, выявлен баг платформы +- 📋 TODO: убрать `sless_function`, встроить в `sless_job` + +--- + + ## 2026-03-20 — Архитектурный рефакторинг: sless_function + sless_service (ветка feat/function-service-split) ### Цель diff --git a/examples/POSTGRES/main.tf b/examples/POSTGRES/main.tf index 08ab574..fcdc110 100644 --- a/examples/POSTGRES/main.tf +++ b/examples/POSTGRES/main.tf @@ -45,14 +45,18 @@ variable "pg_password" { description = "Только для сверки. Реальный пароль из vault_secrets. Должен совпадать с tfvars." } +# Nubes endpoints — не путать: +# API Dashboard (для Terraform-провайдеров): https://deck-api-test.ngcloud.ru/api/v1/index.cfm +# UI облака (только браузер, не для кода): https://deck-test.ngcloud.ru/ +# ВАЖНО: nubes и sless провайдеры требуют API endpoint, НЕ UI! provider "nubes" { api_token = var.api_token - api_endpoint = "https://deck-test.ngcloud.ru/api/v1/index.cfm" + api_endpoint = "https://deck-api-test.ngcloud.ru/api/v1/index.cfm" } provider "sless" { endpoint = "https://sless.kube5s.ru" token = var.api_token - nubes_endpoint = "https://deck-test.ngcloud.ru/api/v1" + nubes_endpoint = "https://deck-api-test.ngcloud.ru/api/v1" } diff --git a/examples/POSTGRES/postgres.tf b/examples/POSTGRES/postgres.tf index 64bec6c..0315443 100644 --- a/examples/POSTGRES/postgres.tf +++ b/examples/POSTGRES/postgres.tf @@ -2,16 +2,20 @@ # Актуальные credentials из vault_secrets (authoritatively) — vault синхронизирован с кластером. # Структура vault_secrets["users"]: JSON-строка {"username": {"password": "...", "username": "..."}} + locals { - pg_creds_map = jsondecode(nubes_postgres.npg.vault_secrets["users"]) + # try() нужен: vault_secrets["users"] появляется только ПОСЛЕ создания первого пользователя. + # На первом apply ключа ещё нет → пустая map. Пароль подтянется при следующем apply. + pg_creds_map = try(jsondecode(lookup(nubes_postgres.npg.vault_secrets, "users", "{}")), {}) pg_username = nubes_postgres_user.pg_user.username - pg_password = local.pg_creds_map[local.pg_username]["password"] + pg_password = try(local.pg_creds_map[local.pg_username]["password"], "") pg_host = nubes_postgres.npg.state_out_flat["internalConnect.master"] pg_database = nubes_postgres_database.db.db_name } + resource "nubes_postgres" "npg" { - resource_name = "teststand-pg-2" + resource_name = "pg-sless-demo" # s3_uid = "s01325" s3_uid = var.s3_uid resource_realm = var.realm @@ -40,14 +44,14 @@ resource "nubes_postgres" "npg" { resource "nubes_postgres_user" "pg_user" { postgres_id = nubes_postgres.npg.id - username = "u-user0" + username = "user0" role = "ddl_user" adopt_existing_on_create = true } resource "nubes_postgres_database" "db" { postgres_id = nubes_postgres.npg.id - db_name = "db_terra" + db_name = "db0" db_owner = nubes_postgres_user.pg_user.username adopt_existing_on_create = true # suspend_on_destroy = false diff --git a/examples/POSTGRES/stress_destroy_apply.sh b/examples/POSTGRES/stress_destroy_apply.sh new file mode 100755 index 0000000..76bb6ca --- /dev/null +++ b/examples/POSTGRES/stress_destroy_apply.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# 2026-03-20 +# stress_destroy_apply.sh — 5 итераций terraform destroy + apply для проверки lifecycle PG. +# Запускать вручную с VM: bash stress_destroy_apply.sh +# Логи каждой итерации пишутся в stress_log_N.txt + +set -e + +ITERATIONS=5 +DIR="$(cd "$(dirname "$0")" && pwd)" +cd "$DIR" + +echo "=== Старт stress-теста: $ITERATIONS итераций destroy+apply ===" +echo "Workdir: $DIR" +echo "" + +for i in $(seq 1 $ITERATIONS); do + LOG="stress_log_${i}.txt" + echo "--- Итерация $i/$ITERATIONS ---" + echo "Лог: $LOG" + + echo "[$i] DESTROY — $(date)" | tee "$LOG" + terraform destroy -auto-approve 2>&1 | tee -a "$LOG" + DESTROY_CODE=${PIPESTATUS[0]} + + if [ $DESTROY_CODE -ne 0 ]; then + echo "[!] destroy завершился с ошибкой (код $DESTROY_CODE), итерация $i. Прерывание." | tee -a "$LOG" + exit $DESTROY_CODE + fi + + echo "" | tee -a "$LOG" + echo "[$i] APPLY — $(date)" | tee -a "$LOG" + terraform apply -auto-approve 2>&1 | tee -a "$LOG" + APPLY_CODE=${PIPESTATUS[0]} + + if [ $APPLY_CODE -ne 0 ]; then + echo "[!] apply завершился с ошибкой (код $APPLY_CODE), итерация $i. Прерывание." | tee -a "$LOG" + exit $APPLY_CODE + fi + + echo "" | tee -a "$LOG" + echo "[$i] Итерация завершена успешно — $(date)" | tee -a "$LOG" + echo "" +done + +echo "=== Все $ITERATIONS итераций прошли успешно ==="