# 2026-07-16 — SubParams: map-fixed → nested Terraform attributes ## Контекст Генератор ресурсов не обрабатывал `map-fixed`/`array-map-fixed` параметры — они шли как `types.String`, пользователь был вынужден писать JSON руками. Теперь YAML содержит `sub_params` (получены через метод Виталия — `/instanceOperations/default/{id}` с `dataDescriptor`), и генератор раскрывает их во вложенные Terraform-блоки. ## Изменения (2026-07-16, ветка svc-api) ### Подготовка - Переход на Gateway API (`lk-api-gateway`) для всех стендов - Метод Виталия: `/instanceOperations/default/{id}` вместо `/serviceOperation/{id}` - YAML сгенерированы заново: dev=50, test=48, prod=46 - Списки сервисов обновлены из Gateway - DDoS-Guard: User-Agent + Referer для всех запросов - LEGACY-пометки на всех старых `deck-api` ### Размоноличивание templates.go - `templates.go` (1224 строки) → 3 файла: `instance.go`, `subresource.go`, `action.go` - Имена констант (`Instance`, `Subresource`, `Action`) не менялись ### Багфиксы lifecycle (Соннет) - **Баг A**: нет `HasError()` guard после диагностик в Create — сайд-эффект выполнялся вопреки ошибкам - **Баг B**: `not created` → авто-delete+create в crud.go противоречил философии (должен быть hard error) ### SubParams — вложенные Terraform-блоки **Изменённые файлы:** | Файл | Что | |------|-----| | `TOOLS/resource-generator/internal/types/types.go` | `SubParams []Param`, `IsNested bool` в `Param` | | `TOOLS/resource-generator/internal/loader/loader.go` | `ConvertParams` — рекурсивная конвертация SubParams; `NormalizeParamType` → `map-fixed`/`array-map-fixed` | | `TOOLS/resource-generator/internal/helpers/helpers.go` | 8 новых функций: `IsNested`, `IsNestedList`, `NestedModelName`, `NestedTfType`, `NestedSchemaType`, `NestedSchemaBlock`, `NestedSchemaEnd`, `NestedJSONExpr`, `SubSchemaType`, `SubDefaultExpr` | | `TOOLS/resource-generator/internal/templates/instance.go` | nested struct'ы перед Model, `SingleNestedAttribute`/`ListNestedAttribute` в Schema, `BuildJSON` в Create/Modify | | `TOOLS/resource-generator/internal/writers/writers.go` | 10 новых template-функций зарегистрировано | | `provider/internal/resources_core/helpers.go` | `BuildJSON(map[string]string) string` — строит JSON из map | **Что генерируется (пример postgres):** ```go // Вложенный struct type PostgresClusterConfigurationModel struct { Cpu types.Int64 `tfsdk:"cpu" json:"cpu"` Memory types.Int64 `tfsdk:"memory" json:"memory"` Replicas types.Int64 `tfsdk:"replicas" json:"replicas"` Disk types.Int64 `tfsdk:"disk" json:"disk"` } // В Model — указатель на nested struct ClusterConfiguration *PostgresClusterConfigurationModel `tfsdk:"cluster_configuration"` // В Schema — SingleNestedAttribute "cluster_configuration": schema.SingleNestedAttribute{Required: true, Attributes: map[string]schema.Attribute{ "cpu": schema.Int64Attribute{Optional: true, Computed: true, Default: int64default.StaticInt64(500)}, ... }, }, // В Create/Modify — JSON через BuildJSON params[788] = resources_core.BuildJSON(map[string]string{ "cpu": fmt.Sprintf("%d", data.ClusterConfiguration.Cpu.ValueInt64()), ... }) ``` **Для array-map-fixed** (postgresConf) — `ListNestedAttribute` + `[]Model`. ### Результаты генерации | Стенд | Go-файлов | |-------|-----------| | dev | 73 | | test | 70 | | prod | 65 | ### Подводные камни (учтены) - **Required + Default**: подполя с default → `Optional + Computed + Default` - **JSON-ключи**: `json:"cpu"` теги = оригинальный code (camelCase) - **types.* в JSON**: `BuildJSON` вместо `json.Marshal` (types.Int64 не маршалится как число) - **value_list**: enum-валидаторы — out of scope - **SubParams только для Instance**: subresource/action используют плоские параметры ### Версия 5.0.68 → 5.0.73