8.2 KiB
Паттерн создания ресурсов "Tubulus" (Platinum Standard)
В платформе Nubes Cloud большинство ресурсов (VDC, S3, DBaaS, Tubulus-болванки) подчиняются строгому 7-шаговому циклу создания. Простого POST /instances недостаточно — ресурс появится в UI, но останется в статусе "not created", пока не будет выполнен финальный POST /run.
Пошаговый алгоритм
Шаг 1: Инициализация (Create Instance)
Отправляем POST /instances.
- Payload:
contractId,serviceId,specificationItemId,displayName. - Результат: Получаем
instanceUid.
Шаг 2: Создание операции (Create Operation)
Отправляем POST /instanceOperations для привязки операции создания к инстансу.
- Payload:
instanceUid,operation: "create". - Результат: Получаем
instanceOperationUid.
Шаг 3: Получение параметров (Fetch Parameters)
Отправляем GET /instanceOperations/{uid}?fields=cfsParams.
- Цель: Получить список параметров (
svcOperationCfsParamId), которые платформа ожидает для этого ресурса.
Шаг 4: Отправка параметров (Submit Parameters) — Критично!
Для каждого параметра из списка (даже если он пустой или имеет значение по умолчанию) нужно отправить POST /instanceOperationCfsParams.
- Payload:
instanceOperationUid,svcOperationCfsParamId,paramValue. - Важно: Браузер всегда переотправляет все параметры. Пропуск этого шага может привести к ошибкам валидации.
Шаг 5: Валидация (Validate)
Отправляем GET /instanceOperations/{uid}/validate-cfs.
- Проверяем, что ответ
200 OKи нет ошибок в теле ответа.
Шаг 6: Запуск (Run) — Самый важный шаг!
Отправляем POST /instanceOperations/{uid}/run.
- Payload: Обязательно
{}(пустой JSON-объект). НЕnil, а именно{}. - Результат: После этого шага бэкенд начинает реальную работу (например, вызывает Jenkins или Ansible).
Шаг 7: Ожидание готовности (Polling)
Периодически опрашиваем GET /instances/{uid}.
- Ждем, когда
explainedStatusстанетrunning(для S3) илиActive.
Специфика S3 бакетов (nubes_s3_bucket)
- Модификация (Update): В текущем UI и API отсутствует операция
modify. Ресурс S3 является иммутабельным в плане параметров бакета через этот API. Для изменения (например, размера) требуется пересоздание или использование других API (если они будут найдены). - Удаление (Delete): Выполняется через стандартный
DELETE /instances/{id}. - Уникальность:
displayNameиbucket_nameдолжны быть уникальны в рамках контракта/платформы. Рекомендуется использовать суффиксы с временной меткой в тестах. - Placement: Допустимые значения:
HOT(по умолчанию) илиCOLD.
Рекомендации для разработчика провайдера
- Объединяйте шаги 1-6 в одну функцию клиента (например,
CreateInstanceвclient_impl.go). - Всегда передавайте пустую карту
map[string]interface{}{}в методRun, чтобы она сериализовалась в{}. - Тщательно логируйте
instanceOperationUid, так как по нему можно отследить ошибки в логах платформы.
Troubleshooting
- Висит в "not created": Вы забыли вызвать Шаг 6 (Run) или отправили неверный payload.
- Ошибка 400 на параметрах: Проверьте, что все ID параметров соответствуют результату из Шага 3.
Operation Lifecycle & Success Criteria (Official Developer Info)
Операции в Nubes Cloud выполняются асинхронно.
- 201 Created: Операция запущена успешно.
- Polling (GET status): Каждый запрос статуса возвращает
200 OK. Это означает, что платформа успешно обрабатывает запрос состояния, но не гарантирует успех самой операции. - Completion Timestamp: Операция считается завершенной только тогда, когда в ответе появляется временная метка завершения.
- isSuccessful: Ключевой флаг, который определяет успех операции и отрисовывает "зелёную галочку" в интерфейсе. Если операция завершена, но
isSuccessful: false, ресурс может находиться в неконсистентном состоянии.
Suspend/Resume и совпадение параметров (Discovery Notes)
Контекст: в Nubes Cloud многие сервисы не удаляются напрямую. destroy приводит к suspend и двухнедельному карантину. Это означает, что следующий apply может столкнуться с существующим инстансом в suspend.
Принцип восстановления
Если найден suspended инстанс с тем же resource_name, корректное поведение:
- Сравнить параметры в Terraform (create‑params) с
instance.state.params. - Resume выполнять только при полном совпадении параметров.
- При несовпадении — вернуть стандартную ошибку "resource already exists".
Потенциальные мины
- Несовпадение ключей:
state.paramsможет использовать ключи, отличные отcodeв YAML — сравнение даст false. - Типы/форматы: bool/int/JSON/масивы могут быть сериализованы по‑разному (строка vs JSON).
- Defaults: если параметр не задан в TF и приходит default от API, возможны ложные mismatches.
- RefSvcId: в create могут отправляться UUID, а в
state.paramsможет быть имя — mismatch. - Ручные изменения: любые правки вне TF делают resume невозможным.
- Пустые params: если API не возвращает
state.params, сравнение всегда провалится. - YAML/Go рассинхрон: неверный маппинг ID→code приводит к ложным mismatch.
- Сеть/таймауты: дополнительный GET
/instances/{id}может фейлиться и блокировать resume.
Экономический аспект
suspend сохраняет данные и продолжает потреблять дисковое пространство — пользователь продолжает платить. Регулярное создание новых инстансов вместо восстановления suspended приведёт к росту расходов.