From 65b78f2a783120ff0c548462fd5be75607fd2ac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Sun, 19 Jul 2026 10:45:22 +0400 Subject: [PATCH] =?UTF-8?q?fix:=20resolve=20s3Uid=20name=E2=86=92UUID=20fo?= =?UTF-8?q?r=20uuid=20sub-params=20inside=20map-fixed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TEST_STAND/LUCEE/{resources.tf => lucee.tf} | 26 +++++--- TEST_STAND/LUCEE/main.tf | 12 ++-- TEST_STAND/LUCEE/nubes_postgres_lucee.tf | 3 +- TEST_STAND/POSTGRES/main.tf | 2 +- TOOLS/ARCHITECTURE.md | 4 ++ TOOLS/config/dev/profile.env | 2 +- TOOLS/config/prod/profile.env | 2 +- TOOLS/config/test/profile.env | 2 +- provider/internal/core/client.go | 71 ++++++++++++++++++++- 9 files changed, 102 insertions(+), 22 deletions(-) rename TEST_STAND/LUCEE/{resources.tf => lucee.tf} (82%) diff --git a/TEST_STAND/LUCEE/resources.tf b/TEST_STAND/LUCEE/lucee.tf similarity index 82% rename from TEST_STAND/LUCEE/resources.tf rename to TEST_STAND/LUCEE/lucee.tf index 8aacfc8..56a562d 100644 --- a/TEST_STAND/LUCEE/resources.tf +++ b/TEST_STAND/LUCEE/lucee.tf @@ -1,9 +1,24 @@ resource "nubes_lucee" "app1" { resource_name = "lucy_0" - resource_realm = var.realm - domain = "tflucee" - git_path = "https://github.com/xahys/testlucee" + startup_configuration = { + resource_realm = var.realm + } + + cluster_configuration = { + cpu = 300 + memory = 512 + replicas = 1 + } + + access_configuration = { + domain = "tflucee" + } + + app_configuration = { + version = "5.4" + git_path = "https://github.com/xahys/testlucee" + } json_env = jsonencode({ # 🔗 Настройки Data Source 'testds' для Lucee (Application.cfc) @@ -31,10 +46,5 @@ resource "nubes_lucee" "app1" { ) }) - resource_c_p_u = 300 - resource_memory = 512 - resource_instances = 1 - app_version = "5.4" - depends_on = [nubes_postgres.npg_lucee] } diff --git a/TEST_STAND/LUCEE/main.tf b/TEST_STAND/LUCEE/main.tf index e72bf42..f8c0ed7 100644 --- a/TEST_STAND/LUCEE/main.tf +++ b/TEST_STAND/LUCEE/main.tf @@ -2,7 +2,7 @@ terraform { required_providers { nubes = { source = "registry.kube5s.ru/nubes-test/nubes" - version = "5.1.3" + version = "5.1.7" } } } @@ -12,11 +12,11 @@ variable "api_token" { sensitive = true description = "Nubes API token" } -variable "s3_uid" { - type = string - sensitive = true - description = "Nubes S3 UID" -} +# variable "s3_uid" { +# type = string +# sensitive = true +# description = "Nubes S3 UID" +# } variable "realm" { type = string sensitive = true diff --git a/TEST_STAND/LUCEE/nubes_postgres_lucee.tf b/TEST_STAND/LUCEE/nubes_postgres_lucee.tf index ba14808..2bd619a 100644 --- a/TEST_STAND/LUCEE/nubes_postgres_lucee.tf +++ b/TEST_STAND/LUCEE/nubes_postgres_lucee.tf @@ -32,7 +32,8 @@ resource "nubes_postgres" "npg_lucee" { }]) backup_configuration = { - s3_uid = var.s3_uid + s3_uid = var.s3_name + # s3_uid = var.s3_uid retain = 14 schedule = "0 0 * * *" } diff --git a/TEST_STAND/POSTGRES/main.tf b/TEST_STAND/POSTGRES/main.tf index 1271438..2643c7c 100644 --- a/TEST_STAND/POSTGRES/main.tf +++ b/TEST_STAND/POSTGRES/main.tf @@ -2,7 +2,7 @@ terraform { required_providers { nubes = { source = "registry.kube5s.ru/nubes-test/nubes" - version = "5.1.6" + version = "5.1.7" } } } diff --git a/TOOLS/ARCHITECTURE.md b/TOOLS/ARCHITECTURE.md index a4de1fa..238c1ea 100644 --- a/TOOLS/ARCHITECTURE.md +++ b/TOOLS/ARCHITECTURE.md @@ -126,6 +126,10 @@ Each operation has a kind: `dataDescriptor` для `map-fixed`-параметра, а значение отсутствует или равно `"{}"`, строится JSON из дефолтов sub-параметров (`{"type":"off","durationCA":"175200",...}`). Это гарантирует что API получит все обязательные sub-поля с их значениями по умолчанию. +- **s3Uid-резолв в map-fixed** (`resolveRefSvcParamValues`): для map-fixed-параметров + с `DataDescriptor`, содержащих uuid sub-params с именем по паттерну `s3.*uid`, + значения-не-UUID резолвятся в UUID через S3 (сервис 12). Позволяет использовать + displayName вместо UUID для S3-ссылок во всех сервисах (Postgres, MariaDB, Clickhouse). - **modify всегда через WithDefaults** (`RunInstanceOperationUniversalWithDefaults`): modify-операции запрашивают `cfsParams` у API и отправляют все параметры, включая новые, с дефолтами из API. diff --git a/TOOLS/config/dev/profile.env b/TOOLS/config/dev/profile.env index fd367ae..29f7385 100644 --- a/TOOLS/config/dev/profile.env +++ b/TOOLS/config/dev/profile.env @@ -4,7 +4,7 @@ TOKEN_FILE="secrets/dev.token" # Release versions # Version -VERSION="3.1.5" +VERSION="3.1.6" # Registry/S3 settings REGISTRY_HOST="registry.kube5s.ru" diff --git a/TOOLS/config/prod/profile.env b/TOOLS/config/prod/profile.env index 2cbdcee..f9b7bc0 100644 --- a/TOOLS/config/prod/profile.env +++ b/TOOLS/config/prod/profile.env @@ -4,7 +4,7 @@ TOKEN_FILE="secrets/prod.token" # Release versions # Version -VERSION="2.1.4" +VERSION="2.1.5" # Registry/S3 settings REGISTRY_HOST="registry.kube5s.ru" diff --git a/TOOLS/config/test/profile.env b/TOOLS/config/test/profile.env index 7239311..0023328 100644 --- a/TOOLS/config/test/profile.env +++ b/TOOLS/config/test/profile.env @@ -3,7 +3,7 @@ NUBES_API_ENDPOINT="https://lk-api-gateway-test.ngcloud.ru/api/v1/svc" TOKEN_FILE="secrets/test.token" # Version -VERSION="5.1.7" +VERSION="5.1.8" # Docs generation — ONLY from docs_gen// (never from docs/) DOCS_GEN_DIR="provider/docs_gen/test" diff --git a/provider/internal/core/client.go b/provider/internal/core/client.go index 40eb7ad..e3e6c48 100644 --- a/provider/internal/core/client.go +++ b/provider/internal/core/client.go @@ -1195,7 +1195,6 @@ func (c *UniversalClient) resolveRefSvcParamValues(ctx context.Context, opParams newValue := value if refSvcId, ok := refById[paramId]; ok { if strings.TrimSpace(value) == "" { - // Опциональный ref-параметр не задан — оставляем пустым newValue = "" } else if !isUUIDLike(value) { uid, err := c.findInstanceUidByDisplayNameRefSvc(ctx, refSvcId, value) @@ -1207,10 +1206,11 @@ func (c *UniversalClient) resolveRefSvcParamValues(ctx context.Context, opParams } newValue = uid } else { - // FIX(uuid-case): UUID-like value passed directly — normalise to lowercase. - // Аналогично refSvcId==12: нормализуем для API, регистр восстановится в state. newValue = strings.ToLower(value) } + } else if strings.TrimSpace(value) != "" { + // map-fixed: резолвим s3Uid-подобные uuid sub-params внутри JSON. + newValue = c.resolveS3UidInMapFixed(paramId, value, opParams) } resolved[paramId] = newValue } @@ -1218,6 +1218,71 @@ func (c *UniversalClient) resolveRefSvcParamValues(ctx context.Context, opParams return resolved, nil } +// resolveS3UidInMapFixed парсит JSON map-fixed-параметра, находит uuid sub-params +// с именем по паттерну s3.*uid и резолвит значения-не-UUID в UUID через S3 (сервис 12). +func (c *UniversalClient) resolveS3UidInMapFixed(paramId int, jsonValue string, opParams []universalCfsParam) string { + // Найти DataDescriptor для этого параметра + var dd map[string]universalSubParam + for _, p := range opParams { + if p.SvcOperationCfsParamId == paramId && len(p.DataDescriptor) > 0 { + dd = p.DataDescriptor + break + } + } + if len(dd) == 0 { + return jsonValue + } + + // Найти uuid sub-params с s3.*uid в имени + s3uidKeys := make(map[string]bool) + re := strings.ToLower + for key, sub := range dd { + lowKey := re(key) + lowSub := re(sub.SvcOperationCfsSubparam) + if (strings.Contains(lowKey, "s3") && strings.Contains(lowKey, "uid")) || + (strings.Contains(lowSub, "s3") && strings.Contains(lowSub, "uid")) { + if strings.Contains(re(sub.DataType), "uuid") { + s3uidKeys[key] = true + } + } + } + if len(s3uidKeys) == 0 { + return jsonValue + } + + // Парсим JSON + var obj map[string]interface{} + if err := json.Unmarshal([]byte(jsonValue), &obj); err != nil { + return jsonValue + } + + changed := false + for key, val := range obj { + if !s3uidKeys[key] { + continue + } + strVal, ok := val.(string) + if !ok || strVal == "" || isUUIDLike(strVal) { + continue + } + uid, err := c.findInstanceUidByDisplayNameRefSvc(context.Background(), 12, strVal) + if err != nil || uid == "" { + continue + } + obj[key] = uid + changed = true + } + + if !changed { + return jsonValue + } + b, err := json.Marshal(obj) + if err != nil { + return jsonValue + } + return string(b) +} + func (c *UniversalClient) findInstanceUidByDisplayNameRefSvc(ctx context.Context, serviceId int, displayName string) (string, error) { // Собираем ВСЕ совпадения, затем выбираем лучшее (running > suspended > остальные). // Deleted инстансы пропускаются — они не должны участвовать в resolve.