docs: повышение читаемости provider-behavior.md (упрощены §1 списком, §2 модификаторы, §3 id/нормализация, §5 приоритет флагов, §6 ALB-константы)

This commit is contained in:
Nail
2026-09-24 20:53:17 +03:00
parent aaf87d966b
commit c808a3b345
+22 -15
View File
@@ -8,29 +8,34 @@
Провайдер Nubes — это не плагин к гипервизору, а **обёртка над API личного кабинета**: каждый Terraform-ресурс
соответствует *инстансу услуги* в облаке, а `create` / `update` / `delete` транслируются в **асинхронные операции**
платформы (`create`, `modify`, `suspend`, `resume`, `delete`). Отсюда все отличия: долгие операции с поллингом,
изменение вместо пересоздания, ошибки внутри тела ответа, идентичность ресурса по имени и возможность
«мягкого» удаления.
платформы (`create`, `modify`, `suspend`, `resume`, `delete`). Отсюда и все отличия от привычного Terraform:
- операции **долгие** — провайдер ждёт их завершения (поллинг);
- меняется **уже созданный объект**, а не создаётся заново;
- ошибки приходят **внутри тела ответа**, а не HTTP-кодом;
- ресурс ищется **по имени**, а не только по `id`;
- удаление может быть **«мягким»** — объект остаётся в облаке.
## 2. Какие ресурсы за что отвечают
| Услуга облака | Ресурс Terraform | Что делает |
|---|---|---|
| Организация в Cloud Director (19) | `nubes_vc_org_ip_allocation` | **модификатор**: меняет квоту внешних IP в уже существующей организации (саму организацию создают в ЛК) |
| Организация в Cloud Director (19) | `nubes_vc_org_ip_allocation` | **модификатор**: меняет квоту внешних IP в организации (саму организацию создают в ЛК, Terraform её не трогает) |
| Виртуальный датацентр (21) | `nubes_vc_vdc` | создаёт vDC с ресурсами (CPU/RAM/Storage) |
| Сетевой шлюз периметра (22) | `nubes_vc_nsxt` | создаёт Edge (routed-сеть, ALB/AVI) |
| Сетевой шлюз периметра (22) | `nubes_vc_nsxt_snat` | **модификатор**: включает/переключает SNAT (`ipSpaceName`) на существующем Edge |
| Kubernetes кластер Штурвал (150) | `nubes_k8s_sthutrval_cluster` | создаёт кластер (control plane + группы воркеров) |
Общее правило: **создаёт** только «инстансный» ресурс услуги, а всё остальное, что делается операцией `modify`
(квота IP, SNAT, свойства шлюза), — это отдельные ресурсы-модификаторы со своим жизненным циклом.
Общее правило. Ресурс, у которого есть свой «объект в облаке», **создаёт** этот объект. А то, что платформа
меняет операцией `modify` (квота IP, включение SNAT, настройки шлюза), собрано в отдельные ресурсы-
**модификаторы**: они не создают ничего нового, а правят уже существующий объект.
## 3. Отличия от «учебного» Terraform
| Ожидание по канону | Как в Nubes | Причина |
|---|---|---|
| `create` = один вызов API | Создание инстанса — **последовательность**: `POST /instances` → `POST /instanceOperations` → параметры (`instanceOperationCfsParams`) → `run` → поллинг до `dtFinish` | Так устроен API платформы |
| `id` — произвольная строка | `id` = UUID инстанса в облаке; чтение — из `instance.state.params` / `state.out` | Состояние живёт в облаке, не в Terraform |
| `id` — произвольная строка | `id` = UUID инстанса в облаке; провайдер читает его из ответа платформы | Состояние живёт в облаке, не в Terraform |
| `update` = замена при несовместимых параметрах | `update` = операция **`modify`** над тем же инстансом; часть параметров — **create-only** (менять нельзя → ошибка на этапе plan) | Платформа не пересоздаёт объекты «из коробки» |
| есть `data sources` для поиска существующего | Поиск/ссылки — через **ref-параметры**: можно указать UUID **или имя** инстанса | Экономит data sources, но требует дисциплины в значениях |
| `import` — явная команда | Плюс к `import` есть **авто-усыновление** `adopt_existing_on_create = true`: ресурс сам находит инстанс **по имени** | В проде объекты живут неделями, и пересоздавать их нельзя |
@@ -38,7 +43,7 @@
| `delete` удаляет | `delete` может быть `delete` / `suspend` / `state_only` — см. §5 | У платформы не всё удаляется, а часть объектов удалять нельзя, пока жив потребитель |
| ошибка приходит HTTP-кодом | Ошибка операции — **в теле**: `isSuccessful=false` + `errorLog`, при успешном HTTP-коде | API платформы отвечает 200/201 почти всегда |
| операции быстрые | Операции асинхронные и долгие (Штурвал — десятки минут) → параметр `operation_timeout`; одновременные операции на одном инстансе не поддерживаются | Наследство платформы (внутри — CFS-оркестратор) |
| план обязан совпадать с config | Тоже, но с оговоркой: **ref-параметры в плане не нормализуются** (нельзя подменить `name` → `uuid`), нормализация только перед вызовом API | Иначе Terraform упадёт с «Provider produced invalid plan» |
| план обязан совпадать с config | Тоже, но: **ref-параметры в плане остаются как написаны** (`name` не подменяется на `uuid`), а уже перед вызовом API провайдер сам разберётся, имя это или UUID | Иначе Terraform упадёт с «Provider produced invalid plan» |
| параметры сравниваются как строки | JSON-параметры сравниваются **канонично**: порядок ключей и пробелы не важны, скаляры приводятся к строке, UUID — без учёта регистра | API возвращает JSON в своём виде, иначе будет «вечный diff» |
| идентичность — по `id` | Дополнительно: инстанс ищется по `resource_name` (displayName) → **переименование = новый ресурс** | Имя задаётся при создании и не меняется |
@@ -70,11 +75,12 @@
| Флаг | Где применим | Поведение при `destroy` | Предупреждение в выводе |
|---|---|---|---|
| `suspend_on_destroy = true` | кластер Штурвала, vDC (по умолчанию `true`) | объект **приостанавливается**, не удаляется | «Ресурс заморожен, а не удалён» |
| `keep_on_destroy = true` | Edge, SNAT, квота IP (по умолчанию `false`) | объект **не трогается в облаке**, только убирается из state | «Ресурс оставлен как есть, а не удалён» / «SNAT не выключался» / «Аллокация IP не снималась» |
| `keep_on_destroy = true` | Edge, SNAT, квота IP (по умолчанию `false`) | объект **не трогается в облаке**, только убирается из state | «Оставлен как есть» (для SNAT — «SNAT не выключался», для квоты IP — «Аллокация IP не снималась») |
| оба `false` | любой | обычное удаление | — |
Приоритет: `keep_on_destroy` важнее `suspend_on_destroy`. Дефолты провайдера — **разрушающие**
(`keep_on_destroy = false`), «заморозку» включают явно в конфигурации стенда.
Если выставлены оба флага, победит `keep_on_destroy` (объект просто не тронут). По умолчанию провайдер
удаляет по-настоящему (`keep_on_destroy = false`), а «заморозку» или «оставить как есть» включают явно
в конфигурации стенда.
### Почему Edge остаётся `running`
@@ -117,7 +123,8 @@ Edge **физически не умеет `suspend`**: в списке дост
1. Организация — **вручную в ЛК** (Terraform её не создаёт).
2. `nubes_vc_vdc` — виртуальный датацентр.
3. `nubes_vc_nsxt` — Edge; обязательно с ALB (`need_enable_avi = true`) и `virtual_services_count >= 3`.
3. `nubes_vc_nsxt` — Edge. Обязательно включать балансировщик (параметр `need_enable_avi = true`)
и задать не меньше 3 виртуальных сервисов (`virtual_services_count >= 3`) — это нужно кластеру Штурвала.
4. `nubes_vc_org_ip_allocation` — внешние адреса в организации (минимум 3 по инструкции услуги Штурвала).
5. `nubes_vc_nsxt_snat` — SNAT на Edge (по `depends_on` после аллокации адресов).
6. `nubes_k8s_sthutrval_cluster` — кластер Штурвала (по `depends_on` после SNAT: нодам нужен выход в интернет).
@@ -129,9 +136,9 @@ Edge **физически не умеет `suspend`**: в списке дост
- Edge не удаляется при живых зависимых объектах (по инструкции услуги).
- Квота IP не опускается ниже занятых адресов (см. §5).
Практическая проверка корректности конфигурации: `terraform plan` после `apply` должен говорить
`No changes`. Если появляется стабильный diff — сравнивайте не «на глаз», а по `terraform state show`
и состоянию инстанса в ЛК.
Как проверить, что конфигурация корректна: `terraform plan` после `apply` должен говорить
`No changes`. Если появляется стабильный diff — сверяйте его с `terraform state show` и с тем,
что реально показывается в личном кабинете.
## 7. Регистр UUID и канонизация значений