resource-generator: SubParams → nested SingleNestedAttribute/ListNestedAttribute + bump 5.0.73

This commit is contained in:
“Naeel”
2026-07-16 15:06:35 +04:00
parent ef72486bd7
commit 3d22758385
5 changed files with 202 additions and 13 deletions
@@ -190,3 +190,131 @@ func PlanModifierExpr(p types.Param) string {
return "stringplanmodifier.RequiresReplace()"
}
}
// ─── Nested (map-fixed) helpers ──────────────────────────────────────────────
// IsNested возвращает true для параметров с SubParams (map-fixed/array-map-fixed).
func IsNested(p types.Param) bool {
return p.IsNested
}
// IsNestedList возвращает true для array-map-fixed (список объектов).
func IsNestedList(p types.Param) bool {
return p.IsNested && strings.Contains(strings.ToLower(p.Type), "array")
}
// NestedModelName возвращает имя вложенного Go-struct для ресурса и параметра.
// Например: NestedModelName("postgres", "cluster_configuration") → "PostgresClusterConfigurationModel"
func NestedModelName(resourceName, paramCode string) string {
return ToCamel(resourceName) + ToCamel(paramCode) + "Model"
}
// NestedTfType возвращает Go-тип для вложенного поля в Model:
// *PostgresClusterConfigurationModel (SingleNestedAttribute) или
// []PostgresClusterConfigurationModel (ListNestedAttribute — array-map-fixed).
func NestedTfType(p types.Param, resourceName string) string {
name := NestedModelName(resourceName, p.Code)
if IsNestedList(p) {
return "[]" + name
}
return "*" + name
}
// NestedSchemaType возвращает тип схемы для nested параметра:
// "SingleNested" (map-fixed) или "ListNested" (array-map-fixed).
func NestedSchemaType(p types.Param) string {
if IsNestedList(p) {
return "ListNested"
}
return "SingleNested"
}
// NestedSchemaBlock генерирует открывающую строку для nested-атрибута в Schema.
func NestedSchemaBlock(p types.Param) string {
t := NestedSchemaType(p)
switch t {
case "ListNested":
return fmt.Sprintf("schema.%sAttribute{Optional: true,\n\t\t\tNestedObject: schema.NestedAttributeObject{Attributes: map[string]schema.Attribute{", t)
default:
req := "Required: true"
if p.Default != "" {
req = "Optional: true, Computed: true"
}
return fmt.Sprintf("schema.%sAttribute{%s,\n\t\t\tAttributes: map[string]schema.Attribute{", t, req)
}
}
// NestedSchemaEnd возвращает закрывающую строку для nested-атрибута.
func NestedSchemaEnd(p types.Param) string {
t := NestedSchemaType(p)
if t == "ListNested" {
return "}},"
}
return "},"
}
// SubSchemaType возвращает тип схемы для подпараметра.
func SubSchemaType(p types.Param) string {
switch strings.ToLower(p.Type) {
case "bool":
return "Bool"
case "int64", "int", "number":
return "Int64"
default:
return "String"
}
}
// SubDefaultExpr возвращает выражение default для подпараметра.
// ⚠️ Только Optional+Computed (Required несовместим с Default во фреймворке).
func SubDefaultExpr(p types.Param) string {
if p.Default == "" {
return ""
}
switch strings.ToLower(p.Type) {
case "bool":
return fmt.Sprintf("booldefault.StaticBool(%s)", strings.ToLower(p.Default))
case "int64", "int", "number":
return fmt.Sprintf("int64default.StaticInt64(%s)", p.Default)
default:
return fmt.Sprintf("stringdefault.StaticString(%q)", p.Default)
}
}
// SubParamFormat возвращает JSON-ключ:значение для форматирования подпараметра.
func SubParamFormat(p types.Param, varPrefix string) string {
varName := varPrefix + "." + ToCamel(p.Code)
switch strings.ToLower(p.Type) {
case "bool":
return fmt.Sprintf(`"%s": `+varName+`.ValueBool()`, p.Code)
case "int64", "int", "number":
return fmt.Sprintf(`"%s": %s `+varName+`.ValueInt64()`, p.Code, "%s")
default:
return fmt.Sprintf(`"%s": `+varName+`.ValueString()`, p.Code)
}
}
// NestedJSONExpr возвращает выражение для сборки JSON из nested struct через resources_core.BuildJSON.
// BuildJSON принимает map[string]string где ключи — имена полей,
// значения — уже отформатированные строки (числа без кавычек, строки с кавычками).
// Пример: resources_core.BuildJSON(map[string]string{"cpu": "500", "name": "\"hello\""}) → {"cpu":500,"name":"hello"}
func NestedJSONExpr(p types.Param, varName string) string {
pairs := make([]string, 0, len(p.SubParams))
for _, sp := range p.SubParams {
field := varName + "." + ToCamel(sp.Code)
var valExpr string
switch strings.ToLower(sp.Type) {
case "bool":
// BuildJSON ожидает "true"/"false" (без кавычек)
valExpr = fmt.Sprintf(`fmt.Sprintf("%%v", %s.ValueBool())`, field)
case "int64", "int", "number":
// BuildJSON ожидает "500" (без кавычек)
valExpr = fmt.Sprintf(`fmt.Sprintf("%%d", %s.ValueInt64())`, field)
default:
// BuildJSON ожидает "\"hello\"" (с кавычками)
valExpr = fmt.Sprintf(`fmt.Sprintf("\"%%s\"", %s.ValueString())`, field)
}
pairs = append(pairs, fmt.Sprintf(`"%s": %s`, sp.Code, valExpr))
}
return fmt.Sprintf("resources_core.BuildJSON(map[string]string{%s})", strings.Join(pairs, ", "))
}