README читает человек впервые — ему нужны структура, шаги запуска и операции,
а не разбор прошлых костылей. Удалено:
- раздел «Почему нельзя создать всё одним apply» с историей про try() и PGPASSWORD;
- упоминания try() в apps/lucee.tf, apps/flask.tf, apps/nodejs.tf;
- «data-source/backend» из apps/locals.tf и путь к удалённому разделу из pg/outputs.tf.
Заодно удалён старый TEST_STAND/CRUD/terraform.tfvars (не читается, значения
перенесены в pg/terraform.tfvars и apps/terraform.tfvars).
Проверено: terraform validate — Success в pg/ и apps/ (apps — с временным creds.json).
Было: одна папка, один state — destroy убивал и БД, и приложения; пароль БД
приходилось вытаскивать костылём try() в одном apply, приложения поднимались
с пустым PGPASSWORD.
Стало:
- pg/ — кластер PostgreSQL + пользователь + база + outputs (хост/порт/юзер/база/пароль);
destroy здесь переводит кластер в Suspend, а пользователь и база не удаляются
(keep_on_destroy = true + adopt_existing_on_create = true);
- apps/ — три приложения-потребителя; креды БД читаются из creds.json (выгрузка
outputs папки pg/, т.к. state раздельные, а data-source у провайдера нет);
try() убран полностью — пароль к моменту этого apply уже существует;
- apps/.gitignore — creds.json, terraform.tfvars, state/lock;
- README.md переписан: структура, «зачем разделено», пошаговые 3 шага запуска,
повседневные операции (destroy приложений не трогает БД), про destroy базы.
Проверено: terraform init+validate в обеих папках — Success;
plan в pg/ — 3 to add (кластер, пользователь, база) + 6 outputs.
Инстанс PG при destroy уходит в Suspend (suspend_on_destroy_default: true в
90_postgres.yaml), а не удаляется. Без keep_on_destroy подресурсы (create_user/
create_database) удалялись бы из живого кластера — после resume приложения
работали бы с пустой БД, данные базы были бы потеряны.
keep_on_destroy=true → режим state_only: при destroy подресурс остаётся в облаке
и только убирается из state. В паре с adopt_existing_on_create=true следующий
apply усыновляет существующий объект, а не падает на 'уже существует'.
Проверено: terraform validate — Success (провайдером 3.0.0, где атрибут есть).
Раньше locals читали пароль напрямую: jsondecode(vault_secrets["users"]).user4crudpg.password.
При первом apply пароля ещё нет (create_user выполняется после создания кластера), поэтому
Terraform падал с «Invalid index ... does not identify an element in this collection value».
Теперь через try(... = ""): на первом apply в env идёт пустая строка и прогон не роняет;
на втором apply пароль уже в Vault, try возвращает настоящее значение, приложения получают верный env.
Комментарии в lucee.tf/flask.tf/nodejs.tf объясняют зачем try и почему два apply.
Проверено: terraform validate — Success; plan — No changes; Exit 0.
Провайдер отправляет postgres_conf на платформу как есть (resources_core.FormatString
возвращает строку без перевода имён), поэтому ключи обязаны совпадать со спекой:
postgresConf.paramName / postgresConf.paramValue. С snake_case (param_name/param_value)
платформа падала с "Invalid JSON String" (операция 5AAF1E39-8812-4994-AD14-78D51ED2077D).
Значение paramValue взято '' — как в HAR/pgmodify.har и в TEST_STAND/PG/resources.tf.
План проходит: 6 to add, exit 0.
Из-за sensitive = true в plan вместо значений печаталось "(sensitive value)".
Убрано в: DEV_STAND/CRUD, DEV_STAND/POSTGRES, TEST_STAND/POSTGRES, TEST_STAND/PGwNewRegistry.
api_token остаётся sensitive везде — он действительно секрет.
realm — не секрет, но из-за sensitive = true в plan вместо имени печаталось
"(sensitive value)". Теперь видно resource_realm = "k8s-3-sandbox-nubes-ru".
Плана это не меняло: plan по-прежнему 6 to add, exit 0.
Прочие sensitive оставлены как есть: api_token (секрет), vault_secrets (платформа).
vm.tf целиком обёрнут в блочный комментарий /* … */ со пояснением причины:
в test инстанс vApp не прошёл валидацию схемы (нужен reconcile). Вернуть —
удалить обрамляющие строки.
Проверено: terraform fmt -check OK, validate Success,
plan = 1 to add (только Штурвал); инстансов vApp/ВМ стенда в тенанте нет (все deleted).
Первый apply в test: vdc/edge/org_ip/snat создались; упали:
- Штурвал: 'свободных Ip в тенанте WZ03709-iaas: 1, необходимо 2' — на NaeelOrg
было count=10, часть адресов держит кластер iot-naeel. Поднято до 12.
- vApp: 'не удалось валидировать схему инстанса' -> not created (вероятно плавающая,
при повторе — reconcile).
После destroy (владелец): fullpipe-vdc = suspended (suspend_on_destroy),
fullpipe-edge = running (keep_on_destroy), локальный state пуст.
Порядок: apply -target=nubes_vc_org_ip_allocation.org_ip -> полный apply.
HISTORY/2026-10-01_test_stand_fpipegmail.md дополнен разделом с ошибками и решением.
Создана папка (без .terraform/state/lock — это состояние dev). Изменены параметры:
- versions.tf: nubes-dev/nubes 2.0.1 -> nubes-test/nubes 3.0.0;
- variables.tf: api_endpoint -> lk-api-gateway-test.ngcloud.ru;
- terraform.tfvars: organization=NaeelOrg (найдена через API, svc 19), ip_count=10
(в test на орге уже выделено 10 IP), storage SSD (в test vDC строят на SSD);
- shturval.tf: shturval-test1 / shturval-test-01 / workers-shturval-test.
Коллизии проверены: в test заняты naeel-vdc, 'VDC для кластера iot-naeel',
naeel_vc_nsxt, 'Edge для кластера IOT naeel', 'Кластер Kubernetes [iot-naeel]' —
наши имена (fullpipe-vdc/-edge/-vapp-02, web02, shturval-test1) свободны.
Проверено: terraform init (3.0.0), fmt -check OK, validate Success,
plan = 7 to add / 0 change / 0 destroy. apply НЕ запускался.
Документация: HISTORY/2026-10-01_test_stand_fpipegmail.md
Легаси-версии (5.0.x/5.1.x/3.1.x/2.1.x) в реестре отсутствуют (404), стенды не могли
пройти terraform init. Приведены к новой схеме нумерации от 2026-09-03.
- DEV (nubes-dev): CRUD, POSTGRES, SHTURVAL_MGMT -> 2.0.0
- TEST (nubes-test): CRUD, PG, POSTGRES, MARIA_DB, buck0, kuber, IOT_RMQ_DEMO -> 3.0.0
(DEV_STAND/IOT_KAFKA_DEMO тоже nubes-test -> 3.0.0)
- PROD (nubes): PG1, POSTGRES, RABBIT -> 1.0.0
- README стендов TEST_STAND/buck0, TEST_STAND/PG: версии приведены к 3.0.0
- getting-started: убрана versioned-ссылка на доки (2.1.7) -> актуальный домен без версии
- .gitignore: откатано правило TMP/ (на remote TMP/init-test-*/main.tf трекаются)
- stages always visible (remove log_level gating)
- fix tty resource leak (move out of poll loop)
- show current stage [..] in addition to completed [OK]/[FAIL]
- sync services_list.txt for all 3 stands with live UI
- add YAML vs API comparison script
- bump TEST version 5.0.1 -> 5.0.2