docs: пометить отменённый заход модификаторов как LEGACY + исправить ложные факты

- баннеры «ЛОЖНЫЙ ПУТЬ — ОТМЕНЕНО» на 4 файла HISTORY/OPUS/2026-09-22_modifier_* и docs/60_strategy/modifier_resources_ideology_and_specification.md
- vIPConfigure: replace-семантика, НЕ накопительная (по тесту docs/ORG_IP_MODIFIER_TEST_2026-09-22.md)
- обновлены ссылки на перенесённые материалы (docs/... -> NOTES/..., HOW_TO/...)
This commit is contained in:
Repinoid
2026-09-24 07:51:25 +03:00
parent d93ff66482
commit 2d8e435dd4
59 changed files with 23 additions and 6 deletions
+133
View File
@@ -0,0 +1,133 @@
# Universal Provider Work Summary (Detailed)
## 1) Repository & Workspace
- Workspace root: `/home/naeel/terra`
- Active generator project: `/home/naeel/terra/nubes_provider_gen`
- Shared Terraform test config (the one you requested): `/home/naeel/terra/test_persistent/main.tf`
- Provider dev override for this shared config: `/home/naeel/terra/test_persistent/dev_override.tfrc`
## 2) What Was Built / Changed (High Level)
### Universal generator-based provider (Go)
We implemented a generator that reads YAML specs in `resources_yaml` and produces Go resources in `internal/resources_gen`, plus a resource registry.
### Exporter (auto YAML generation)
Created/extended exporter tool to pull CFS params and outputs from API:
- Path: `/home/naeel/terra/nubes_provider_gen/tools/export_yaml/main.go`
- Exports full `create` and `modify` params (cfsParams)
- Added outputs extraction from `state/out`
- Handles non-string `defaultValue`
- Resolves `svcOperationId` via instance details and operations history
- Doesn’t fail if `modify` op is absent (for resources that have no modify)
### Generator updates
- Path: `/home/naeel/terra/nubes_provider_gen/tools/gen/main.go`
- Added `outputs` to YAML schema and generated resource schema
- Added output fetch during Create/Read/Update (uses `GetInstanceOutputs`)
- If outputs fetch fails, outputs are set to `null` (avoid unknowns)
- Improved `attrNameFromCode` to avoid `resource_c_p_u` / `allow_no_s_s_l` style
- Required params with defaults now become optional+computed in schema
### Core client updates
- Path: `/home/naeel/terra/nubes_provider_gen/internal/core/client.go`
- Added `GetInstanceOutputs()` to fetch `state.out` for computed outputs
### Documentation
- Added MAYDO section in `/home/naeel/terra/docs/ai_universal_provider_gen.md` for future enhancements
## 3) Key Files (Current)
- Generator: `/home/naeel/terra/nubes_provider_gen/tools/gen/main.go`
- Exporter: `/home/naeel/terra/nubes_provider_gen/tools/export_yaml/main.go`
- Core client: `/home/naeel/terra/nubes_provider_gen/internal/core/client.go`
- YAML specs: `/home/naeel/terra/nubes_provider_gen/resources_yaml/*.yaml`
- Generated resources: `/home/naeel/terra/nubes_provider_gen/internal/resources_gen/*`
- Shared Terraform test config: `/home/naeel/terra/test_persistent/main.tf`
- Dev override: `/home/naeel/terra/test_persistent/dev_override.tfrc`
## 4) Exported YAML Specs (Current)
### Dummy
- File: `/home/naeel/terra/nubes_provider_gen/resources_yaml/dummy.yaml`
- `create` and `modify` params exported
- `outputs` are **absent** (API returns `state.out = null` for dummy)
### Bucket (S3 bucket)
- File: `/home/naeel/terra/nubes_provider_gen/resources_yaml/bucket.yaml`
- `modify` is empty (API does not expose modify op for that instance)
- `outputs` are **absent** (API returns `state.out = null`)
### Postgres
- File: `/home/naeel/terra/nubes_provider_gen/resources_yaml/postgres.yaml`
- CFS params exported, outputs include:
- `externalConnect`, `internalConnect`, `monitoring` (all as string)
- `resourceDisk` type conflict fixed (kept as string for both create/modify)
## 5) Shared Terraform Test Config (as requested)
File: `/home/naeel/terra/test_persistent/main.tf`
Contains **dummy + bucket + postgres**. Current content:
- `nubes_dummy.test_bolt`:
- display_name = `Terraform-Test-Bolvanka-20260201-01`
- resource_realm = `dummy`
- delete_mode = `suspend`
- resume_if_exists = `true`
- `nubes_bucket.test_bucket`:
- display_name = `tf-bucket-gen-20260201-02`
- delete_mode = `delete`
- resume_if_exists = `false`
- `nubes_postgres.test_pg`:
- display_name = `tf-postgres-20260201-03`
- delete_mode = `state_only`
- resume_if_exists = `false`
- other required params from exported YAML
**Dev override** now points to generator build:
`/home/naeel/terra/test_persistent/dev_override.tfrc` → `"terrareg.kube5s.ru/nubes/nubes" = "/home/naeel/terra/nubes_provider_gen"`
## 6) Tokens & Auth Handling
Rule: on new access_token, save to `/home/naeel/terra/HH-MM-SS.token` (expiry time).
Saved tokens so far:
- `/home/naeel/terra/11-53-16.token` (old)
- `/home/naeel/terra/15-20-50.token` (old)
- `/home/naeel/terra/15-23-19.token` (old)
- `/home/naeel/terra/15-25-59.token` (latest)
Important:
- `/home/naeel/terra/test_persistent/terraform.tfvars` was updated to use the latest token from `15-25-59.token`.
- `/user` endpoint returns 200 with the latest token (so token is valid).
## 7) Test Runs / Current State
### Dummy & Bucket
- Dummy created successfully (id: `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`).
- Bucket created successfully (id: `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`).
### Postgres
- Postgres resource is **not in Terraform state** (it was removed with `terraform state rm`).
- New create was attempted with display_name `tf-postgres-20260201-03` but apply was **cancelled** by user.
- Last error before name change: duplicate display name (400). Now fixed with new display_name.
### TLS timeouts
Occasional TLS handshake timeouts when creating resources. Retrying apply usually works.
## 8) Known Issues / Fixes Applied
- **Outputs**: provider now sets outputs to `null` if `state/out` is missing/unavailable, preventing “unknown after apply” errors.
- **Attribute names**: fixed to avoid `resource_c_p_u` or `allow_no_s_s_l`.
- **Required + default**: required params with defaults are optional+computed in schema.
- **Bucket delete**: fails if instance not fully created. Fixed by waiting and retrying destroy.
## 9) What To Do Next (Continuation Steps)
1) Rebuild provider (if not already):
- `cd /home/naeel/terra/nubes_provider_gen`
- `go run ./tools/gen`
- `go build -o terraform-provider-nubes`
2) Ensure token in `/home/naeel/terra/test_persistent/terraform.tfvars` is valid.
3) Apply from shared config:
- `cd /home/naeel/terra/test_persistent`
- `TF_CLI_CONFIG_FILE=./dev_override.tfrc terraform apply -auto-approve`
4) If TLS timeouts occur, re-run `terraform apply`.
5) If Postgres creation fails due to name conflict, change `display_name` to a new unique value.
## 10) Notes on Outputs
- For dummy & bucket: `state.out` is null, so YAML does not list outputs.
- For postgres: outputs are present in YAML; provider sets them to `null` when not returned yet.
---
If you want a shorter summary or specific error fixes, tell me what to focus on.
@@ -0,0 +1,89 @@
# Резюме сессии: Диагностика K8s (Штурвал), VDC и архитектура провайдера (2026-09-20)
## 1. Инфраструктурный контекст
- **ВМ 213 (jump-host / dev)**:
- SSH: `ssh vps` (`5.172.178.213`, user `naeel`, key `~/.ssh/naeel_vm_id_ed25519`).
- kubectl контекст по умолчанию: `tazetdinovn@gmail.com@naeel-test-3`.
- **Кластер `naeel-test-3`**:
- API: `https://185.247.187.146:6443`.
- Узлы: 6 нод (3 control-plane, 3 workers), версия v1.34.1 / платформа Штурвал 2.12.1.
- **Кластер `devclustername`**:
- API: `https://185.247.187.226:6443`.
- Статус: порт 6443 на Edge доступен, но TLS сбрасывается (`connection reset by peer`) — виртуальные машины кластера находятся в `suspend` / выключены.
---
## 2. Что было сделано и починено в кластере `naeel-test-3`
### Проблема:
В веб-интерфейсе Штурвала кластер висел в статусе **«Работает с ошибками» (⚠️ 2/4 по NodeConfigItems)**.
### Причина:
1. На активном воркере `naeel-test-3-workers-5p8w7-vxzch` висело ожидание применения конфигураций (`RebootPending` с типом `drainonly`).
2. Очередь на применение/drain была заблокирована (`SlotsOccupied`), так как в CRD `nodeconfigs.node.shturval.tech` осталась старая удалённая нода `naeel-test-3-workers-5p8w7-nqkr2` с зависшим флагом `rebootallowed: true`.
### Решение:
1. Вычищены все фантомные объекты `nodeconfigs`, которых уже нет среди реальных K8s-нод (сняты блокирующие finalizers).
2. Слот освободился: контроллер `shturval-node-config` корректно выполнил `drainonly` на воркере `vxzch` (под `pythonk8s` переехал на соседний воркер `wwqj2`).
3. Применились оставшиеся `NodeConfigItem` (`generic-init-config`, `all-to-nubes-registry`).
4. **Текущий статус**:
- Все 6 нод в статусе `Ready`.
- Все 6 `nodeconfigs` в статусе `READY: true`.
- Все 4 `nodeconfigitems` в статусе `ready: true` (**4/4, статус кластера зелёный**).
- Под `pythonk8s` (`drhider.pythonk8s.dev.nubes.ru`, ns `20a75175-a58c-49cb-b8fa-e86367b1a8dc`) поднят и работает (1/1 Running).
- Потребление ресурсов: среднее ~22m CPU и ~103 MiB RAM на под; суммарно на весь 6-узловой кластер ~1.6 CPU и ~7.5 GiB RAM (минимальный фоновый простой).
---
## 3. Блокировка операций в личном кабинете облака (Suspend / Modify)
### Симптом:
При попытке выполнить операцию `suspend` кластера в UI облака возникает ошибка:
`Concurrent operations are not supported (job status: cannot obtain job result) There is a started operation on this instance`
### Диагностика через API Gateway (`lk-api-gateway-dev.ngcloud.ru`):
- Инстанс кластера: `e78a40b9-7de1-4c88-af7a-ad7f7efaa7c2`.
- Зависшая операция: `modify` (`opUid: 2fb7dd59-732a-4bb9-add2-6bddd7329f72`).
- Причина зависания: оркестратор CFS поймал таймаут (`Timeout has been exceeded`), выполнил откат, записал лог ошибки, но **не проставил `dtFinish` и `isSuccessful` в БД**.
- Статус операции в API остался незакрытым, из-за чего API Gateway блокирует любые новые операции над инстансом.
- **Внимание**: это баг бэкенда платформы облака (CFS/оркестратора). Средствами `kubectl` внутри кластера это не лечится — требуется сброс статуса операции на стороне API платформы или через поддержку.
- Ошибка в истории операций: `Не удалось включить кластер. Ошибка: Error not found from 'parseTerraformError'` — вызвана тем, что общий обработчик бэкенда облака по ошибке прогнал текст через парсер ошибок Terraform. Внутри K8s Terraform не используется.
---
## 4. Архитектурные правила по VDC и Terraform-провайдеру
### Почему возникает ошибка дубликата VDC:
`VDC с именем 'WZ03709-saas-snb1-i24-vcpu50' уже существует внутри организации 'WZ03709-saas'`
- Имя VDC генерируется бэкендом детерминированно: `{org}-{type}-{segment}-{cpu}-vcpu{reservation}`.
- В одном сегменте организации существует максимум два класса VDC:
- `vcpu50` (50% гарантия vCPU — для dev/test, оверселлинг, дешевле);
- `vcpu80` (80% гарантия vCPU — для prod/баз данных, жесткая фиксация ресурсов).
- Создавать третий VDC с тем же процентом SLA в рамках одной организации невозможно (конфликт уникальности имен в vCloud) и бессмысленно: изоляция проектов внутри VDC делается через **vApp**, **сети (Org Networks)** и правила фаервола. При нехватке ресурсов VDC масштабируется через `modify`.
- **Канон Terraform**: при работе с уже созданными VDC в манифесте указывать:
```hcl
adopt_existing_on_create = true
```
(согласно `docs/60_strategy/provider_philosophy.md`).
### Зачем нужны дочерние ресурсы-действия (Action / Sub-resources):
Цепочка развертывания vCloud/NSX-T имеет циклические зависимости:
1. `vcOrg -> create`
2. `vcVdc -> create`
3. `vcNsxt -> create` (Edge Gateway)
4. `vcOrg -> modify` (выделение белых IP в организацию, так как появился Edge)
5. `vcNsxt -> modify` (настройка SNAT под конкретный выделенный IP)
6. `k8sShturval -> create` (нодам нужен интернет через SNAT)
Чтобы пользователю не приходилось делать несколько ручных прогонов `terraform apply` с ручным редактированием `.tf` файлов между шагами, в провайдере создаются **дочерние ресурсы-действия**.
- Под капотом провайдера эти дочерние ресурсы транслируются в точечные вызовы **`modify`** над родительскими объектами.
- Это стандартная практика в Terraform (аналог `aws_security_group_rule` для `aws_security_group`).
---
## 5. Что делать дальше в новом чате
1. Если продолжаем работу с провайдером Nubes:
- Проверить статус зависшей операции `2fb7dd59-732a-4bb9-add2-6bddd7329f72` в API Gateway.
- Разрабатывать/тестировать логику дочерних ресурсов (action/sub-resources) и `modify`-пайплайна по стандарту `docs/60_strategy/provider_philosophy.md`.
2. Если требуется проверить второй кластер (`devclustername` / `185.247.187.226`):
- Убедиться, что кластер выведен из suspend в веб-интерфейсе (чтобы поднялся API server на порту 6443).
@@ -0,0 +1,155 @@
# Резюме сессии: VDC create-flow, диалог с Opus и правка fallback (2026-09-21)
## 1. Контекст задачи
- Цель: довести до рабочего состояния создание `nubes_vc_vdc` в `FullPipe`.
- Симптом: при создании VDC провайдер падал на `GET /instanceOperations/{opUid}?fields=cfsParams` с HTTP 500.
- В ходе разбора было подтверждено, что обычные сервисы через тот же провайдер работали, а VDC попадал в отдельную проблемную ветку backend-обработки.
---
## 2. Диагностика проблемы
### 2.1. Что ломалось
- В `provider/internal/core/client.go` create-flow делал `GET /instanceOperations/{opUid}?fields=cfsParams` сразу после создания операции.
- Для VDC этот запрос приводил к ошибке backend’а:
- `Invalid call of the function [getResourceRealmConfig]`
- `Cannot cast Object type [Struct] to a value of type [string]`
- источник ошибки: `/app/api/v1/resources/instance_operation_cfs_param.cfc`
- Причина по отчету: для `vc_vdc` вычислялся динамический `descr` у `storageConfig.name`, и backend падал на `resourceRealm`, который в DEV хранится как `Struct`, а не `string`.
### 2.2. Почему обычные сервисы не ломались
- На обычных сервисах этот `GET` либо не попадал в проблемный backend-код, либо не требовал вычисления `resourceRealm`.
- Для VDC в YAML есть специфическая зависимость:
- `generated/dev/resources_yaml/21_vc_vdc.yaml`
- `storageConfig.name` содержит вычисляемый `descr` с `getResourceRealmConfig(...resourceRealm...)`.
- Для обычных сервисов, например `vapp` и `postgres`, такого вычисляемого `resourceRealm`-контекста нет.
### 2.3. Почему `hasUnresolvedParams` мешал
- Эвристика проверяла **все** строковые параметры, а не только параметры с `ref_svc_id`.
- Для VDC это ломало fallback на обычных литералах вроде:
- `providerVdc = fast-2.8`
- `networkProvider = default`
- Эти значения не UUID и не JSON, но и резолвить их не нужно.
- В результате при падении GET провайдер вместо продолжения переходил в ошибку.
---
## 3. Диалог с Opus
### 3.1. Что просили у Opus
- Проверить только:
- `provider/internal/core/client.go`
- `docs/DEBUG_REPORT_VC_VDC_500.md`
- `generated/dev/resources_yaml/21_vc_vdc.yaml`
- `generated/dev/resources_yaml/26_vapp.yaml`
- `generated/dev/resources_yaml/90_postgres.yaml`
- Вопросы к Opus были узкими:
1. почему обычные сервисы работали, а VDC начал падать на `GET ?fields=cfsParams`
2. есть ли в VDC специфическая структура или зависимость, которой нет у обычных сервисов
3. является ли `hasUnresolvedParams` неверной эвристикой именно в этом месте
4. что именно надо исправить
### 3.2. Что ответил Opus по сути
- Root cause — не данные Terraform и не сами строки `fast-2.8` / `default`, а backend-ошибка на `GET /instanceOperations/{opUid}?fields=cfsParams` именно для VDC.
- VDC отличается от обычных сервисов тем, что в его YAML есть динамический `descr` для `storageConfig.name`, который тянет `resourceRealm`.
- `hasUnresolvedParams` была признана лишней и хрупкой эвристикой: она может ломать fallback на обычных строках.
- Итоговое решение Opus: при ошибке GET идти дальше по браузерному flow, без условий по всем строковым параметрам.
### 3.3. Дополнительные уточнения в диалоге
- Был отдельный спор по формулировке про Lucee / ColdFusion backend.
- В итоге было зафиксировано, что этот термин — не отдельная гипотеза, а просто обозначение backend-слоя, который уже фигурировал в отчетах и traceback’ах.
- Opus также подтвердил, что для VDC этот GET нужен только как вспомогательный шаг для `resolveRefSvcParamValues`, а не как обязательный бизнес-этап.
---
## 4. Что изменили в коде
### 4.1. `provider/internal/core/client.go`
- В `CreateGenericInstanceUniversalV6` удалён gate по `hasUnresolvedParams`.
- Теперь логика такая:
- если `GET /instanceOperations/{opUid}?fields=cfsParams` успешен — парсим и резолвим `ref_svc_id`
- если GET падает — просто продолжаем POST’ить параметры, а потом идём в `validate-cfs` и `run`
- Функция `hasUnresolvedParams` удалена полностью.
- После удаления была убрана осиротевшая документационная строка, оставшаяся над `isHexDigit`.
### 4.2. `provider/internal/core/client_test.go`
- Добавлен тест:
- `TestCreateGenericInstanceUniversalV6_ContinuesWhenOpDetailsGETFails`
- Тест моделирует:
- `POST /instances`
- `POST /instanceOperations`
- `GET /instanceOperations/{opUid}?fields=cfsParams` → 500
- `POST /instanceOperationCfsParams`
- `GET /instanceOperations/{opUid}/validate-cfs`
- `POST /instanceOperations/{opUid}/run`
- финальный `GET /instances/{uid}`
- Проверка теста:
- create-flow завершился успешно
- все 7 параметров были отправлены с ожидаемыми значениями
- polling по операции был ровно один раз
---
## 5. Проверка после правки
- `cd /home/naeel/TF/tf_provider/provider && go test ./internal/core` — успешно.
- После ревью был пойман и исправлен только косметический хвост:
- старый комментарий над `isHexDigit`, оставшийся после удаления `hasUnresolvedParams`.
- После этого пакет `internal/core` снова прошёл тесты.
---
## 6. Вывод по итогам сессии
- Проблема была не в обычных сервисах как таковых, а в специфике VDC-данных и backend-пути, который срабатывал на `GET ?fields=cfsParams`.
- `hasUnresolvedParams` была неверной эвристикой именно в create-flow VDC и ломала рабочий fallback.
- Правильное поведение: если GET падает, не гадать по строковым параметрам, а продолжать browser-like flow через POST параметров, validate и run.
---
## 7. Что дальше
- Следующий этап — уже не правка логики, а публикация и стендовая проверка при необходимости.
- DEV-релиз `2.0.3` успешно собран и загружен в registry `nubes-dev` через `TOOLS/scripts/03_build_and_upload_provider.sh --profile TOOLS/config/dev`.
- Перед этим уже был подготовлен короткий запрос на ревью для Opus и получен ответ, который подтвердил направление правки.
---
## 8. Отдельный диалог про `organization_uid`, refSvcId и универсальное поведение
### 8.1. Что стало проблемой
- В `vc_vdc` поле `organization_uid` можно передавать как display name (`kontora`), так и как UUID организации.
- В коде `provider/internal/resources_gen/21_vc_vdc_resource.go` это поле сейчас резолвится через `ResolveRefSvcParamValue(...)` в UUID.
- После `apply` Terraform видит расхождение: в конфиге было имя, в state оказался UUID, и появляется ошибка `Provider produced inconsistent result after apply`.
- Параллельно в этом же ресурсе остаются ручные `EqualFold`-хаки, которые пытаются сохранить старое значение, но не решают кейс "имя vs UUID".
### 8.2. Почему это сравнивали с S3
- Для `nubes_s3_bucket` похожее поведение уже работает: ref-поле `s3_user_uid` проходит через общий механизм refSvc-резолва и state-refresh.
- В S3 есть симметричный путь: UUID можно принимать на вход, а состояние при чтении синхронизируется через общий mapping-слой.
- Поэтому S3 не падает на inconsistency, а VDC падает из-за локальных restore-хаков и разного поведения на create/read/update.
### 8.3. Что выяснили по коду
- Ключевой участок VDC:
- [provider/internal/resources_gen/21_vc_vdc_resource.go](provider/internal/resources_gen/21_vc_vdc_resource.go#L197-L202)
- [provider/internal/resources_gen/21_vc_vdc_resource.go](provider/internal/resources_gen/21_vc_vdc_resource.go#L323-L338)
- [provider/internal/resources_gen/21_vc_vdc_resource.go](provider/internal/resources_gen/21_vc_vdc_resource.go#L388-L403)
- [provider/internal/resources_gen/21_vc_vdc_resource.go](provider/internal/resources_gen/21_vc_vdc_resource.go#L511-L525)
- В S3 аналогичный слой устроен аккуратнее:
- [provider/internal/resources_gen/13_s3bucket_resource.go](provider/internal/resources_gen/13_s3bucket_resource.go#L149-L159)
- [provider/internal/resources_core/state_refresh.go](provider/internal/resources_core/state_refresh.go#L82-L96)
- [provider/internal/resources_core/params_ref_mapping.go](provider/internal/resources_core/params_ref_mapping.go#L124-L147)
### 8.4. Что решил сделать дальше
- Пользователю нужен не частный фикс только для VDC, а универсальная схема для всех refSvcId-полей.
- Была сформулирована задача для Opus: определить, какой канон выбрать для state, где делать name→UUID и UUID→display_name, и как убрать ручные `EqualFold`-хаки без поломки S3 и других уже рабочих ресурсов.
- Отдельно зафиксировано требование: ответ Opus нужен короткий, но сам вопрос должен быть подробным и однозначным.
### 8.5. Важный вывод на сейчас
- Универсальное решение пока не внедрено.
- Текущий безопасный путь — сначала получить короткий архитектурный ответ от Opus, а уже потом править генератор и пересобирать ресурсы.
---
## 9. Детерминированная пересборка генератора
- После отдельного разбора `kind: modifier` выяснилось, что падение генерации было эксплуатационным: запускался устаревший бинарник `resource-generator`, а не текущие исходники.
- В `TOOLS/scripts/02_generate_resources_and_docs_v2.sh` убран `mtime`-гард через `find ... -newer`; генераторы теперь всегда собираются заново перед прогоном.
- Это сделано специально, чтобы старый бинарник больше не мог скрыть поддержку новых `kind`-веток в YAML-спеках.
- Дополнительно `TOOLS/resource-generator/bin/` добавлен в ignore, чтобы локальный stale-артефакт не путал следующий запуск.
@@ -0,0 +1,194 @@
# Передача контекста: Terraform-провайдер Nubes
Дата: 2026-09-22 | Версия DEV: 2.0.8 | HEAD: 13beb9c (`release(dev): 2.0.8`)
Документ для старта новой сессии. Прочитать целиком перед любыми действиями.
---
## 1. Правила работы (соблюдать строго)
- **Никаких действий без прямого разрешения.** Правки, сборки, заливки, коммиты, запуск
terraform, запросы в API — только по явной команде оператора.
- **Вопрос в любой форме = только ответ.** Не выполнять действий, не предлагать «а ещё могу».
- **Коммитить после каждой правки**, разбивая по смыслу. Не копить в рабочем дереве.
- **Не расширять область работ.** Формулировка «сделай актуальным везде» не даёт права
на дополнительные шаги.
- **Не догадываться.** Не уверен — сказать прямо и спросить. Причину бага доказывать
фактами (логи, трассировки, содержимое файлов), а не гипотезами.
- Язык ответов — русский.
---
## 2. Проект
- Репозиторий: `/home/naeel/TF/tf_provider`
- Провайдер: `terraform-provider-nubes`, Go, `terraform-plugin-framework v1.8.0`
- **Go-модуль провайдера лежит в `provider/`** (не в корне). `go build ./...` из корня
падает с «directory prefix . does not contain main module».
- Генераторы в `TOOLS/`:
- `yaml-generator` — из API в YAML-спеки;
- `resource-generator` — из YAML в Go (шаблоны `text/template` в
`TOOLS/resource-generator/internal/templates/`);
- `docs-generator` — из YAML в Markdown.
- Пайплайн: `TOOLS/scripts/01_generate_yamls.sh` → `02_generate_resources_and_docs_v2.sh`
→ `03_build_and_upload_provider.sh` (скрипт `03` сам прогоняет `01` и `02`).
---
## 3. Состояние на 2026-09-21 (конец сессии)
- Ветка `master`, **рабочее дерево чистое**, HEAD = `13beb9c` (`release(dev): 2.0.8`).
- Локальные коммиты **в origin не пушились**.
- **DEV-версия: 2.0.8**, залита в
`tf-registry.containerk8s.services.ngcloud.ru/nubes-dev/nubes`,
подпись GPG `CB3A0DF161ECC416` (`tazet@narod.ru`, ключ `secrets/private_key.asc`).
- S3: `prod-s3/nubes-terraform-registry/...`, endpoint `https://s3.msk-1.ngcloud.ru`.
- Namespace: `nubes-dev`, провайдер `nubes`.
- Terraform v1.9.5 локально.
---
## 4. Что починено в этой сессии
| Коммит | Что |
|---|---|
| `7ecd2aa` | детерминированная пересборка генераторов (удалён устаревший бинарь) |
| `2286d34` | destroy-guard в `ModifyPlan` + универсальный refSvc (имя или UUID) |
| `1401003` | release 2.0.4 |
| `d608fba` | FullPipe: `edge.tf`, `storage_config` fast→SATA |
| `92e04da` | TODO-документ по багу docs-generator |
| `bffe3d9` | refSvc-поля без `Computed` (unset = null, а не unknown) |
| `61c7e20` | HISTORY сессии |
| `54b0baa` | release 2.0.5 |
| `af2e10b` | docs-generator: `map-fixed` → `= { ... }` (аргумент, не блок) |
| `7c2cc67` | docs-generator: `array-map-fixed` → `jsonencode([...])` |
| `3ca0752` | docs-generator: строковые дефолты в кавычках |
| `8d405ba` | core: lifecycle-aware подсказки + `supportsSuspend` в сигнатурах |
| `c6715e8` | генератор: `supportsSuspend` в diagnostics; нет `suspend_on_destroy` без suspend |
| `69808bd` | release 2.0.6 |
| `67c4d2f` | `TOOLS/scripts/validate_docs_examples.sh` |
| `14ada09` | ТЗ для Flash по tainted-replace |
| `724f5f7` | **убрана create-time проверка существования из `ModifyPlan`** (ломал tainted-replace и `destroy`) |
| `25080b7` | release 2.0.7 |
| `3c0157a` | **`ShouldBeOptionalComputed`**: read-back параметры без Default → `Optional+Computed` |
| `4b34cc7` | **core: гарантия known** — `unknown → null` для read-back полей |
| `13beb9c` | release 2.0.8 |
---
## 5. Ключевые архитектурные факты (не переоткрывать заново)
1. **Две копии сгенерированного кода.**
- `provider/internal/resources_gen/` — в `.gitignore`, локальный артефакт;
- `generated/dev/go/` — актуальный вывод генератора; именно его компилирует релиз
(скрипт `03` копирует его в temp-копию `provider`).
Проверять надо **`generated/dev/go`**, не `resources_gen`. Проверка не той копии
уже приводила к ложным выводам.
2. **Рецепт проверки сборки без релиза:**
```bash
TMP=$(mktemp -d) && cp -R provider "$TMP/provider" && \
find "$TMP/provider/internal/resources_gen" -maxdepth 1 -type f -name '*.go' -delete && \
cp generated/dev/go/*.go "$TMP/provider/internal/resources_gen/" && \
(cd "$TMP/provider" && go build ./...) && echo BUILD_OK && rm -rf "$TMP"
```
3. **Версия правится в 3 файлах:** `TOOLS/config/dev/profile.env` (`VERSION`),
`DEV_STAND/FullPipe/versions.tf`, `VERSIONS.md`.
Затем коммит `release(dev): X.Y.Z` и
`./TOOLS/scripts/03_build_and_upload_provider.sh --profile TOOLS/config/dev X.Y.Z`.
4. **Перезаливка той же версии бесполезна** — Terraform не перекачает провайдер.
Всегда бампать версию.
5. `*.tfvars` в `.gitignore` (реальный токен в `terraform.tfvars` безопасен от коммита).
6. **Read-back инвариант.** Провайдер читает параметр обратно из `state_params` инстанса
(`RefreshResourceState` + `InputField`). Такой параметр обязан быть `Optional+Computed`,
если он не `Required` и без `Default` — правило `helpers.ShouldBeOptionalComputed`.
Иначе `plan=null` vs `state=значение` → «Provider produced inconsistent result after
apply».
7. `RefreshResourceState` при отсутствии кода в `state_params` схлопывает `unknown → null`
(иначе «Provider produced invalid result object after apply: ... was unknown»).
8. **`terraform destroy` при tainted-ресурсе** выполняет внутренний обычный plan, который
планирует замену (destroy+create); create-узел замены приходит в `ModifyPlan` с prior
state = null — отличить замену от создания невозможно. Поэтому create-time проверка
существования из `ModifyPlan` убрана (коммит `724f5f7`), проверка осталась в `Create`.
9. У сервиса без операции `suspend` в YAML: `SupportsSuspendDestroy=false` →
`deleteMode := "delete"`, атрибут `suspend_on_destroy` не генерируется, а подсказки в
diagnostics не предлагают adopt (он невозможен).
10. Вложенные параметры (`map-fixed`) — `schema.SingleNestedAttribute`; в HCL это
**аргумент** `= { ... }`, не блок. `array-map-fixed` — `schema.StringAttribute`
(JSON-строка).
11. Логи и артефакты отладки: `/tmp/nubes_find_debug.log` (пишет только Plan-диагностика),
`/tmp/plan_trace.txt`, `/tmp/plan_destroy.txt`, `/tmp/plan_norefresh.txt`.
12. Секреты: `secrets/private_key.asc`, `secrets/public_key.asc`, `secrets/dev.token`.
Не выводить содержимое в чат.
---
## 6. Файлы, которые нужно прочесть
**Обязательно:**
1. `.github/copilot-instructions.md` — жёсткие правила оператора.
2. `VERSIONS.md` — что и когда залито.
3. `HISTORY/2026-09-21_fullpipe_vdc_nsxt_and_refsvc_fixes.md` — журнал предыдущей сессии.
4. `TOOLS/resource-generator/internal/templates/instance.go` — главный шаблон ресурса
инстанса (ModifyPlan / Create / Read / Update / Delete / Schema).
5. `TOOLS/resource-generator/internal/helpers/helpers.go` — `ShouldBeOptionalComputed`,
`ParamDefaultExpr`, `IsNested`, nested-хелперы.
6. `provider/internal/resources_core/state_refresh.go` — read-back и инвариант known.
7. `provider/internal/resources_core/resource_diagnostics_required.go` — create-time
проверки существования/усыновления, `runningConflictHint` / `suspendConflictHint`.
8. `TOOLS/scripts/03_build_and_upload_provider.sh` и `TOOLS/scripts/build-provider.sh` —
релизный пайплайн.
9. `DEV_STAND/FullPipe/` — `versions.tf`, `vdc.tf`, `edge.tf`, `variables.tf`, `outputs.tf`.
10. `docs/TODO/docs_generator_nested_attr_syntax.md` — описание бага docs-generator
(уже исправлен, см. раздел 8).
**По необходимости:**
- `TOOLS/resource-generator/internal/templates/{subresource,modifier,action}.go`
- `TOOLS/docs-generator/internal/writers/writers.go` — `formatParamOrBlock`, `sampleValue`,
`isNestedListParam`
- `provider/internal/resources_core/crud.go` — adopt / suspend / delete
- `docs/prompt_for_flash_fix_tainted_replace.md` — разбор tainted-replace
(реализован в `724f5f7`)
- `TOOLS/scripts/validate_docs_examples.sh` — прогон `terraform validate` по примерам из доков
- Память репозитория: `/memories/repo/registry-versions.md`
---
## 7. Стенд FullPipe (Organization → vDC → Edge)
- Каталог `DEV_STAND/FullPipe`, провайдер берётся из `versions.tf` (сейчас 2.0.8).
- `nubes_vc_vdc.vdc` — `suspend_on_destroy = true`, `adopt_existing_on_create = true`.
- `nubes_vc_nsxt.edge` — `routed_net_configuration` задаётся **через `=`** (объект), не блоком.
- Подхватить новую версию: `terraform init -upgrade`.
- На 2026-09-21 `nubes_vc_nsxt.edge` был **tainted** в state (последствие прошлых
неудачных apply). Убирается `terraform untaint nubes_vc_nsxt.edge`.
---
## 8. Открытые вопросы
1. **`docs/TODO/docs_generator_nested_attr_syntax.md` устарел** — баг исправлен
(`af2e10b`, `7c2cc67`, `3ca0752`), но в файле статус «не исправлено».
2. **Стенд FullPipe не проверен end-to-end на 2.0.8** — нет подтверждённого успешного
`apply` (Organization → vDC → Edge) и `destroy` после фиксов.
3. Полный прогон `terraform validate` по всем примерам из доков (63 сервиса) не делался —
проверен только `vc_nsxt`. Скрипт для прогона готов:
`TOOLS/scripts/validate_docs_examples.sh`.
4. `TOOLS/resource-generator/internal/templates/modifier.go:65` — та же схема `Computed`
без ветки read-back. Для бага «inconsistent result after apply» не критично
(Create/Update модификаторов не читают обратно в state), но при работе с `kind: modifier`
держать в голове.
5. Пуш локальных коммитов в `origin/master` не делался.
@@ -0,0 +1,199 @@
# CHAT RESUME: IaC-развёртывание Штурвала — состояние на 2026-09-24
> **Кому:** новый чат / новый участник. Читать целиком, это хендовер.
> **Что это:** сводка длинной сессии (2026-09-23/24) по вопросу «как дать клиенту IaC для цепочки Штурвал».
> **Статус:** решение НЕ принято, код НЕ написан. Есть анализ, проверенные факты и развилка.
---
## 0. TL;DR (одним абзацем)
Клиенту нужен **настоящий IaC**: один конфиг + `terraform apply` = вся инфраструктура. Цепочка Штурвала
(`vcOrg → vcVdc → vcNsxt → [modify оргов/эдж] → k8sShturval`) упирается в две операции `modify`, которые
провайдер сейчас выразить не может: в схеме tf-ресурса их параметров нет (схема строится только из `create`).
Ручной ЛК и скрипт **отклонены** — это не IaC. Единственный каноничный путь — **отдельные tf-ресурсы под
модификации** (как сделано в провайдере VMware Cloud Director, прецедент в папке `!/`),
плюс желательно, чтобы платформа отдавала через API выводимые значения (`ipSpaceName`), которые юзер знать не может.
Часть прежних «блокеров» оказалась **ложной** — см. §7, это критично.
---
## 1. Задача
Развернуть Штурвал (k8s) целиком через Terraform, с корректным `apply`/`plan`/`destroy`:
```
vcOrg -> create (в нашем случае орг уже создана вручную и НЕ в state)
vcVdc -> create
vcNsxt -> create (Edge)
------------------------------
vcOrg -> modify (аллокация внешних IP: vIPConfigure)
vcNsxt -> modify (включить SNAT, указать внешний IP из vcOrg: ipSpaceName)
------------------------------
k8sShturval -> create
```
Операции строго последовательны. Проблема: между `nsxt.create` и `shturval.create` стоят два `modify`,
которые в один tf-ресурс не укладываются.
---
## 2. Позиции участников (Telegram 2026-09-23)
| Кто | Позиция |
|---|---|
| **Владимир (наш)** | Пытается сделать всё терраформом. `create` — ок, `modify` — «просто так не получится, надо создавать дополнительные ресурсы-модификаторы». Сомневался: может, руками в ЛК или скриптом. |
| **Георгий** | **Основной запрос клиента — IaC.** Ручной ЛК/скрипт «совсем не подойдёт». Правильно указал порядок: сначала nsxt, потом квота на оргу. |
| **Дмитрий** | Хочет «terraform apply одного ямлика со всей инфрой — и всё». Спрашивал, как это реализовано в провайдере Cloud Director из провайдерской УЗ. |
| **Виталий** | Дал 3 tf-файла (`vmware_org.tf`, `vdc.tf`, `network.tf.tmpl`) — **официальный провайдер Cloud Director**. Ключевое: `ipSpace → providerGateway → providerVdc` (цепочка, которую юзер не знает), «квоту делаем через API на оргу, т.к. эджей много, а орга одна», «при создании параметры подкладываются», «в организации один T0». |
---
## 3. Подтверждённые факты (с источниками)
1. **Схема tf-ресурса строится ТОЛЬКО из `create`** (генератор `TOOLS/resource-generator`).
→ modify-only параметры в схему не попадают.
2. **`vIPConfigure`** (vc_org, modify id **207**, param id **662**, `array-map-fixed`, sub: `name`=39, `count`=40)
есть **только** в modify. В `create` (id 136) — только `resourceRealm`(418), `organizationType`(556), `orgSuffix`(1125).
Файл: `generated/dev/resources_yaml/19_vc_org.yaml`.
3. **`ipSpaceName`** (vc_nsxt, modify id **111**, param id **372**, string, required false) есть **только** в modify.
В `create` (id 10) — `vdcUid`, `needEnableAVI`(340), `virtualServicesCount`(341), `qosProfile`(825), `routedNetConfiguration`(1110).
Файл: `generated/dev/resources_yaml/22_vc_nsxt.yaml`.
4. **`vIPConfigure` — replace-семантика, НЕ накопительная.** Повторный modify с тем же count не задваивает (1→1),
работает вверх/вниз/до 0, `count=0` принимается (несмотря на `minvalue:1`), live читается из `state.params`.
Источник: `docs/ORG_IP_MODIFIER_TEST_2026-09-22.md` (проверено на стенде DEV_STAND/FullPipe, провайдер 2.0.9).
5. **`ipSpaceName` — выводимое значение:** цепочка `providerVdc → providerGateway → ipSpace`, юзер его не знает.
Платформа сейчас «подкладывает» недостающие параметры при создании пустой орги. Список доступных ipSpace
в статической выгрузке (`/instanceOperations/default/{id}`) — пустой, виден только в ЛК/живом инстансе. (Виталий + форензика)
6. **Допущение платформы: в организации один T0/провайдер-шлюз.** Рост T0 отложен, но при нём схема сломается.
7. **Доступ к значению modify-параметра:** live берётся из `GET /instances/{uid}` → `state.params`,
а НЕ из `cfsParams.paramValue` (это сохранённый дефолт формы от прошлых прогонов, см. `dtCreated` в HAR).
8. **Flow modify (HAR `org_enough_.har`):** `POST /instanceOperations {instanceUid, operation:"modify"}` →
`POST /instanceOperationCfsParams {paramValue, instanceOperationUid, svcOperationCfsParamId}` →
`POST /instanceOperations/{opUid}/validate-cfs` → `POST /instanceOperations/{opUid}/run`.
9. **Прецедент (VCD, папка `!/`):** та же цепочка делается **отдельными ресурсами** с `depends_on`:
`vcd_nsxt_alb_settings` (`count = var.alb_enable ? 1 : 0`), `vcd_nsxt_alb_edgegateway_service_engine_group`
(`reserved_virtual_services`), `vcd_network_routed_v2`, `vcd_ip_space_custom_quota` (на оргу).
Приём «включено/выключено» = существование ресурса; **inverse = удаление ресурса**.
10. **Nubes — надстройка над Cloud Director.** Наши `vcOrg`/`vcVdc`/`vcNsxt` создают объекты в VCD.
Провайдер Nubes — обёртка над API Nubes, отдельный от официального `terraform-provider-vcd`.
---
## 4. Почему «просто добавить поле» / «насильно в state» / «скрипт» — не работает
- **Добавить поле в .tf** → падает на `plan`: атрибута нет в схеме (см. §3.1).
- **Terraform не может внутри одного ресурса** сделать «create → через N шагов modify».
Декларативный Update требует **желаемого состояния**; `ipSpaceName` — это включение SNAT, а не значение поля.
- **Вписать в tfstate** нельзя: state валидируется по схеме провайдера, а «записанное» состояние ≠ реальность
(получишь чистый `plan` при сломанной инфраструктуре). `null_resource`/`terraform_data` + `local-exec` даёт
только **факт** выполнения, не состояние.
- **Ручной ЛК / скрипт вне tf** — отклонено: это не IaC (нет версионирования, воспроизводимости, дрейфа, отката).
- **Правка провайдера «по-старому»** (метки `kind: modifier` в YAML + реестр в `yaml-generator`) — **отменённый заход**,
см. §7.
---
## 5. Каноничное решение (что делать)
**Два независимых требования — нужны оба:**
1. **Отдельные tf-ресурсы под `modify`** (наша сторона): e.g. `nubes_org_ip_allocation` (vIPConfigure),
`nubes_nsxt_network` (`needEnableAVI`/`virtualServicesCount`/`ipSpaceName`/`routedNetConfiguration`),
привязка через `depends_on` к орге/эджу.
- `Read` = читать родителя (`state.params`), `Delete` = обратный modify (`count=0` / `needEnableAVI=false` /
`ipSpaceName="no-needed"`), `Create/Update` = `modify` с параметрами.
2. **Доступ к выводимым значениям через API** (сторона платформы): динамические `valueList` + цепочка
`providerVdc → providerGateway → ipSpace`. Иначе юзер подсматривает в ЛК (ручной ввод как временный долг допустим,
но поле надо делать `Optional+Computed`, чтобы позже включить автоподстановку без breaking change).
**Дизайн-требования, заложить сразу:**
- `ip_space_name` → `Optional + Computed`;
- optional селектор шлюза (`t0_id` / `provider_gateway`) — чтобы рост T0 не сломал схему;
- не тащить доменные метки в универсальный YAML (см. §7).
---
## 6. Что можно делать уже сейчас, не дожидаясь платформы
- **`vIPConfigure` (аллокация IP на оргу) — можно делать начисто**: блокеров нет, replace-семантика подтверждена тестом,
Read/Delete выражаются через `state.params` и `count=0`.
- **`needEnableAVI` / `virtualServicesCount`** — выразимы (есть и в create, и в modify).
- **`ipSpaceName`** — единственное, что упирается в платформу; временно — ввод юзером (значение он и так смотрит в ЛК).
- **`routedNetConfiguration`** — есть в create (1110) и modify (1112), выразимо.
**Не решено (требует решения до кода):**
- откуда генератор берёт **список** доменных ресурсов (это не данные API, а доменное знание — то самое место,
где раньше был реестр в `yaml-generator`). Форму выбрать осознанно: явный список vs отдельный вход.
- какие шаги вообще остаются на **провайдерском** (облачном) уровне, а какие отдаются тенанту
(квота ipSpace / ALB — возможно, это уровень облака, и тогда в клиентский tf они не входят).
---
## 7. ⚠️ Исправленные ошибки (НЕ повторять!)
1. **Ложный факт «`vIPConfigure` накопительный».** Был протащен в промпт для Opus как «подтверждённый», из-за чего
Opus построил вывод «накопительный API несовместим с декларативной моделью» и объявил два «блокера»
(Read счётчика, адресное освобождение). **Оба ложны** — тест `ORG_IP_MODIFIER_TEST_2026-09-22.md` доказывает
идемпотентность и работу в обе стороны. Документы исправлены.
2. **Прежняя repo-память (`modifier-gotchas.md`) содержала устаревшие утверждения** (эпоха 09-21/22):
`kind: modifier`, `delete_strategy`, `nubes_vc_nsxt_network`, «у vc_nsxt нет instance-modify»,
«Update = no-op». **Файл перезаписан** актуальными фактами. НЕ использовать старую формулировку.
3. **Старые «модификаторы» были написаны и даже работали** (09-22), но заход признан негодным:
доменную логику вшили в универсальный генератор (метки в YAML). Соответствующие документы помечены баннером LEGACY.
---
## 8. Карта файлов
**АКТУАЛЬНО (источник истины):**
- `docs/CHAT_RESUME_IAC_2026-09-24.md` ← этот файл
- `docs/SHTURVAL_IAC_MODIFY_ANALYSIS_2026-09-23.md` — анализ, варианты A–E, мнение
- `docs/OPUS_ANSWER_IAC_SHTURVAL_MODIFY_2026-09-23.md` — ответ Opus + поправки (ложные блокеры сняты)
- `docs/ORG_IP_MODIFIER_TEST_2026-09-22.md` — проверенные факты по vIPConfigure
- `docs/prompts/prompt_for_opus_iac_shturval_modify.md` — промпт (факты исправлены)
- `generated/dev/resources_yaml/19_vc_org.yaml`, `22_vc_nsxt.yaml` — спеки (факты по операциям/параметрам)
- `HAR/org_enough_.har`, `HAR/org2.har`, `HAR/edge_.har` — live-семантика modify
- `!/` — прецедент Cloud Director (3 файла `vcd_*`), НЕ наш код
**LEGACY (история, НЕ источник истины):**
- `PLAN_modifier_redesign.md` ⛔ (баннер добавлен)
- `docs/60_strategy/modifier_resources_ideology_and_specification.md` ⛔ (баннер добавлен)
- `docs/inverse_rollback_analysis_2026-09-23.md`
- `prompt_for_opus_modifier_global_architecture.md`, `prompt_for_opus_modifier_review_2.md` (корень)
- `docs/prompts/prompt_for_opus_modifier_*.md`, `docs/prompts/prompt_for_opus_modifiable_architecture.md`
- `HISTORY/OPUS/2026-09-22_modifier_*.md`
- `PLAN_regenerate_providers_0.0.1.md` — перекрыт `PLAN_FLASH_reversion_cleanup.md` (0.0.1 объявлен легаси)
> Примечание: `docs/ORG_IP_MODIFIER_TEST_2026-09-22.md` — **актуален** (это отчёт по проверке, не план).
**Инфра-контекст:**
- `TOOLS/config/<стенд>/profile.env` → `NUBES_API_ENDPOINT`, `TOKEN_FILE`
- `VERSIONS.md` — залитые версии (DEV на 09-22 = 2.0.13; в `generated/dev/provider_build/` лежат 2.0.17 — расхождение)
---
## 9. Развилка (ждёт решения)
| Вариант | Суть | Вердикт |
|---|---|---|
| **A** | Отдельные tf-ресурсы под modify (+ позже data-source для ipSpace) | канон; реализуемо сейчас для `vIPConfigure` |
| **B** | То же, но значения вводит юзер вручную | приемлемый временный долг при `Optional+Computed` |
| **C** | Ждать новых спеков платформы | часть работ всё равно можно начать сейчас |
| **D** | Ручной ЛК / скрипт вне tf | ❌ отклонено (требование IaC) |
| **E** | Пресеты/дефолтное окружение | снижает боль на старте, IaC не заменяет |
**Не принято:** делать ли `modify`-ресурсы доменными «руками» (и как их перечислять в генераторе) —
вопрос архитектуры; и что из шагов остаётся за облаком.
---
## 10. Открытые вопросы к людям
1. **Георгию/продукту:** какие шаги цепочки — тенантские, а какие — уровень облака (квота ipSpace, ALB)?
От этого зависит объём ресурсов в клиентском tf.
2. **Виталию (платформа):** можете отдавать через API (а) динамические списки значений (`ipSpace`),
(б) цепочку `providerVdc → providerGateway → ipSpace`?
3. **Виталию:** файлы `!/` — ваш инструмент провижининга от провайдерской УЗ или справочный пример?
(в диалоге он сказал только «это провайдер от клауд директора»)
4. **Команде:** откуда генератор берёт список доменных ресурсов-модификаций (форма решения, без меток в YAML).
@@ -0,0 +1,23 @@
# Резюме — tf_provider документация
## Сайты
- 5.1.2 (рабочий): https://registry.kube5s.ru <!-- ⛔ LEGACY: registry.kube5s.ru ЗАКРЫТ. Актуальный хост: tf-registry.containerk8s.services.ngcloud.ru --> <!-- ⛔ LEGACY: registry.kube5s.ru <!-- ⛔ LEGACY: registry.kube5s.ru ЗАКРЫТ. Актуальный хост: tf-registry.containerk8s.services.ngcloud.ru --> ЗАКРЫТ. Актуальный хост: tf-registry.containerk8s.services.ngcloud.ru -->/docs/nubes-test/nubes/5.1.2/
- 5.2.0 (мусор): удалить
## Генератор
TOOLS/bin/docs-generator -resources generated/test/resources_yaml -docs generated/test/docs -services TOOLS/config/test/services_list.txt -version "5.1.2" -api-endpoint "https://lk-api-gateway-test.ngcloud.ru/api/v1/svc"
## CSS
generated/test/docs/assets/extra.css — 1800px, синий/зелёный, без переносов
## Промпт
docs/prompt_deepseek_flash.txt — для DeepSeek Flash: MAN HTML→MD, русские заголовки, убрать br. НИЧЕГО не удалять.
## Сборка
python3 -m mkdocs build --config-file /tmp/mkdocs_clean.yml
## S3
mc cp --recursive generated/test/site/ "reg/terraform-registry/docs/nubes-test/nubes/5.1.2/"
## ЗАДАЧА
На 5.1.2: MAN HTML→Markdown + русские заголовки + убрать br. Параметры из API не трогать.
@@ -0,0 +1,72 @@
# Резюме + план действий (новый чат)
Дата: 2026-02-01
## Контекст
- Репозиторий: /home/naeel/terra
- Генератор провайдера: /home/naeel/terra/nubes_provider_gen
- Адрес провайдера (актуально): registry.kube5s.ru <!-- ⛔ LEGACY: registry.kube5s.ru ЗАКРЫТ. Актуальный хост: tf-registry.containerk8s.services.ngcloud.ru --> <!-- ⛔ LEGACY: registry.kube5s.ru <!-- ⛔ LEGACY: registry.kube5s.ru ЗАКРЫТ. Актуальный хост: tf-registry.containerk8s.services.ngcloud.ru --> ЗАКРЫТ. Актуальный хост: tf-registry.containerk8s.services.ngcloud.ru -->/nubes/nubes
- Registry S3 bucket: terraform-registry (endpoint s3.msk-1.ngcloud.ru)
- Dev override: /home/naeel/terra/test_persistent/dev_override.tfrc
## Что уже сделано
1) **VM ресурс сгенерирован**:
- YAML: /home/naeel/terra/nubes_provider_gen/resources_yaml/vm.yaml
- Go: /home/naeel/terra/nubes_provider_gen/internal/resources_gen/vm_resource.go
2) **Тестовая конфигурация**:
- /home/naeel/terra/test_persistent/main.tf
- Добавлен ресурс nubes_vm.test_vm (использует vapp_uid xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, образ Ubuntu_22-20G).
3) **Провайдер v2.0.0 собран и загружен в registry**:
- Артефакты в S3 по пути: s3://terraform-registry/registry.kube5s.ru <!-- ⛔ LEGACY: registry.kube5s.ru ЗАКРЫТ. Актуальный хост: tf-registry.containerk8s.services.ngcloud.ru -->/nubes/nubes/2.0.0/
- Файлы: terraform-provider-nubes_2.0.0_linux_amd64.zip, _SHA256SUMS, _SHA256SUMS.sig
4) **GPG ключ в наличии**:
- Key ID: FFE0F4D723F14BCA
5) **Токены**:
- Правило: имя файла = время окончания токена (HH-MM-SS). Последний: /home/naeel/terra/23-25-49.token
6) **Параметры VM**:
- vapp_uid найден в debug_vm/terraform.tfvars
## Текущие проблемы
- Terraform init без dev_override лезет в registry.kube5s.ru <!-- ⛔ LEGACY: registry.kube5s.ru ЗАКРЫТ. Актуальный хост: tf-registry.containerk8s.services.ngcloud.ru --> и может падать.
- Для apply нужны актуальные токены (401 были частые).
## План действий (VM)
1) **Проверить токен**:
- Убедиться, что в /home/naeel/terra/test_persistent/terraform.tfvars актуальный api_token.
- Если новый токен получен — сохранить его как /home/naeel/terra/HH-MM-SS.token (время exp). Обновить terraform.tfvars.
2) **Init/Apply через dev_override**:
- В /home/naeel/terra/test_persistent выполнить:
- TF_CLI_CONFIG_FILE=./dev_override.tfrc terraform init
- TF_CLI_CONFIG_FILE=./dev_override.tfrc terraform apply -auto-approve
3) **Создание VM**:
- Проверить, что nubes_vm.test_vm создаётся.
- Если TLS handshake timeout — повторять apply (как ранее с Postgres).
4) **Modify тесты (один инстанс)**:
- Менять параметры (vm_cpu / vm_ram / access_port_list / need_add_zabbix_template) последовательно.
- После каждого modify — apply, ждать завершения.
5) **Suspend/Resume**:
- delete_mode = "suspend", resume_if_exists = true
- terraform destroy -target nubes_vm.test_vm -auto-approve
- terraform apply -auto-approve (должен сделать resume)
6) **Если VM тесты не пройдут**:
- Тогда анализировать HAR в /home/naeel/terra/har/ (инструкции: сначала тесты, потом HAR).
## Важные файлы
- VM YAML: nubes_provider_gen/resources_yaml/vm.yaml
- VM Go: nubes_provider_gen/internal/resources_gen/vm_resource.go
- Test config: test_persistent/main.tf
- Token file: /home/naeel/terra/23-25-49.token (пример)
## Команды (шаблон)
- Build:
- cd /home/naeel/terra/nubes_provider_gen && go build -o terraform-provider-nubes
- Apply:
- cd /home/naeel/terra/test_persistent
- TF_CLI_CONFIG_FILE=./dev_override.tfrc terraform init
- TF_CLI_CONFIG_FILE=./dev_override.tfrc terraform apply -auto-approve