fix(Q5): сохранять instanceUid при ошибке после создания + partial state

Проблема: CreateGenericInstanceUniversalV6 при ЛЮБОЙ ошибке после создания инстанса
возвращал "", а шаблон Create при ошибке не писал ID в state => облачный инстанс
осиротевал (Terraform о нём не знает, повторный apply упирается в страж дубликатов).

- core/instance_create.go: ошибки после получения instanceUid возвращают uid вместе
  с ошибкой (POST /instanceOperations, пустой opUid, разбор cfsParams, resolve,
  отправка параметров, validate, run, waitForOperationFinish, ensureInstanceCreated).
  До создания uid — по-прежнему "".
- templates/instance.go: при err != nil и id != "" -> data.ID + resp.State.Set (partial
  state), затем AddError.
- client_test.go: TestCreateGenericInstance_KeepsUIDWhenOperationCreateFails,
  TestCreateGenericInstance_EmptyUIDWhenInstanceCreateFails.
- ARCHITECTURE.md: пункт про partial state.

Проверено: 02 (dev) + dev-materialize -> 40 файлов resources_gen содержат фикс;
go build ./... OK; go test ./internal/... -short PASS.
This commit is contained in:
Repinoid
2026-09-30 20:53:14 +03:00
parent 54f036e228
commit 9da97663c6
4 changed files with 70 additions and 11 deletions
+5
View File
@@ -131,6 +131,11 @@ Each operation has a kind:
### Generated Code Resilience
- **Partial state при ошибке create** (шаблон `instance.go`): если инстанс успел создаться
(`CreateResourceWithTimeout` вернул непустой uid ВМЕСТЕ с ошибкой), uid фиксируется в state
до вывода ошибки. Иначе облачный инстанс «осиротеет»: Terraform о нём не знает, а повторный
`apply` упрётся в страж дубликатов. Ядро (`CreateGenericInstanceUniversalV6`) возвращает uid
при любой ошибке ПОСЛЕ создания инстанса; пустой uid — только если создание не состоялось.
- **Zero-value fallback** (`normalizeUniversalValueV6`): если параметр отсутствует
в пользовательском `.tf`, подставлять zero-value по `dataType`:
- `integer` → `"0"`, `boolean` → `"false"`, `map-fixed` → `"{}"`, `array` → `"[]"`, `string` → `""`
@@ -313,6 +313,13 @@ func (r *{{ToCamel .Name}}Resource) Create(ctx context.Context, req resource.Cre
}
id, err := resources_core.CreateResourceWithTimeout(ctx, r.client, {{.ServiceID}}, resourceName, data.AdoptExistingOnCreate.ValueBool(), params, operationTimeout)
if err != nil {
// Partial state (Q5): если инстанс успел создаться (id != ""), фиксируем его в state.
// Иначе облачный инстанс «осиротеет»: Terraform о нём не знает, а повторный apply
// упрётся в страж дубликатов. Read затем сверит/очистит состояние.
if id != "" {
data.ID = types.StringValue(id)
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
resp.Diagnostics.AddError("Ошибка клиента", err.Error())
return
}