From 3e0cfa48042833d42d9996d67c2294499aab7f8d Mon Sep 17 00:00:00 2001 From: Stuart McLaren Date: Thu, 15 Aug 2024 14:29:19 +0100 Subject: [PATCH] Allow overriding computed_optional_required This can be useful, for example, when the person writing the Terraform provider does not control the contents of the OpenAPI spec. For example to set an attribute to "required": ``` attributes: overrides: name: description: The new description for name computed_optional_required: required ``` --- internal/config/parse.go | 2 + internal/explorer/config_explorer.go | 5 +- internal/explorer/config_explorer_test.go | 6 +- internal/explorer/explorer.go | 3 +- .../attrmapper/resource_attributes_test.go | 96 +++++++++++++++++++ internal/mapper/attrmapper/string.go | 19 ++++ 6 files changed, 127 insertions(+), 4 deletions(-) diff --git a/internal/config/parse.go b/internal/config/parse.go index a628e8a..8b2f663 100644 --- a/internal/config/parse.go +++ b/internal/config/parse.go @@ -82,6 +82,8 @@ type AttributeOptions struct { type Override struct { // Description overrides the description that was mapped/merged from the OpenAPI specification. Description string `yaml:"description"` + // ComputedOptionalRequired overrides the inferred value from the OpenAPI specification. + ComputedOptionalRequired string `yaml:"computed_optional_required"` } // ParseConfig takes in a byte array (of YAML), unmarshals into a Config struct, and validates the result diff --git a/internal/explorer/config_explorer.go b/internal/explorer/config_explorer.go index cc5fa13..7265f16 100644 --- a/internal/explorer/config_explorer.go +++ b/internal/explorer/config_explorer.go @@ -211,7 +211,10 @@ func extractSchemaOptions(cfgSchemaOpts config.SchemaOptions) SchemaOptions { func extractOverrides(cfgOverrides map[string]config.Override) map[string]Override { overrides := make(map[string]Override, len(cfgOverrides)) for key, cfgOverride := range cfgOverrides { - overrides[key] = Override{Description: cfgOverride.Description} + overrides[key] = Override{ + Description: cfgOverride.Description, + ComputedOptionalRequired: cfgOverride.ComputedOptionalRequired, + } } return overrides diff --git a/internal/explorer/config_explorer_test.go b/internal/explorer/config_explorer_test.go index 36fa2cf..b597216 100644 --- a/internal/explorer/config_explorer_test.go +++ b/internal/explorer/config_explorer_test.go @@ -270,7 +270,8 @@ func Test_ConfigExplorer_FindResources(t *testing.T) { }, Overrides: map[string]config.Override{ "test": { - Description: "test description for override", + Description: "test description for override", + ComputedOptionalRequired: "computed_optional", }, }, }, @@ -310,7 +311,8 @@ func Test_ConfigExplorer_FindResources(t *testing.T) { }, Overrides: map[string]explorer.Override{ "test": { - Description: "test description for override", + Description: "test description for override", + ComputedOptionalRequired: "computed_optional", }, }, }, diff --git a/internal/explorer/explorer.go b/internal/explorer/explorer.go index 908b62c..0a49b8c 100644 --- a/internal/explorer/explorer.go +++ b/internal/explorer/explorer.go @@ -50,5 +50,6 @@ type AttributeOptions struct { } type Override struct { - Description string + Description string + ComputedOptionalRequired string } diff --git a/internal/mapper/attrmapper/resource_attributes_test.go b/internal/mapper/attrmapper/resource_attributes_test.go index 51aa331..178eae2 100644 --- a/internal/mapper/attrmapper/resource_attributes_test.go +++ b/internal/mapper/attrmapper/resource_attributes_test.go @@ -282,6 +282,102 @@ func TestResourceAttributes_ApplyOverrides(t *testing.T) { }, }, }, + "matching overrides computed": { + overrides: map[string]explorer.Override{ + "string_attribute": { + ComputedOptionalRequired: "computed", + }, + }, + attributes: attrmapper.ResourceAttributes{ + &attrmapper.ResourceStringAttribute{ + Name: "string_attribute", + StringAttribute: resource.StringAttribute{ + ComputedOptionalRequired: schema.Required, + }, + }, + }, + expectedAttributes: attrmapper.ResourceAttributes{ + &attrmapper.ResourceStringAttribute{ + Name: "string_attribute", + StringAttribute: resource.StringAttribute{ + ComputedOptionalRequired: schema.Computed, + Description: pointer(""), + }, + }, + }, + }, + "matching overrides optional": { + overrides: map[string]explorer.Override{ + "string_attribute": { + ComputedOptionalRequired: "optional", + }, + }, + attributes: attrmapper.ResourceAttributes{ + &attrmapper.ResourceStringAttribute{ + Name: "string_attribute", + StringAttribute: resource.StringAttribute{ + ComputedOptionalRequired: schema.Required, + }, + }, + }, + expectedAttributes: attrmapper.ResourceAttributes{ + &attrmapper.ResourceStringAttribute{ + Name: "string_attribute", + StringAttribute: resource.StringAttribute{ + ComputedOptionalRequired: schema.Optional, + Description: pointer(""), + }, + }, + }, + }, + "matching overrides required": { + overrides: map[string]explorer.Override{ + "string_attribute": { + ComputedOptionalRequired: "required", + }, + }, + attributes: attrmapper.ResourceAttributes{ + &attrmapper.ResourceStringAttribute{ + Name: "string_attribute", + StringAttribute: resource.StringAttribute{ + ComputedOptionalRequired: schema.Computed, + }, + }, + }, + expectedAttributes: attrmapper.ResourceAttributes{ + &attrmapper.ResourceStringAttribute{ + Name: "string_attribute", + StringAttribute: resource.StringAttribute{ + ComputedOptionalRequired: schema.Required, + Description: pointer(""), + }, + }, + }, + }, + "matching overrides computed_optional": { + overrides: map[string]explorer.Override{ + "string_attribute": { + ComputedOptionalRequired: "computed_optional", + }, + }, + attributes: attrmapper.ResourceAttributes{ + &attrmapper.ResourceStringAttribute{ + Name: "string_attribute", + StringAttribute: resource.StringAttribute{ + ComputedOptionalRequired: schema.Computed, + }, + }, + }, + expectedAttributes: attrmapper.ResourceAttributes{ + &attrmapper.ResourceStringAttribute{ + Name: "string_attribute", + StringAttribute: resource.StringAttribute{ + ComputedOptionalRequired: schema.ComputedOptional, + Description: pointer(""), + }, + }, + }, + }, "matching nested overrides": { overrides: map[string]explorer.Override{ "single_nested": { diff --git a/internal/mapper/attrmapper/string.go b/internal/mapper/attrmapper/string.go index fc54a6a..798ef30 100644 --- a/internal/mapper/attrmapper/string.go +++ b/internal/mapper/attrmapper/string.go @@ -4,11 +4,13 @@ package attrmapper import ( + "fmt" "github.com/hashicorp/terraform-plugin-codegen-openapi/internal/explorer" "github.com/hashicorp/terraform-plugin-codegen-openapi/internal/mapper/util" "github.com/hashicorp/terraform-plugin-codegen-spec/datasource" "github.com/hashicorp/terraform-plugin-codegen-spec/provider" "github.com/hashicorp/terraform-plugin-codegen-spec/resource" + "github.com/hashicorp/terraform-plugin-codegen-spec/schema" ) type ResourceStringAttribute struct { @@ -34,6 +36,23 @@ func (a *ResourceStringAttribute) Merge(mergeAttribute ResourceAttribute) (Resou func (a *ResourceStringAttribute) ApplyOverride(override explorer.Override) (ResourceAttribute, error) { a.Description = &override.Description + switch override.ComputedOptionalRequired { + case "": // No override + case "computed": + a.ComputedOptionalRequired = schema.Computed + case "optional": + a.ComputedOptionalRequired = schema.Optional + case "required": + a.ComputedOptionalRequired = schema.Required + case "computed_optional": + a.ComputedOptionalRequired = schema.ComputedOptional + default: + return nil, fmt.Errorf( + "invalid value for computed_optional_required: %s", + override.ComputedOptionalRequired, + ) + } + return a, nil }