diff --git a/pkg/config/common.go b/pkg/config/common.go index 651a4c88..c559bb1a 100644 --- a/pkg/config/common.go +++ b/pkg/config/common.go @@ -124,10 +124,18 @@ func MoveToStatus(sch *schema.Resource, fieldpaths ...string) { } } +// MarkAsRequired marks the given fieldpaths as required without manipulating +// the native field schema. +func (r *Resource) MarkAsRequired(fieldpaths ...string) { + r.requiredFields = append(r.requiredFields, fieldpaths...) +} + // MarkAsRequired marks the schema of the given fieldpath as required. It's most // useful in cases where external name contains an optional parameter that is // defaulted by the provider but we need it to exist or to fix plain buggy // schemas. +// Deprecated: Use Resource.MarkAsRequired instead. +// This function will be removed in future versions. func MarkAsRequired(sch *schema.Resource, fieldpaths ...string) { for _, fieldpath := range fieldpaths { if s := GetSchema(sch, fieldpath); s != nil { diff --git a/pkg/config/common_test.go b/pkg/config/common_test.go index a8cec8d9..3bdfc553 100644 --- a/pkg/config/common_test.go +++ b/pkg/config/common_test.go @@ -128,6 +128,7 @@ func TestDefaultResource(t *testing.T) { cmpopts.IgnoreFields(ExternalName{}, "SetIdentifierArgumentFn", "GetExternalNameFn", "GetIDFn"), cmpopts.IgnoreFields(Resource{}, "useTerraformPluginSDKClient"), cmpopts.IgnoreFields(Resource{}, "useTerraformPluginFrameworkClient"), + cmpopts.IgnoreFields(Resource{}, "requiredFields"), } for name, tc := range cases { diff --git a/pkg/config/resource.go b/pkg/config/resource.go index 1023fd9a..58bec39b 100644 --- a/pkg/config/resource.go +++ b/pkg/config/resource.go @@ -489,6 +489,15 @@ type Resource struct { // the value of the generated Kind, for example: // "TagParameters": "ClusterTagParameters" OverrideFieldNames map[string]string + + // requiredFields are the fields that will be marked as required in the + // generated CRD schema, although they are not required in the TF schema. + requiredFields []string +} + +// RequiredFields returns slice of the marked as required fieldpaths. +func (r *Resource) RequiredFields() []string { + return r.requiredFields } // ShouldUseTerraformPluginSDKClient returns whether to generate an SDKv2-based diff --git a/pkg/types/builder.go b/pkg/types/builder.go index f61e79e3..1afb68d8 100644 --- a/pkg/types/builder.go +++ b/pkg/types/builder.go @@ -380,7 +380,7 @@ func newTopLevelRequiredParam(path string, includeInit bool) *topLevelRequiredPa } func (r *resource) addParameterField(f *Field, field *types.Var) { - requiredBySchema := !f.Schema.Optional + requiredBySchema := !f.Schema.Optional || f.Required // Note(turkenh): We are collecting the top level required parameters that // are not identifier fields. This is for generating CEL validation rules for // those parameters and not to require them if the management policy is set diff --git a/pkg/types/field.go b/pkg/types/field.go index b4f04866..61e2afae 100644 --- a/pkg/types/field.go +++ b/pkg/types/field.go @@ -45,6 +45,7 @@ type Field struct { TransformedName string SelectorName string Identifier bool + Required bool // Injected is set if this Field is an injected field to the Terraform // schema as an object list map key for server-side apply merges. Injected bool @@ -120,6 +121,12 @@ func NewField(g *Builder, cfg *config.Resource, r *resource, sch *schema.Schema, } } + for _, required := range cfg.RequiredFields() { + if required == snakeFieldName { + f.Required = true + } + } + var commentText string docString := getDocString(cfg, f, tfPath) if len(docString) > 0 {