diff --git a/pkg/tools/gen/genkcl.go b/pkg/tools/gen/genkcl.go index f87eb837..2a3ddabc 100644 --- a/pkg/tools/gen/genkcl.go +++ b/pkg/tools/gen/genkcl.go @@ -127,7 +127,7 @@ func (k *kclGenerator) parserGoStructFieldTag(tag string) (string, string, error tagMap := make(map[string]string, 0) sp := strings.Split(tag, "`") if len(sp) == 1 { - return "", "", errors.New("this field not found tag string like `` !") + return "", "", errors.New("this field not found tag string like ``") } value, ok := k.Lookup(sp[1], "kcl") if !ok { diff --git a/pkg/tools/gen/genkcl_jsonschema.go b/pkg/tools/gen/genkcl_jsonschema.go index 293dfced..a0dabd75 100644 --- a/pkg/tools/gen/genkcl_jsonschema.go +++ b/pkg/tools/gen/genkcl_jsonschema.go @@ -179,7 +179,7 @@ func convertSchemaFromJsonSchema(ctx *convertContext, s *jsonschema.Schema, name } for i, prop := range *v { val := prop.Schema - propSch := convertSchemaFromJsonSchema(ctx, val, "patternProperties" + strconv.Itoa(i)) + propSch := convertSchemaFromJsonSchema(ctx, val, "patternProperties"+strconv.Itoa(i)) if propSch.IsSchema { ctx.resultMap[propSch.schema.Name] = propSch } diff --git a/pkg/tools/gen/genkcl_test.go b/pkg/tools/gen/genkcl_test.go index 5b810203..d12a5267 100644 --- a/pkg/tools/gen/genkcl_test.go +++ b/pkg/tools/gen/genkcl_test.go @@ -219,6 +219,8 @@ func TestGenKclFromYaml(t *testing.T) { } } +type TestData = data + func TestGenKclFromJsonAndImports(t *testing.T) { file := kclFile{} g := &kclGenerator{} @@ -240,13 +242,47 @@ func TestGenKclFromJsonAndImports(t *testing.T) { } file.Imports = append(file.Imports, importStmt) configSchemaName := strings.Join([]string{importStmt.PkgName(), "AppConfiguration"}, ".") - // Add configurations + // Add the configuration `app1` at top level. file.Config = append(file.Config, config{ Data: data, IsUnion: true, Var: "app1", Name: configSchemaName, }) + // Add the configuration `app2` at top level with more data configs. + data = append(data, TestData{ + Key: "labels", + Value: config{ + Name: "Labels", + Data: []TestData{{ + Key: "app", + Value: "nginx", + }}, + }, + }) + data = append(data, TestData{ + Key: "annotations", + Value: config{ + Data: []TestData{{ + Key: "app1", + Value: map[string]any{ + "app": "nginx", + }, + }, { + Key: "app2", + Value: config{ + Name: "Annotation", + Data: []TestData{{ + Key: "app1", + Value: map[string]string{ + "app": "nginx", + }, + }, + }, + }, + }}, + }, + }) file.Config = append(file.Config, config{ Data: data, IsUnion: true, @@ -280,6 +316,15 @@ app2: ac.AppConfiguration { } replicas = 2 } + labels = Labels { + app = "nginx" + } + annotations = { + app1 = {"app": "nginx"} + app2 = Annotation { + app1 = {"app": "nginx"} + } + } } `) } diff --git a/pkg/tools/gen/template.go b/pkg/tools/gen/template.go index 560d3ef2..e852049e 100644 --- a/pkg/tools/gen/template.go +++ b/pkg/tools/gen/template.go @@ -37,6 +37,10 @@ var funcs = template.FuncMap{ _, ok := v.([]data) return ok }, + "isKclConfig": func(v interface{}) bool { + _, ok := v.(config) + return ok + }, "isArray": func(v interface{}) bool { _, ok := v.([]interface{}) return ok @@ -94,15 +98,18 @@ func formatValue(v interface{}) string { return "True" } return "False" + case map[string]bool: + return formatMap(value) + case map[string]float32: + return formatMap(value) + case map[string]float64: + return formatMap(value) + case map[string]int: + return formatMap(value) + case map[string]string: + return formatMap(value) case map[string]interface{}: - var s strings.Builder - for _, key := range getSortedKeys(value) { - if s.Len() != 0 { - s.WriteString(", ") - } - s.WriteString(fmt.Sprintf("%s: %s", formatValue(key), formatValue(value[key]))) - } - return "{" + s.String() + "}" + return formatMap(value) case []interface{}: var s strings.Builder for i, item := range value { @@ -117,6 +124,17 @@ func formatValue(v interface{}) string { } } +func formatMap[V any](value map[string]V) string { + var s strings.Builder + for _, key := range getSortedKeys(value) { + if s.Len() != 0 { + s.WriteString(", ") + } + s.WriteString(fmt.Sprintf("%s: %s", formatValue(key), formatValue(value[key]))) + } + return "{" + s.String() + "}" +} + var kclKeywords = map[string]struct{}{ "True": {}, "False": {}, diff --git a/pkg/tools/gen/templates/kcl/data.gotmpl b/pkg/tools/gen/templates/kcl/data.gotmpl index ece47777..41aeb83a 100644 --- a/pkg/tools/gen/templates/kcl/data.gotmpl +++ b/pkg/tools/gen/templates/kcl/data.gotmpl @@ -1,10 +1,11 @@ {{ formatName .Key }}{{ " = " }} - {{- if isKclData .Value }} + {{- if isKclConfig .Value }}{{ template "config" .Value -}} + {{- else if isKclData .Value }} {{- "{\n" }} {{- range .Value -}} {{- indentLines (include "data" .) " " }} {{- end }} - {{- "}" }} + {{- "}\n" }} {{- else if isArray .Value }} {{- "[\n" }} {{- range .Value -}} @@ -18,7 +19,7 @@ {{- indentLines (formatValue .) " " }}{{- "\n" }} {{- end }} {{- end }} - {{- "]" }} + {{- "]\n" }} {{- else }} - {{- formatValue .Value }} - {{- end }} + {{- formatValue .Value }}{{- "\n" }} + {{- end }} \ No newline at end of file