docs: убрать устаревшее «канонизация в plan-modifier» (совет Opus был неверен); план живого прогона FullPipe
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
# ПЛАН: живой прогон цепочки на DEV_STAND/FullPipe (2026-09-24)
|
||||
|
||||
> Стенд: dev, орга **`organ`** (`57eeacd1-dc7f-4a52-b903-7e5f7d3c1164`, realm `sandbox.nubes.ru`, тип `saas`,
|
||||
> CD-имя `WZ01325-saas`). Провайдер `2.0.19` (`terraform init -upgrade` уже сделан, `validate` — Success).
|
||||
> **`apply`/`destroy` запускает только пользователь.**
|
||||
|
||||
## 0. Что уже готово
|
||||
|
||||
- Ресурсы `nubes_vc_org_ip_allocation` (modify `vIPConfigure`) и `nubes_vc_nsxt_snat` (modify `ipSpaceName`) —
|
||||
в провайдере, собраны в `2.0.19`, залиты в `nubes-dev`, есть unit-тесты канонизации.
|
||||
- Конфиг стенда: `DEV_STAND/FullPipe/` — `vdc.tf`, `edge.tf`, `modifiers.tf` (аллокация после эджа, затем SNAT),
|
||||
`organization = "organ"` + `org_uid`.
|
||||
- Орга создана вручную (в tf её нет) — по решению пользователя.
|
||||
|
||||
## 1. Цель прогона
|
||||
|
||||
Проверить **одним `apply`**: `vdc → edge → IP на орге → SNAT`, затем чистый повторный `plan` и корректный
|
||||
`destroy`. Это первый живой прогон обоих новых ресурсов: CRUD до сих пор не проверялся.
|
||||
|
||||
## 2. Перед прогоном (проверить значения)
|
||||
|
||||
1. `vdc_network_provider` (`snb1`), `vdc_provider_vdc` (`Intel Broadwell 2.4`), `vdc_storage_config` (`SATA`) —
|
||||
убедиться в ЛК, что доступны для орги `organ` (значения брались из ЛК для прежней орги).
|
||||
2. `ip_space_name` — сначала может быть недоступен: **список ipSpace в ЛК падает** (`Can't cast Complex Object
|
||||
Type Struct to String`), пока нет vDC/эджа. Брать имя из прежних HAR: `internet-ipv4-v1`.
|
||||
3. `ip_count` — `"3"` (строка).
|
||||
|
||||
## 3. Шаги прогона (пользователь)
|
||||
|
||||
| # | Команда | Ожидаемый результат |
|
||||
|---|---|---|
|
||||
| 1 | `terraform plan` | создание: `nubes_vc_vdc.vdc` → `nubes_vc_nsxt.edge` → `nubes_vc_org_ip_allocation.org_ip` → `nubes_vc_nsxt_snat.snat`; порядка не меньше |
|
||||
| 2 | `terraform apply` | всё создаётся за один проход |
|
||||
| 3 | `terraform plan` (повторно) | **пустой** — главный тест канонизации (иначе вечный diff) |
|
||||
| 4 | проверить API (см. §4) | `vIPConfigure` и `ipSpaceName` в live-состоянии |
|
||||
| 5 | изменить `ip_count` 3 → 2, `plan`+`apply` | меняется только аллокация, state сходится |
|
||||
| 6 | `terraform destroy` | порядок `snat (no-needed)` → `org_ip (count=0)` → `edge` → `vdc`; орги не касается |
|
||||
|
||||
## 4. Что проверять и чем
|
||||
|
||||
```bash
|
||||
TOK=$(tr -d '\n' < secrets/narodDEV.token) # токен орги organ
|
||||
# состояние орги
|
||||
curl -s -H "Authorization: Bearer $TOK" 'https://lk-api-gateway-dev.ngcloud.ru/api/v1/svc/instances/<org_uid>'
|
||||
# состояние эджа
|
||||
curl -s -H "Authorization: Bearer $TOK" 'https://lk-api-gateway-dev.ngcloud.ru/api/v1/svc/instances/<nsxt_uid>'
|
||||
```
|
||||
|
||||
**Гипотезы, которые прогон подтверждает/опровергает:**
|
||||
|
||||
1. **Имена live-ключей**: `state.params.vIPConfigure` (орга) и `state.params.ipSpaceName` (эдж) — взяты из HAR,
|
||||
кодом не проверены. Если Read вернёт не то → увидим дрейф/пустое значение.
|
||||
2. **Частичный payload не затирает остальное**: SNAT-модификация шлёт только `372`; `needEnableAVI`
|
||||
и `virtualServicesCount` должны остаться прежними (`true` / `1`), т.к. досылаются из live
|
||||
(`core/operation_run_bycode.go`). Проверить в состоянии эджа до/после.
|
||||
3. **Один `apply`** проходит целиком без второго прогона (ради этого и делались ресурсы).
|
||||
4. **Нет вечного diff** после apply (канонизация `vip_configure`).
|
||||
5. **`Required` + пустое live** не даёт ошибок (лечение из ревью).
|
||||
|
||||
## 5. Точки отказа и что делать
|
||||
|
||||
| Симптом | Вероятная причина | Действие |
|
||||
|---|---|---|
|
||||
| аллокация падает `Can't cast ... Struct to String` | платформа ещё не видит `job.vcd.networkProvider`/`providerGateway` (эдж/VDC не в состоянии) | проверить порядок и фактическое состояние эджа; при необходимости — пауза/повторный `apply` |
|
||||
| `Provider produced inconsistent result after apply` на `vdc`/`edge` | read-back перекрыл план (известный класс дефектов) | записать в NOTES, разбирать отдельно (это уже не про наши ресурсы) |
|
||||
| повторный `plan` не пустой | порядок ключей/формат не сошлись | сверить, что вернул live, с `formatVipConfigure` |
|
||||
| SNAT не включился | `372` не доехал / неверное имя ipSpace | проверить `state.params.ipSpaceName` эджа и лог операции |
|
||||
| `destroy` падает | обратный modify на живой/мёртвый родитель | смотреть тексты диагностик ресурсов (мы развели: ошибка API ≠ «родителя нет») |
|
||||
|
||||
## 6. После прогона
|
||||
|
||||
1. Отчёт в `NOTES/30_analysis/` — что прошло, что упало, с HAR/логами.
|
||||
2. Обновить память репозитория (подтверждённые факты вместо гипотез).
|
||||
3. Если найдутся баги — отдельные коммиты + при необходимости новый релиз провайдера.
|
||||
4. Публикация документации (`04_build_and_publish_docs.sh`) — отдельной командой.
|
||||
|
||||
**Не входит в этот прогон:** кластер Штурвал (`nubes_k8s_shturval_cluster`) — отдельным шагом, после того как
|
||||
SNAT подтверждён.
|
||||
@@ -808,14 +808,24 @@ func (m jsonNormalizePlanModifier) PlanModifyString(_ context.Context, req planm
|
||||
(только destroy) — **задокументировать** в описании атрибута.
|
||||
- Раздел 3 (риски живой платформы) без прогона не закрывается — остаётся открытым.
|
||||
|
||||
## Требуется сделать (по итогам ревью) — ВЫПОЛНЕНО (коммиты `ba6c4f5`, `4b497e6`, `1236c59`)
|
||||
## Итог по ревью: что сделано и где ревью ошиблось
|
||||
|
||||
1. ✅ Заменить `JsonNormalize()` на канонизирующий plan-modifier (`parse → formatVipConfigure`) —
|
||||
закрывает баг порядка ключей (в т.ч. для `jsonencode`).
|
||||
2. ✅ Убрать запись `null` в `Required`-атрибуты (`vip_configure`, `ip_space_name`) — при пустом live
|
||||
сохраняется текущее значение state (проверка «что отправили — то и в state»).
|
||||
3. ✅ `Delete`: ошибки API → `AddError`; warning оставлен только для отсутствующего родителя.
|
||||
4. ✅ `setSnat`: вместо тихой подмены — валидация пустой строки.
|
||||
**⚠️ Совет Opus (вариант «б», канонизация в plan-modifier) — НЕВЕРЕН.** Plan-modifier не имеет права
|
||||
менять значение пользовательского атрибута: Terraform отвечает
|
||||
`Provider produced invalid plan: planned value does not match config value`.
|
||||
Это правило описано в нашем же сгенерированном коде (`22_vc_nsxt_resource.go`, комментарий в `ModifyPlan`).
|
||||
Проверено живым `terraform plan` 2026-09-24 (ошибка воспроизведена).
|
||||
|
||||
Правильное решение (коммит `807dfde`):
|
||||
- plan-modifier удалён полностью (`JsonNormalize` тоже снят — он компактит, то есть тоже менял бы значение);
|
||||
- в `Read` — смысловое сравнение `vipAllocationsEqual`: если смысл совпал (порядок ключей/формат не важны),
|
||||
значение пользователя НЕ переписывается; пишется только реальный дрейф.
|
||||
|
||||
**Выполнено корректно:**
|
||||
1. ✅ Убран plan-modifier, менявший пользовательское значение; сравнение — смысловое (коммит `807dfde`).
|
||||
2. ✅ `null` в `Required`-атрибуты не пишется — при пустом live сохраняется текущее значение state.
|
||||
3. ✅ `Delete`: ошибки API → `AddError`; warning только для отсутствующего родителя.
|
||||
4. ✅ `setSnat`: валидация пустой строки вместо тихой подмены на `no-needed`.
|
||||
5. ✅ Задокументировано: «снять всё» через `vip_configure` нельзя, только `destroy`.
|
||||
6. ✅ Поправлены/добавлены тесты канонизации (`jsonencode`-форма, пробелы, `[{}]`, невалидный JSON).
|
||||
7. ⏳ Новый релиз провайдера (2.0.19) с повторной заливкой в `nubes-dev`.
|
||||
6. ✅ Тесты: смысловое сравнение (порядок ключей, разный count/имя, пустая аллокация).
|
||||
7. ⚠️ Релиз `2.0.19` залит, но **содержит сломанный plan-modifier** — для работы из реестра нужен `2.0.20`.
|
||||
|
||||
Reference in New Issue
Block a user