chore: save current changes
This commit is contained in:
@@ -9,3 +9,8 @@
|
||||
НИКОГДА НЕ ПРЕВЫШАЙ СВОИ ПОЛНОМОЧИЯ !!!
|
||||
ВСЕГДА СОБЛЮДАЙ БЕЗОПАСНОСТЬ И КОНФИДЕНЦИАЛЬНОСТЬ !!!
|
||||
НИКОГДА НЕ ПЕРЕДАВАЙ СЕКРЕТЫ ИНТЕРНЕТУ БЕЗ РАЗРЕШЕНИЯ !!!
|
||||
НЕ ВЫЗЫВАТЬ ДРУГИЕ АГЕНТЫ БЕЗ РАЗРЕШЕНИЯ !!!
|
||||
коммитить после каждой правки, чтобы зафиксировать текущее состояние и избежать потери изменений. Использовать осмысленные сообщения коммитов, отражающие суть изменений.
|
||||
ВСЕГДА СОХРАНЯТЬ РЕЗЕРВНЫЕ КОПИИ ВАЖНЫХ ФАЙЛОВ ПЕРЕД ВНЕСЕНИЕМ ИЗМЕНЕНИЙ.
|
||||
НИКОГДА НЕ ПОЛАГАЙСЯ НА ПАМЯТЬ — ВСЕГДА ПРОВЕРЯЙ АКТУАЛЬНОСТЬ ИНСТРУКЦИЙ.
|
||||
ВСЕГДА СОБЛЮДАЙ ИНСТРУКЦИИ, ДАВАЙТЕ ПОДТВЕРЖДЕНИЯ И НЕ ДЕЛАЙТЕ САМОСТОЯТЕЛЬНЫХ ИЗМЕНЕНИЙ.
|
||||
@@ -1,3 +1,8 @@
|
||||
> ⛔ **LEGACY / НЕ ИСТОЧНИК ИСТИНЫ (помечено 2026-09-24).**
|
||||
> Этот план относится к отменённому заходу (метки `kind: modifier` в YAML + реестр в `yaml-generator`).
|
||||
> Актуальное состояние и выводы: `docs/CHAT_RESUME_IAC_2026-09-24.md`,
|
||||
> `docs/SHTURVAL_IAC_MODIFY_ANALYSIS_2026-09-23.md`, `docs/OPUS_ANSWER_IAC_SHTURVAL_MODIFY_2026-09-23.md`.
|
||||
|
||||
# ПЛАН реализации: редизайн ресурсов-модификаторов (kind: modifier)
|
||||
|
||||
Основа: `HISTORY/OPUS/2026-09-22_modifier_architecture_project.md`.
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
> ⛔ **LEGACY / НЕ ИСТОЧНИК ИСТИНЫ (помечено 2026-09-24).**
|
||||
> Идеология отменённого захода (метки `kind: modifier` в YAML, реестр модификаторов в `yaml-generator`,
|
||||
> `delete_strategy`/`inverse` как механизм генератора). Сохранена как история.
|
||||
> Актуальное: `docs/CHAT_RESUME_IAC_2026-09-24.md`.
|
||||
|
||||
# Архитектурная концепция: Modifier-ресурсы (Идеология, правила и интеграция в Terraform Provider)
|
||||
|
||||
## 1. Введение и архитектурный контекст
|
||||
|
||||
@@ -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).
|
||||
@@ -5,6 +5,8 @@
|
||||
**Связанный анализ:** `docs/SHTURVAL_IAC_MODIFY_ANALYSIS_2026-09-23.md`
|
||||
**Статус:** документирование ответа. Конкретный план НЕ составляется.
|
||||
|
||||
> ⚠️ **ВАЖНАЯ ПОПРАВКА (2026-09-23, позже).** Ответ Опуса ниже строился на НЕВЕРНОЙ посылке «`vIPConfigure` — накопительный API». Это опровергнуто тестом `docs/ORG_IP_MODIFIER_TEST_2026-09-22.md`: `vIPConfigure` ведёт себя как **replace-состояние** — идемпотентно (1→1), работает в обе стороны (вверх/вниз/до 0), `count` читается из `state.params`. Соответственно «блокеры» (a) Read счётчика и (b) адресное освобождение **сняты как ложные**. Остаётся только (c) Read цепочки `providerVdc → providerGateway → ipSpace`. НЕ использовать прежнюю формулировку «накопительный API несовместим с декларативной моделью» как источник истины.
|
||||
|
||||
---
|
||||
|
||||
## 1. Суть ответа (главный вывод)
|
||||
@@ -26,7 +28,7 @@
|
||||
- **Update:** та же дельта-логика (target изменился → доначислить/освободить).
|
||||
- **Delete (inverse):** `modify` с обратным знаком до `count=0` по этому `name`. Требует адресного освобождения конкретных IP. Если освобождение — тоже накопительный modify без адресации, inverse корректно сделать нельзя.
|
||||
|
||||
**Риск:** накопительный API без «прочитать текущее» и без «освободить конкретное» несовместим с декларативной моделью. Чинится на стороне платформы, не провайдера.
|
||||
**Риск (ОПРОВЕРГНУТ позже):** это утверждение строилось на ложной посылке «накопительный API». Факт: `vIPConfigure` — replace-состояние, дельта `target − current` по факту не нужна — достаточно слать целевой `count`, платформа сама выставляет его (идемпотентно). См. `ORG_IP_MODIFIER_TEST_2026-09-22.md`.
|
||||
|
||||
### Пункт 2 — `ipSpaceName` (цепочка providerVdc → providerGateway → ipSpace)
|
||||
|
||||
@@ -47,20 +49,21 @@
|
||||
|
||||
- **Форму ресурсов можно и нужно фиксировать сейчас** — она диктуется моделью Terraform, а не спеками.
|
||||
- **Не блокер (делаем сейчас):** раздельные ресурсы + `depends_on`; целевое состояние вместо дельты; селектор шлюза; data-source для `ipSpaceName`; inverse через обратный modify.
|
||||
- **Блокер (нужно от платформы):**
|
||||
- a) чтение текущего числа vIP по `name` (иначе нет Read/идемпотентности);
|
||||
- b) адресное освобождение IP (иначе нет корректного Delete);
|
||||
- **Блокер (нужно от платформы) — только один подтверждённый:**
|
||||
- c) API чтения цепочки providerVdc → providerGateway → ipSpace (иначе data-source невозможен).
|
||||
- **Вывод:** проектируем форму сейчас, помечаем a/b/c как зависимости от платформы. Новые спеки повлияют на **резолвинг значений**, не на форму ресурсов — если форма построена на «целевое состояние + селектор + data-source».
|
||||
- **Сняты как ложные (опровергнуты тестом 2026-09-22):**
|
||||
- a) чтение текущего числа vIP — УЖЕ работает через `state.params.vIPConfigure`;
|
||||
- b) адресное освобождение IP — УЖЕ работает: `count` меньше/`0` задаётся тем же `modify`, в обе стороны.
|
||||
- **Вывод:** проектируем форму сейчас, блокер только (c). Новые спеки повлияют на **резолвинг значений**, не на форму ресурсов — если форма построена на «целевое состояние + селектор + data-source».
|
||||
|
||||
### Пункт 5 — минимально-инвазивный порядок внедрения
|
||||
|
||||
**От платформы (до кодинга ресурсов) — обязательно:**
|
||||
- Read-эндпоинт: текущее количество vIP по `name` (для идемпотентности/Read).
|
||||
- Освобождение конкретных vIP (для Delete/inverse).
|
||||
- Read цепочки → `ipSpaceName` (для data-source).
|
||||
- Подтверждение, что генератор умеет строить схему из объединения `create`+`modify` полей (иначе `vIPConfigure`/`ipSpaceName` вообще не попадут в схему).
|
||||
|
||||
> ⚠️ Read счётчика vIP и адресное освобождение — НЕ блокеры (уже подтверждено тестом). Исключены.
|
||||
|
||||
**На стороне провайдера — можно сейчас, не дожидаясь:**
|
||||
- Раздельные ресурсы vip-allocation / nsxt-snat с `depends_on`.
|
||||
- Логика «target − current = дельта» (заглушка current, пока нет Read).
|
||||
@@ -68,7 +71,7 @@
|
||||
- Optional+computed селектор шлюза.
|
||||
- Inverse-контракт (Delete = обратный modify до нуля).
|
||||
|
||||
**Главный неустранимый на нашей стороне блокер:** накопительный API без чтения текущего состояния и без адресного освобождения. Без этого идемпотентность и Delete принципиально недостижимы. Правится в спеках/API платформы, а не в провайдере.
|
||||
**Главный неустранимый на нашей стороне блокер:** ❌ СНЯТ — строился на ложной посылке «накопительный API». Реальный остаточный блокер — только (c) чтение цепочки providerVdc → providerGateway → ipSpace (для data-source `ipSpaceName`).
|
||||
|
||||
---
|
||||
|
||||
@@ -87,29 +90,33 @@
|
||||
2. **`ipSpaceName` — data-source, не аргумент ресурса** — сдвиг от «юзер вписывает значение» к «computed-from-parent». Раньше виделось как ввод.
|
||||
3. **Селектор шлюза (`t0_id`/`provider_gateway`) как optional+computed сейчас** — в старых планах про «один T0» вообще не было (пришло только из реплики Виталия).
|
||||
4. **Чёткая граница «данные vs логика»** — в реестре только «тип поля + что computed-from-parent», цепочка обхода — логика data-source.
|
||||
5. **Три конкретных блокера от платформы** как API-требования (Read счётчика, адресное освобождение, Read цепочки) — раньше это было «unknown, проверить», теперь жёсткий список.
|
||||
5. **Блокеры от платформы** — из трёх заявленных Опуса два (Read счётчика, адресное освобождение) **ложны** (опровергнуты тестом), остаётся один реальный: Read цепочки providerVdc→providerGateway→ipSpace.
|
||||
|
||||
### Главное отличие одной фразой
|
||||
|
||||
Старые планы отвечали на «**как сделать модификатор в tf**». Опус отвечает на «**как сделать его идемпотентным и IaC-честным при накопительном API и скрытых зависимостях**» — и выявил, что ядро проблемы не в провайдере, а в платформе (Read счётчика + адресное освобождение + Read цепочки).
|
||||
Старые планы отвечали на «**как сделать модификатор в tf**». Опус отвечает на «**как сделать его идемпотентным и IaC-честным**» — но его центральный вывод «ядро проблемы в платформе (накопительный API)» **оказался ошибочным**, т.к. исходная посылка «накопительный» неверна (см. поправку в шапке). Реальный остаток — только `ipSpaceName` (цепочка providerVdc→providerGateway→ipSpace) и селектор шлюза.
|
||||
|
||||
---
|
||||
|
||||
## 4. Спорный/непроверенный момент (требует живой проверки)
|
||||
## 4. Спорный/непроверенный момент — РАЗРЕШЁН
|
||||
|
||||
Опус утверждает: накопительный `vIPConfigure` без Read-счётчика и без адресного освобождения «несовместим с декларативной моделью».
|
||||
Посылка Опуса «накопительный `vIPConfigure` без Read-счётчика и адресного освобождения несовместим с декларативной моделью» **опровергнута** тестом `docs/ORG_IP_MODIFIER_TEST_2026-09-22.md`:
|
||||
|
||||
Проверено частично: из HAR (`org2.har`, `org_enough_.har`) видно, что live `vIPConfigure` с `count` читается (это уже потенциально «Read текущего числа»). Значит блокер (a) — чтение счётчика — возможно, уже закрыт.
|
||||
- повторный `modify` с тем же `count` не аккумулирует IP (1→1) → идемпотентно;
|
||||
- `count` меняется в обе стороны (2→1→0) через тот же `modify` → «адресное освобождение» не нужно, достаточно задать меньший/нулевой `count`;
|
||||
- `count=0` принимается (несмотря на `minvalue:1` в схеме), элемент ipSpace остаётся в `state.params`;
|
||||
- Read уже есть: `state.params.vIPConfigure = [{"name":"internet-ipv4-v1","count":N}]`.
|
||||
|
||||
НЕ проверено: умеет ли API **адресно освободить** конкретный `name`/`count` (откат), или освобождение тоже накопительное. Это блокер (b), и его надо проверить живым API, прежде чем принимать вывод Опуса за окончательный.
|
||||
Единственный реально непроверенный момент: полное удаление ipSpace (`[]` / отсутствие элемента) — тест этого не покрывал. Для IaC-задачи «обнулить» достаточно, полное удаление — опционально.
|
||||
|
||||
---
|
||||
|
||||
## 5. Резюме
|
||||
## 5. Резюме (с поправкой)
|
||||
|
||||
- Форма ресурсов — проектируем сейчас, она не зависит от спеков.
|
||||
- Три блокера платформы: Read счётчика vIP, адресное освобождение, Read цепочки ipSpace.
|
||||
- Из трёх блокеров (a) частично подтверждён HAR-дампами; (b) и (c) — непроверены.
|
||||
- `vIPConfigure` — **НЕ блокер**: идемпотентно, обе стороны, `count` читается/задаётся из `state.params` (тест 2026-09-22).
|
||||
- Единственный подтверждённый блокер: **Read цепочки `providerVdc → providerGateway → ipSpace`** для data-source `ipSpaceName` (c).
|
||||
- Непроверено: полное удаление ipSpace (`[]`), но для задачи достаточно `count=0`.
|
||||
- Конкретный план внедрения пока НЕ составляется (по решению пользователя).
|
||||
|
||||
**Следующий возможный шаг (только по запросу):** проверить живым API блокеры (b) адресное освобождение и (c) чтение цепочки, после чего фиксировать, что реально блокирует, а что уже закрыто.
|
||||
**Следующий возможный шаг (только по запросу):** проверить (c) чтение цепочки ipSpace живым API.
|
||||
|
||||
@@ -45,7 +45,7 @@ k8sShturval -> create
|
||||
|
||||
### 2.2. Эти параметры — не «настройки», а отложенные действия
|
||||
|
||||
- `vIPConfigure=[{name,count}]` — транзакция «выделить N внешних IP» на ресурсной платформе. Повторный вызов **накапливает** (аккумулирует квоту), а не задаёт состояние. Это не декларативное значение.
|
||||
- `vIPConfigure=[{name,count}]` — задаёт желаемое число внешних IP целиком. **Не накопительная** (повторный вызов с тем же `count` не аккумулирует, подтверждено `docs/ORG_IP_MODIFIER_TEST_2026-09-22.md`), работает в обе стороны (вверх/вниз/до `count=0`). Это **декларативное значение** в смысле «желаемое количество IP по данному ipSpace».
|
||||
- `ipSpaceName` — включение SNAT на конкретный ipSpace, который возникает **только после** того, как на орге выделены IP.
|
||||
- Эти операции требуют порядка (org.modify → затем nsxt.modify) и зависят от живого состояния инстанса, а не от дефолтов формы.
|
||||
|
||||
@@ -166,4 +166,4 @@ providerVdc → никто не знает изначально
|
||||
|
||||
**Рекомендация:** не городить модификатор сейчас по устаревшим спекам. Дождаться изменений спеков (сначала sandbox), параллельно — обсчитать два blockers: (1) как провайдер будет резолвить `providerVdc → providerGateway → ipSpace` без ручного ввода; (2) допущение «один T0». После этого проектировать форму ресурсов.
|
||||
|
||||
**Что точно не делать:** вписывать параметры «насильно» в tfstate; дёргать `modify` через скрипт на каждый apply без live-сверки (накопит `vIPConfigure`); ждать, что «прописал поле в tf → apply» заработает без правки провайдера.
|
||||
**Что точно не делать:** вписывать параметры «насильно» в tfstate; ждать, что «прописал поле в tf → apply» заработает без правки провайдера. (`vIPConfigure` при этом НЕ накопительный — см. §2.2, тест 2026-09-22.)
|
||||
|
||||
@@ -27,7 +27,7 @@ k8sShturval -> create
|
||||
- Провайдер генерируется из YAML-спеков. Схема tf-ресурса строится ТОЛЬКО из операции `create`.
|
||||
- `vIPConfigure` (array-map-fixed, sub: name/count) есть только в `modify` vc_org (id 207); в `create` (136) его нет.
|
||||
- `ipSpaceName` (string) есть только в `modify` vc_nsxt (id 111); в `create` (10) его нет.
|
||||
- `vIPConfigure` — накопительный: повторный `modify` выделяет IP заново, а не задаёт состояние.
|
||||
- `vIPConfigure` — **не накопительный, а replace-семантика** (подтверждено `docs/ORG_IP_MODIFIER_TEST_2026-09-22.md`): повторный `modify` с тем же `count` не аккумулирует IP (1→1), работает в обе стороны (вверх/вниз/до 0), `count=0` принимается. Значение задаётся целиком, читается из `state.params`.
|
||||
- `ipSpaceName` выводится из цепочки `providerVdc -> providerGateway -> ipSpace`, которую пользователь не знает. Сейчас платформа «подкладывает» недостающие параметры при создании пустой орги.
|
||||
- Допущение платформы: в организации один T0/провайдер-шлюз. Рост числа T0 отложен.
|
||||
- Платформа в движении: форма ресурсов зависит от новых спеков (ждут, придут сначала в sandbox).
|
||||
@@ -38,7 +38,7 @@ k8sShturval -> create
|
||||
|
||||
## Вопросы
|
||||
|
||||
1. Как корректно выразить накопительный `vIPConfigure` идемпотентным tf-ресурсом (чтобы повторный apply не выделял IP заново)? Как устроить Read и Delete (inverse: обнулить count), если отдельного API-объекта нет?
|
||||
1. `vIPConfigure` уже ведёт себя как replace-состояние (идемпотентно, обе стороны, `count=0` читается из `state.params`). Как это оформить в tf-ресурсе, чтобы Read брал `state.params`, а Delete (inverse) выставлял `count=0` — если отдельного API-объекта нет?
|
||||
|
||||
2. Как провайдер должен получать выводимое значение `ipSpaceName` (цепочка providerVdc → providerGateway → ipSpace): data-source, вычисляемое из state родителя, или иное? Где граница «данные vs логика», что хранить в реестре, что выводить из типа/state?
|
||||
|
||||
|
||||
Reference in New Issue
Block a user