From cbc033ea140ffb8260ff4cfeb0463acf58372bc4 Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Mon, 19 Aug 2024 02:22:37 +0100 Subject: [PATCH] generator-go-sdk: populate inherited model struct fields from all parents, only set ancestor-specific fields when implementing its interface --- .../generator-go-sdk/internal/cmd/generate.go | 2 +- .../internal/generator/templater_models.go | 38 ++++++++++++++----- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/tools/generator-go-sdk/internal/cmd/generate.go b/tools/generator-go-sdk/internal/cmd/generate.go index 3fa2de78bec..c610f45a74d 100644 --- a/tools/generator-go-sdk/internal/cmd/generate.go +++ b/tools/generator-go-sdk/internal/cmd/generate.go @@ -93,7 +93,7 @@ func (g GenerateCommand) Run(args []string) int { f := flag.NewFlagSet("generator-go-sdk", flag.ExitOnError) f.StringVar(&input.apiServerEndpoint, "data-api", "http://localhost:8080", "-data-api=http://localhost:8080") f.StringVar(&input.outputDirectory, "output-dir", "", "-output-dir=../generated-sdk-dev") - f.StringVar(&serviceNames, "services", "", "A list of comma separated Service named from the Data API to import") + f.StringVar(&serviceNames, "services", "", "A list of comma separated Service named from the Data API to generate") if err := f.Parse(args); err != nil { log.Fatalf("parsing arguments: %+v", err) } diff --git a/tools/generator-go-sdk/internal/generator/templater_models.go b/tools/generator-go-sdk/internal/generator/templater_models.go index 7ed1c799e71..66c89cdf5d5 100644 --- a/tools/generator-go-sdk/internal/generator/templater_models.go +++ b/tools/generator-go-sdk/internal/generator/templater_models.go @@ -112,21 +112,38 @@ func (c modelsTemplater) structCode(data GeneratorData) (*string, error) { } parentAssignmentInfo = fmt.Sprintf("var _ %[1]s = %[2]s{}", parentTypeName, structName) + parentFields := make(map[string]models.SDKField) + parent, ok := data.models[*c.model.ParentTypeName] if !ok { return nil, fmt.Errorf("couldn't find Parent Model %q for Model %q", *c.model.ParentTypeName, c.name) } + for fieldName, fieldDetails := range parent.Fields { + parentFields[fieldName] = fieldDetails + } + + // Also include fields from the grandparent model + // Related to: https://github.com/hashicorp/pandora/issues/1235 + if parentTypeName != *c.model.ParentTypeName { + grandParent, ok := data.models[parentTypeName] + if !ok { + return nil, fmt.Errorf("couldn't find [Grand]Parent Model %q for Model %q", parentTypeName, c.name) + } + for fieldName, fieldDetails := range grandParent.Fields { + parentFields[fieldName] = fieldDetails + } + } - parentFields := make([]string, 0) - for fieldName := range parent.Fields { - parentFields = append(parentFields, fieldName) + parentFieldNames := make([]string, 0, len(parentFields)) + for fieldName := range parentFields { + parentFieldNames = append(parentFieldNames, fieldName) } - sort.Strings(parentFields) + sort.Strings(parentFieldNames) - if len(parentFields) > 0 { + if len(parentFieldNames) > 0 { structLines = append(structLines, fmt.Sprintf("\n// Fields inherited from %s", *c.model.ParentTypeName)) - for _, fieldName := range parentFields { - fieldDetails := parent.Fields[fieldName] + for _, fieldName := range parentFieldNames { + fieldDetails := parentFields[fieldName] fieldTypeName := "FIXME" fieldTypeVal, err := helpers.GolangTypeForSDKObjectDefinition(fieldDetails.ObjectDefinition, nil, data.commonTypesPackageName) if err != nil { @@ -393,7 +410,8 @@ func (c modelsTemplater) codeForParentStructFunctions(data GeneratorData) (*stri parentTypeName = *c.model.ParentTypeName } - parent, ok := data.models[*c.model.ParentTypeName] + // Intentionally only setting fields from the outermost parent model + parent, ok := data.models[parentTypeName] if !ok { return nil, fmt.Errorf("couldn't find Parent Model %q for Model %q", *c.model.ParentTypeName, c.name) } @@ -449,7 +467,7 @@ func (c modelsTemplater) codeForMarshalFunctions(data GeneratorData) (*string, e structName := c.name - // parent models get a {model}Parent struct + // parent models get a {model}Base struct if c.model.IsDiscriminatedParentType() { structName = fmt.Sprintf("%sBase", c.name) } @@ -623,7 +641,7 @@ func Unmarshal%[1]sImplementation(input []byte) (%[1]s, error) { func (c modelsTemplater) codeForUnmarshalStructFunction(data GeneratorData) (*string, error) { structName := c.name - // parent models get a {model}Parent struct + // parent models get a {model}Base struct if c.model.IsDiscriminatedParentType() { structName = fmt.Sprintf("%sBase", c.name) }