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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user