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:
Repinoid
2026-09-24 07:51:25 +03:00
parent d93ff66482
commit 2d8e435dd4
59 changed files with 23 additions and 6 deletions
+373
View File
@@ -0,0 +1,373 @@
<!-- ⛔ LEGACY: deck-api.ngcloud.ru ЗАКРЫВАЕТСЯ. Актуальный API: lk-api-gateway.ngcloud.ru/api/v1/svc -->
# Матрица состояний ресурсов в облаке ngcloud
## Основные параметры состояния
### 1. В структуре инстанса (instance object)
Каждый ресурс имеет следующие флаги:
| Параметр | Тип | Возможные значения | Описание |
|----------|-----|------------------|---------|
| `explainedStatus` | string | `running`, (другие?) | Основной объяснительный статус |
| `isCreated` | boolean | `true`, `false` | Был ли инстанс создан |
| `isDeleted` | boolean | `true`, `false` | Отмечен ли как удаленный |
| `isSuspended` | boolean | `true`, `false` | Приостановлен ли |
| `operationIsInProgress` | boolean | `true`, `false` | Идет ли корректная операция |
| `operationIsPending` | boolean | `true`, `false` | Есть ли ожидающие операции |
| `uptime` | number | >= 0 | Время работы в секундах (0, если не создан) |
### 2. Структура state (instanceState object)
```json
{
"state": {
"instanceStateUid": "uuid",
"version": 1, // версия состояния
"dtState": "timestamp", // дата состояния
"isTest": boolean
}
}
```
### 3. Операции (operations array)
```json
{
"operation": "create|modify|delete|suspend|resume",
"dtSubmit": "timestamp",
"dtStart": null, // null если еще не началась
"dtFinish": null, // null если еще не закончилась
"isSuccessful": null|true|false, // null если не выполнялась
"isInProgress": boolean,
"isPending": boolean,
"submitResult": "201|..." // HTTP статус результата отправки
}
```
---
## МАТРИЦА СОСТОЯНИЙ
### ✅ СОСТОЯНИЕ: АКТИВНЫЙ РАБОЧИЙ ИНСТАНС (RUNNING)
```
isCreated=true
isDeleted=false
isSuspended=false
explainedStatus="running"
operationIsInProgress=false
operationIsPending=false
uptime > 0
state.version >= 1
```
**Значение:** Ресурс создан, работает, нет выполняющихся операций
---
### 🔄 СОСТОЯНИЕ: СОЗДАНИЕ В ПРОЦЕССЕ (CREATING)
```
isCreated=true (или может быть false на ранних стадиях)
isDeleted=false
isSuspended=false
operationIsInProgress=true
operationIsPending=false
state.version = 1
operations[0].operation = "create"
operations[0].isSuccessful = null (еще не завершено)
operations[0].dtStart != null
operations[0].dtFinish = null
```
**Значение:** Операция создания выполняется
---
### ⏸️ СОСТОЯНИЕ: ПРИОСТАНОВЛЕН (SUSPENDED)
```
isCreated=true
isDeleted=false
isSuspended=true
explainedStatus="suspended" (или может быть другое)
operationIsInProgress=false
```
**Значение:** Ресурс создан, но приостановлен (власт нет - suspend)
---
### ⏸️ СОСТОЯНИЕ: ПРИОСТАНОВКА В ПРОЦЕССЕ (SUSPENDING)
```
isCreated=true
isSuspended=false (еще не приостановлен)
operationIsInProgress=true
operations[last].operation = "suspend"
operations[last].isSuccessful = null
```
**Значение:** Операция приостановки выполняется
---
### ▶️ СОСТОЯНИЕ: ВОЗОБНОВЛЕНИЕ В ПРОЦЕССЕ (RESUMING)
```
isCreated=true
isSuspended=true (еще приостановлен)
operationIsInProgress=true
operations[last].operation = "resume"
operations[last].isSuccessful = null
```
**Значение:** Операция возобновления выполняется
---
### ❌ СОСТОЯНИЕ: НЕ СОЗДАН (NOT CREATED)
```
isCreated=false
isDeleted=false
isSuspended=false
state = null или пуст
uptime = 0
version = null или отсутствует
```
**Значение:** Ресурс был определен в коде, но никогда не создавался в облаке
---
### 🗑️ СОСТОЯНИЕ: УДАЛЕН (DELETED)
```
isDeleted=true
isCreated=true (был когда-то создан)
state.version может быть или не быть
```
**Значение:** Ресурс был удален, может оставаться в истории
---
### 🔄 СОСТОЯНИЕ: УДАЛЕНИЕ В ПРОЦЕССЕ (DELETING)
```
isCreated=true
isDeleted=false (еще не отмечен как удаленный)
operationIsInProgress=true
operations[last].operation = "delete"
operations[last].isSuccessful = null
```
**Значение:** Операция удаления выполняется
---
### 🔧 СОСТОЯНИЕ: ИЗМЕНЕНИЕ В ПРОЦЕССЕ (MODIFYING)
```
isCreated=true
isDeleted=false
operationIsInProgress=true
operations[last].operation = "modify"
operations[last].isSuccessful = null
```
**Значение:** Конфигурация ресурса изменяется
---
### ⏳ СОСТОЯНИЕ: ОПЕРАЦИЯ ОЖИДАЕТ (PENDING)
```
operationIsPending=true
operationIsInProgress=false
operations[last].dtStart = null (еще не началась, но создана)
operations[last].isSuccessful = null
```
**Значение:** Операция создана, но еще не началась (в очереди)
---
### ⚠️ СОСТОЯНИЕ: ОШИБКА ОПЕРАЦИИ (OPERATION_FAILED)
```
operations[last].isSuccessful=false
operations[last].dtFinish != null
operations[last].errorLog != null
operationIsInProgress=false
```
**Значение:** Последняя операция завершилась с ошибкой
---
### 🔀 СОСТОЯНИЕ: ГИБРИДНОЕ/ПЕРЕХОДНОЕ (HYBRID)
**Противоречивые комбинации указывают на переходное состояние:**
- `operationIsInProgress=true` + `operations[last].dtStart=null` → операция только создана, еще не началась
- `isCreated=true` + `operationIsPending=true` → есть ожидающая операция
- `state.version=null` + `isCreated=true` → некорректное состояние
---
## АЛГОРИТМ ОПРЕДЕЛЕНИЯ СОСТОЯНИЯ
### На уровне API (GET /api/v1/index.cfm/instances/{uid})
```python
def get_instance_state(instance_data):
"""
instance_data = {
'isCreated': bool,
'isDeleted': bool,
'isSuspended': bool,
'explainedStatus': str,
'operationIsInProgress': bool,
'operationIsPending': bool,
'uptime': float,
'state': {...} or null,
'operations': [...]
}
"""
# Шаг 1: Проверка удаления
if instance_data['isDeleted']:
return 'DELETED'
# Шаг 2: Проверка создания
if not instance_data['isCreated']:
return 'NOT_CREATED'
# Шаг 3: Проверка операции в процессе
if instance_data['operationIsInProgress']:
last_op = instance_data['operations'][-1] if instance_data['operations'] else None
if last_op:
operation_type = last_op.get('operation', 'unknown')
return f'{operation_type.upper()}_IN_PROGRESS'
# Шаг 4: Проверка ожидающей операции
if instance_data['operationIsPending']:
last_op = instance_data['operations'][-1] if instance_data['operations'] else None
if last_op and not last_op.get('dtStart'):
return 'OPERATION_PENDING'
# Шаг 5: Проверка приостановки
if instance_data['isSuspended']:
return 'SUSPENDED'
# Шаг 6: Проверка основного статуса
if instance_data['explainedStatus'] == 'running':
return 'RUNNING'
# Шаг 7: Проверка ошибок в операциях
if instance_data['operations']:
last_op = instance_data['operations'][-1]
if last_op.get('isSuccessful') == False:
return 'OPERATION_FAILED'
return 'UNKNOWN'
```
---
## РЕКОМЕНДУЕМЫЕ ЗАПРОСЫ К API
### Получить список ресурсов определенного типа
```bash
GET /api/v1/index.cfm/instances?fields=instanceConfigDtCreated,instanceUid,displayName,svc,uptime,explainedStatus,svcExtendedName,updaterLogin,updaterShortname,operationIsInProgress,operationIsPending,monitoringUrl&search={resource_name}&isAuxiliary=false&isDeleted=false
```
### Получить полную информацию о ресурсе
```bash
GET /api/v1/index.cfm/instances/{instance_uid}?fields=instanceConfigDtCreated,instanceUid,displayName,descr,svc,state,operations,availableOperations,uptime,isDeleted,updaterLogin,updaterShortname,explainedStatus,man,dependencies,dependentInstances,svcExtendedName
```
### Выполнить операцию
```bash
POST /api/v1/index.cfm/instanceOperations
Content-Type: application/json
{
"instanceUid": "uuid",
"operation": "create|modify|delete|suspend|resume"
}
```
### Получить статус операции
```bash
GET /api/v1/index.cfm/instanceOperations/{operation_uid}?fields=instanceOperationUid,instanceUid,state,stages,cfsParams,isSuccessful,dtCreated,dtUpdated,dtStart,dtFinish,operation,svcOperationId,svc,displayName,submitResult,duration,errorLog,updaterShortname,man,nestedRefData,isInProgress,isPending,dtSubmit
```
---
## ПРИМЕРЫ ИЗ HAR
### Пример 1: RUNNING инстанс
```json
{
"displayName": "Newly Added",
"isCreated": true,
"isDeleted": false,
"isSuspended": false,
"explainedStatus": "running",
"operationIsInProgress": false,
"operationIsPending": false,
"uptime": 1102.739073,
"state": {
"instanceStateUid": "48bfdbc5-e8fc-4286-8098-d6ab7f6de50e",
"version": 2
}
}
```
### Пример 2: CREATE_IN_PROGRESS инстанс
```json
{
"displayName": "ttst00",
"isCreated": true,
"isDeleted": false,
"isSuspended": false,
"explainedStatus": "running",
"operationIsInProgress": false,
"operationIsPending": true,
"uptime": 0,
"operations": [
{
"operation": "modify",
"dtSubmit": "2026-01-22T19:30:21.790+0300",
"dtStart": null,
"dtFinish": null,
"isSuccessful": null,
"isInProgress": false,
"isPending": true
}
]
}
```
### Пример 3: DELETE_IN_PROGRESS инстанс
```json
{
"displayName": "ttt0-terraform",
"isCreated": true,
"isDeleted": false,
"isSuspended": false,
"operations": [
{
"operation": "delete",
"dtSubmit": "2026-01-22T19:28:24.720+0300",
"dtStart": null,
"dtFinish": null,
"isSuccessful": null
}
]
}
```
---
## СВОДНАЯ ТАБЛИЦА ВОЗМОЖНЫХ СОСТОЯНИЙ
| Состояние | isCreated | isDeleted | isSuspended | operationIsInProgress | Описание |
|-----------|-----------|-----------|-------------|----------------------|---------|
| NOT_CREATED | false | false | false | false | Еще не создан |
| CREATING | true | false | false | true | Создание выполняется |
| RUNNING | true | false | false | false | Работает нормально |
| MODIFYING | true | false | false | true | Конфигурация изменяется |
| SUSPENDING | true | false | false | true | Приостановка выполняется |
| SUSPENDED | true | false | true | false | Приостановлен |
| RESUMING | true | false | true | true | Возобновление выполняется |
| DELETING | true | false | false | true | Удаление выполняется |
| DELETED | true | true | - | - | Удален |
| OPERATION_PENDING | true | false | - | false | Есть ожидающая операция |
| OPERATION_FAILED | true | false | - | false | Операция завершилась ошибкой |
+196
View File
@@ -0,0 +1,196 @@
<!-- ⛔ LEGACY: deck-api.ngcloud.ru ЗАКРЫВАЕТСЯ. Актуальный API: lk-api-gateway.ngcloud.ru/api/v1/svc -->
# Instance State Transitions - Матрица состояний инстансов ngcloud
Полное руководство по определению состояния инстансов через API ngcloud на основе комбинаций флагов и истории операций.
---
## 📊 Таблица состояний
| **Состояние** | `isCreated` | `isDeleted` | `isSuspended` | `operationIsInProgress` | `operationIsPending` | `isSuccessful` | Описание |
|---|---|---|---|---|---|---|---|
| **NOT_CREATED** | `false` | `false` | `false` | `false` | `false` | - | Ресурс в TF, но в облаке его нет |
| **CREATING** | `false` | `false` | `false` | `true` | `false` | - | Идет создание инстанса |
| **CREATION_FAILED** | `false` | `false` | `false` | `false` | `false` | `false` | ❌ Попытка создания завершилась ошибкой |
| **RUNNING** | `true` | `false` | `false` | `false` | `false` | `true` | ✅ Нормальное работающее состояние |
| **RUNNING_PENDING** | `true` | `false` | `false` | `false` | `true` | - | ✅ Работает, но в очереди ждет операция |
---
## 📊 Полная таблица состояний
| **Состояние** | `isCreated` | `isDeleted` | `isSuspended` | `operationIsInProgress` | `operationIsPending` | `isSuccessful` | Описание |
|---|---|---|---|---|---|---|---|
| **NOT_CREATED** | `false` | `false` | `false` | `false` | `false` | - | Ресурс в TF, но в облаке его нет |
| **CREATING** | `false` | `false` | `false` | `true` | `false` | - | Идет создание инстанса |
| **CREATION_FAILED** | `false` | `false` | `false` | `false` | `false` | `false` | ❌ Попытка создания завершилась ошибкой |
| **RUNNING** | `true` | `false` | `false` | `false` | `false` | `true` | ✅ Нормальное работающее состояние |
| **RUNNING_PENDING** | `true` | `false` | `false` | `false` | `true` | - | ✅ Работает, но в очереди ждет операция |
| **MODIFYING** | `true` | `false` | `false` | `true` | `false` | - | Идет изменение конфигурации |
| **MODIFICATION_FAILED** | `true` | `false` | `false` | `false` | `false` | `false` | ❌ Ошибка при изменении |
| **SUSPENDING** | `true` | `false` | `false` | `true` | `false` | - | Идет приостановка |
| **SUSPEND_FAILED** | `true` | `false` | `false` | `false` | `false` | `false` | ❌ Ошибка при приостановке |
| **SUSPENDED** | `true` | `false` | `true` | `false` | `false` | `true` | ⏸️ Приостановлен |
| **RESUMING** | `true` | `false` | `true` | `true` | `false` | - | Идет возобновление |
| **RESUME_FAILED** | `true` | `false` | `true` | `false` | `false` | `false` | ❌ Ошибка при возобновлении |
| **DELETING** | `true` | `false` | `false` | `true` | `false` | - | Идет удаление |
| **DELETION_FAILED** | `true` | `false` | `false` | `false` | `false` | `false` | ❌ Ошибка при удалении |
| **DELETED** | `true` | `true` | - | - | - | - | ❌ Удален |
| **ORPHANED** | `false` | `false` | - | - | - | `false` | ⚠️ История ошибок |
---
## 🔗 API Запросы для определения состояния
### Основной запрос к инстансу
```bash
curl -s -H "Authorization: Bearer $(cat /home/naeel/remote_dev/terraform/secrets/prod.token)" \
"https://deck-api.ngcloud.ru/api/v1/index.cfm/instances/{instanceUid}?fields=isCreated,isDeleted,isSuspended,operationIsInProgress,operationIsPending,operations,availableOperations,explainedStatus,uptime"
```
### Ответ API при CREATION_FAILED
```json
{
"instance": {
"instanceUid": "vcOrg-2402",
"displayName": "Организация в Cloud Director",
"isCreated": false,
"isDeleted": false,
"isSuspended": false,
"operationIsInProgress": false,
"operationIsPending": false,
"operations": [
{
"operation": "create",
"isSuccessful": false,
"errorLog": "Connection timeout to Cloud Director API",
"dtFinish": "2026-02-24T18:51:30+0300",
"duration": 80.5
}
],
"availableOperations": [
{"operation": "create"},
{"operation": "delete"}
]
}
}
```
---
## 🐍 Python функция определения состояния
```python
def get_instance_state(instance_data):
"""Определить состояние инстанса на основе ответа API"""
ic = instance_data.get('isCreated', False)
id = instance_data.get('isDeleted', False)
is_susp = instance_data.get('isSuspended', False)
is_in_prog = instance_data.get('operationIsInProgress', False)
is_pend = instance_data.get('operationIsPending', False)
ops = instance_data.get('operations', [])
# ПЕРВЫЙ ПРИОРИТЕТ: Проверить ошибки в последней операции
if ops and len(ops) > 0:
last_op = ops[0]
if last_op.get('isSuccessful') == False: # явное False
op_type = last_op.get('operation', 'unknown').upper()
return {
'state': f'{op_type}_FAILED',
'error': last_op.get('errorLog'),
'attempt_at': last_op.get('dtFinish'),
'can_retry': True
}
# Операции в процессе
if is_in_prog:
return {'state': 'OPERATING'}
# Ожидающие операции
if is_pend:
return {'state': 'RUNNING_PENDING'}
# Не создан
if not ic:
return {'state': 'NOT_CREATED'}
# Удален
if id:
return {'state': 'DELETED'}
# Приостановлен
if is_susp:
return {'state': 'SUSPENDED'}
# Работает
return {
'state': 'RUNNING',
'uptime': instance_data.get('uptime')
}
```
---
## 📋 Логика для Terraform Provider
### terraform apply
- **NOT_CREATED** → CreateInstance
- **RUNNING** + config_changed → ModifyInstance
- **CREATION_FAILED**, **MODIFICATION_FAILED** → Retry
- **OPERATING_*** → Wait
### terraform destroy
- **NOT_CREATED** → Skip
- **DELETED** → RemoveFromState
- **DELETION_FAILED** → Retry
- **Остальные** → DeleteInstance
---
## ⚠️ Критические комбинации
### 1. Инстанс не видно, но ошибка создания
```
isCreated=false + operations[0].isSuccessful=false + operation=create
= CREATION_FAILED
```
**Действие:**
- Проверить `errorLog` для деталей
- Использовать `availableOperations` для определения возможных действий
- Перепопытаться через create или удалить
### 2. Операция зависла
```
operationIsInProgress=true + duration > 3600 сек
= STUCK_OPERATION
```
**Действие:** Требует ручного вмешательства
### 3. Ошибка удаления (инстанс остался)
```
isDeleted=false + operations[0].operation=delete + isSuccessful=false
= DELETION_FAILED
```
**Действие:**
- Инстанс остается в облаке
- Перепопытаться delete или обратиться в поддержку
---
## 📖 Ссылки
- API: https://deck-api.ngcloud.ru/api/v1/
- Операции: create, modify, delete, suspend, resume
- Токен: /home/naeel/remote_dev/terraform/secrets/prod.token
@@ -0,0 +1,188 @@
# Universal Provider (ядро + генератор ресурсов) — подробный отчёт
Дата: 2026-01-31
## Цель
Нужна архитектура «универсального провайдера», где:
- есть **ядро** (общий клиент и универсальный флоу операций);
- есть **папка ресурсов** (Go-файлы ресурсов);
- есть **папка YAML-описаний сервисов** (чтобы DevOps мог добавить сервис одним файлом);
- есть **генератор**, который:
- читает YAML,
- генерирует ресурсы,
- генерирует реестр ресурсов,
- дальше выполняется build (ядро + ресурсы из папки).
В итоге: если файла ресурса нет — в провайдере его не будет. Если YAML изменён — перегенерация.
---
## Итоговая архитектура (v2.0.0, «голое» ядро + ресурсы)
Новая сборка размещена в:
- [nubes_provider_gen](nubes_provider_gen)
Структура:
- [nubes_provider_gen/internal/core](nubes_provider_gen/internal/core) — **ядро** (клиент, универсальный flow, запуск операций)
- [nubes_provider_gen/internal/provider](nubes_provider_gen/internal/provider) — **провайдер** (schema + клиент)
- [nubes_provider_gen/internal/resources_gen](nubes_provider_gen/internal/resources_gen) — **сгенерированные ресурсы** (Go)
- [nubes_provider_gen/resources_yaml](nubes_provider_gen/resources_yaml) — **YAML-описания сервисов**
- [nubes_provider_gen/tools/gen](nubes_provider_gen/tools/gen) — **генератор**
- [nubes_provider_gen/test_persistent](nubes_provider_gen/test_persistent) — тестовые манифесты
### 1) Ядро (core)
Файл: [nubes_provider_gen/internal/core/client.go](nubes_provider_gen/internal/core/client.go)
Содержит:
- `UniversalClient` с HTTP-клиентом и API endpoint/token.
- Универсальный flow **CreateGenericInstanceUniversalV6**:
1. POST /instances
2. POST /instanceOperations (create)
3. GET /instanceOperations/{opUid}?fields=cfsParams
4. POST /instanceOperationCfsParams (явные параметры)
5. POST /instanceOperationCfsParams (дефолтные/пустые для пропущенных)
6. GET /instanceOperations/{opUid}/validate-cfs
7. POST /instanceOperations/{opUid}/run
- Универсальные операции:
- `RunInstanceOperationUniversal` (delete/suspend/resume и т.д.)
- `RunInstanceOperationUniversalWithDefaults` (modify с автоподстановкой параметров)
- Утилиты:
- `FindInstanceByDisplayName`
- `GetInstanceState`
**Почему нужно WithDefaults для modify**
На modify требуются обязательные параметры (часто даже те, что не меняются). Без них backend падает.
### 2) Провайдер (provider)
Файл: [nubes_provider_gen/internal/provider/provider.go](nubes_provider_gen/internal/provider/provider.go)
- Тип провайдера: `nubes`
- Адрес: `terrareg.kube5s.ru/nubes/nubes`
- Ресурсы приходят из **реестра**:
- `resources_gen.AllResources()` — возвращает список функций создания ресурсов.
### 3) Генератор (tools/gen)
Файл: [nubes_provider_gen/tools/gen/main.go](nubes_provider_gen/tools/gen/main.go)
Функции:
- Читает все YAML-файлы в `resources_yaml/`
- Генерирует ресурсный Go-файл в `internal/resources_gen/` для каждого YAML
- Генерирует `registry.go` с `AllResources()`
То есть:
- **Добавили YAML → сгенерировали Go → build**
- Нет YAML → нет Go → нет ресурса
### 4) YAML-описания
Файл: [nubes_provider_gen/resources_yaml/dummy.yaml](nubes_provider_gen/resources_yaml/dummy.yaml)
Минимальная схема (пример dummy):
- `name`, `service_id`, `display_name_default`
- `create.params` — ID параметров create
- `modify.params` — ID параметров modify
- `lifecycle` — defaults для `adopt_existing_on_create` и `suspend_on_destroy`
---
## Что было сделано (конкретные шаги)
### Шаг 1. «Голое» ядро + генератор
Создан отдельный проект:
- [nubes_provider_gen](nubes_provider_gen)
Сделан core + provider + tools/gen + resources_yaml.
### Шаг 2. YAML для dummy
Создан YAML dummy: [nubes_provider_gen/resources_yaml/dummy.yaml](nubes_provider_gen/resources_yaml/dummy.yaml)
### Шаг 3. Генерация ресурсов
Команда:
- `go run ./tools/gen`
Сгенерированы:
- [nubes_provider_gen/internal/resources_gen/dummy_resource.go](nubes_provider_gen/internal/resources_gen/dummy_resource.go)
- [nubes_provider_gen/internal/resources_gen/registry.go](nubes_provider_gen/internal/resources_gen/registry.go)
### Шаг 4. Build
Команда:
- `go build -o terraform-provider-nubes`
### Шаг 5. Тесты dummy
Тестовый конфиг:
- [nubes_provider_gen/test_persistent/main.tf](nubes_provider_gen/test_persistent/main.tf)
- [nubes_provider_gen/test_persistent/dev_override.tfrc](nubes_provider_gen/test_persistent/dev_override.tfrc)
Проверены сценарии:
1. `apply` (create/adopt) — OK
2. `modify` (duration 750 → 820) — OK
3. `destroy` (`suspend_on_destroy = true`) — OK
4. `apply` после suspend (resume/adopt c явным `adopt_existing_on_create`) — OK
5. удаление ресурса из манифеста + `apply` — OK
6. возвращение ресурса в манифест + `apply` — OK
---
## Ошибки и как решались
### 1) `action modify not available`
Причина: в Update использовался `id` из `Plan` (неизвестен).
Решение: брать `id` из `State`.
### 2) `API error 400: Parameter specified does not belong to this operation`
Причина: неверные ID параметров modify.
Решение: для modify использовать `287/288` вместо `198/199`.
### 3) `API error 500: checkParam ... instanceOperationCfsParamUid` (повторно)
Причина: операция modify требует подстановки всех параметров; без них backend падает.
Решение:
- Добавлен `RunInstanceOperationUniversalWithDefaults` — читает `cfsParams` и заполняет недостающие
- Позже для dummy оказалось нужно отправлять **все** параметры (не только required)
### 4) `TLS handshake timeout`
Причина: VPN/сеть.
Решение: повторить команду.
### 5) `status 401`
Причина: токен истёк/невалидный.
Решение: заменить токен и сохранить по правилу `/home/naeel/terra/HH-MM-SS.token`.
### 6) Критерий завершения операции (важно)
Любая операция (create/modify/delete/suspend/resume) считается **завершённой**, когда у неё заполнено **время окончания**.
Это является признаком завершения **и успеха, и ошибки**. В UI и API ориентируемся на наличие `dtFinish`.
---
## Текущее состояние
- Провайдер «голый» + ресурсы из YAML работает.
- `dummy` полностью тестируется из YAML → Go → build.
- В `resources_gen` присутствует 1 ресурс: `nubes_dummy`.
---
## План (следующий шаг)
1) Расширить YAML-схему:
- поддержку дополнительных параметров (например, failInProgress, whereFail и т.п.)
- поддержку optional параметров с явными defaults
2) Добавить генерацию документации из YAML
3) Добавить проверку схемы YAML (валидация) перед генерацией
4) Скрипт "build pipeline":
- gen → registry → go build
5) Опционально: тестовый фреймворк для «batch» тестов
---
## Важные файлы
- Ядро: [nubes_provider_gen/internal/core/client.go](nubes_provider_gen/internal/core/client.go)
- Генератор: [nubes_provider_gen/tools/gen/main.go](nubes_provider_gen/tools/gen/main.go)
- Реестр: [nubes_provider_gen/internal/resources_gen/registry.go](nubes_provider_gen/internal/resources_gen/registry.go)
- YAML dummy: [nubes_provider_gen/resources_yaml/dummy.yaml](nubes_provider_gen/resources_yaml/dummy.yaml)
- Сгенерированный ресурс: [nubes_provider_gen/internal/resources_gen/dummy_resource.go](nubes_provider_gen/internal/resources_gen/dummy_resource.go)
- Тесты: [nubes_provider_gen/test_persistent/main.tf](nubes_provider_gen/test_persistent/main.tf)
---
## MAYDO (отложено до запроса заказчика)
- Добавить в YAML `outputs` (из `state/out`) и `state_params` (из `state/params`).
- Добавить `param_meta`: `valueList`, `func`, `refSvcId`, `dataDescriptor`.
- Добавить `secrets` (из `vault`) с пометкой чувствительных данных.
- Добавить `operations` (man/описания, доступные операции) для генерации доков.
- Добавить поддержку `subparams` (nested/list/json) и типизацию сложных структур.
- Добавить обработку версий операций (если API это отдаёт).
+14
View File
@@ -0,0 +1,14 @@
# ⛔⛔⛔ LEGACY — СТАРЫЕ API ЗАКРЫВАЮТСЯ ⛔⛔⛔
# НИКОГДА не использовать для генерации! Только для справки.
# Актуальные API:
# https://lk-api-gateway.ngcloud.ru/api/v1/svc (prod)
# https://lk-api-gateway-dev.ngcloud.ru/api/v1/svc (dev)
# https://lk-api-gateway-test.ngcloud.ru/api/v1/svc (test)
#
# === НИЖЕ — ЛЕГАСИ, НЕ ИСПОЛЬЗОВАТЬ ===
https://deck-api.ngcloud.ru/api/v1
https://deck-api-dev.ngcloud.ru/api/v1
https://deck-api-test.ngcloud.ru/api/v1