Files
tf_provider/docs/inverse_rollback_analysis_2026-09-23.md
T

54 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Inverse-откат модификаторов: анализ ответа Опуса — 2026-09-23
Источник: prompt_for_opus_inverse_architecture.md → ответ Опуса (принят, анализ ниже).
## Принятые решения (по Опусу)
1. **Модель delete_params** → заменить плоский `{Code, Value}` на `{Code, Mode, Value?}`:
- `Mode: static` — значение из `Value` (дефолт, обратная совместимость).
- `Mode: zero_count` — обнулить integer-поля в элементах array-map-fixed, взяв live.
2. **Баланс данные/логика**: форма преобразования выводится из `dataType`
(boolean→"false", array-map-fixed→zero integer); сентинелы-значения — ТОЛЬКО данные в реестре.
3. **Маркер поля**: явный `zero_fields:["count"]` (или флаг на sub_param), а НЕ «обнулить все integer»
(риск: порт/приоритет/индекс в том же object).
4. **Порядок destroy** — обратный порядок создания из `depends_on`.
## Мои замечания к ответу (что Опуc недоговорил)
- **A. Граф уже правильный.** Факт: `edge_net` (SNAT) зависит от `org_ips` (IP), `org_ips` — от `edge`.
Обратный порядок destroy: `edge_net → org_ips → edge → vdc` уже корректен.
Рекомендация Опуса «сделать ip_space зависимым от edge_net» — перепутана направлением; граф уже такой.
- **B. Источник live для zero_count в Delete не указан.** `Delete` модификатора имеет только TF `state`,
а live `vIPConfigure` надо читать через `GetInstanceStateParams` в рантайме Delete.
- **C. Отличие sentinel от имени в valueList не разобрано** (valueList без разметки sentinel в данных API).
- **D. Идемпотентность zero_count при повторном destroy не поднята** (count=0 → снова 0: no-op?).
## Открытые вопросы (второй раунд к Опусу) — ЗАКРЫТЫ
1. **Источник live для zero_count в Delete** → `GetInstanceStateParams` (не TF state). ✅
2. **Sentinel в valueList** → явный `off_value:"no-needed"` в реестре (данные, не логика). ✅
3. **Идемпотентность zero_count** → пропускать `run`, если live уже `count=0` (применимо и к static). ✅
4. **count=0** → канонический inverse; полное удаление ipSpace = отдельный опциональный `Mode:remove` (не подменять zero_count). ✅
## ИТОГ — финальная модель inverse
`delete_params: []{ Code, Mode, Value?, zero_fields?, off_value? }`
- `Mode: static` — обратное значение = `Value` (boolean→"false"; string→off_value).
- `Mode: zero_count` — взять live array-map-fixed, обнулить поля из `zero_fields:["count"]`.
- `Mode: remove` (опц., не для FullPipe) — полное удаление элемента.
Рантайм: Delete → `GetInstanceStateParams` → построить inverse → если live уже целевое → no-op (skip run) → иначе `modify`.
Реестр (yaml-generator main.go):
- `vc_org.ip_space`: `inverse`, param `vIPConfigure` `Mode:zero_count, zero_fields:[count]`.
- `vc_nsxt.network`: `inverse`, params `needEnableAVI`=static `"false"`, `ipSpaceName`=static off_value `"no-needed"`.
Порядок destroy (уже корректен в .tf): `edge_net → org_ips → edge → vdc`.
## Факты (не менять, проверено)
- `count=0` принимается API (minvalue:1 в схеме — не отвергает), идемпотентно (ORG_IP_MODIFIER_TEST_2026-09-22).
- SNAT off = `ipSpaceName="no-needed"` (sentinel в valueList, HAR_SNAT_MODIFY_FINDINGS).
- `needEnableAVI` boolean → inverse `"false"`.
- vc_org.ip_space: `error` → нужен `inverse` (zero_count). vc_nsxt.network: inverse+static `needEnableAVI=false`, добавить `ipSpaceName="no-needed"`.