From 707c9ca36898a421366106f41ed76cc577802f78 Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Tue, 13 Dec 2022 06:32:40 -0800 Subject: [PATCH] resource+tfsdk: Remove tfsdk package schema types and functions (#576) Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/132 Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/326 Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/491 Refer to the following pull request descriptions for migration information about migrating to the split schema packages: - `datasource/schema`: https://github.com/hashicorp/terraform-plugin-framework/pull/546 - `provider/schema`: https://github.com/hashicorp/terraform-plugin-framework/pull/553 - `resource/schema`: https://github.com/hashicorp/terraform-plugin-framework/pull/558 - `provider/metaschema`: https://github.com/hashicorp/terraform-plugin-framework/pull/562 --- .changelog/576.txt | 31 + .golangci.yml | 8 - datasource/data_source.go | 32 +- internal/fwschema/attribute_nesting_mode.go | 32 + .../fwxschema/attribute_plan_modification.go | 14 - .../fwxschema/attribute_validation.go | 14 - .../fwxschema/block_plan_modification.go | 14 - .../fwschema/fwxschema/block_validation.go | 14 - internal/fwschema/nested_attributes.go | 215 -- internal/fwschema/nested_attributes_test.go | 173 - .../fwserver/attribute_plan_modification.go | 120 +- .../attribute_plan_modification_test.go | 318 +- internal/fwserver/attribute_validation.go | 121 +- .../fwserver/attribute_validation_test.go | 512 +-- internal/fwserver/block_plan_modification.go | 45 +- .../fwserver/block_plan_modification_test.go | 128 +- internal/fwserver/block_validation.go | 50 +- internal/fwserver/block_validation_test.go | 222 +- internal/fwserver/schema_plan_modification.go | 4 +- internal/fwserver/schema_validation.go | 8 +- internal/fwserver/server.go | 148 +- .../testing/planmodifiers/planmodifiers.go | 114 - .../testprovider/attributeplanmodifier.go | 44 - .../testprovider/attributevalidator.go | 44 - .../types/listnestedattributescustom.go | 11 - .../types/mapnestedattributescustom.go | 11 - .../types/setnestedattributescustom.go | 11 - .../types/singlenestedattributescustom.go | 11 - internal/toproto5/schema_attribute.go | 12 +- internal/toproto6/block_test.go | 43 +- internal/toproto6/schema_attribute.go | 19 - provider/provider.go | 28 +- resource/plan_modifiers.go | 347 -- resource/plan_modifiers_test.go | 1561 -------- resource/resource.go | 34 +- tfsdk/attribute.go | 271 -- tfsdk/attribute_plan_modification.go | 128 - tfsdk/attribute_test.go | 241 -- tfsdk/attribute_validation.go | 54 - tfsdk/block.go | 218 -- tfsdk/block_nested_mode.go | 11 - tfsdk/block_test.go | 137 - tfsdk/config_test.go | 61 +- tfsdk/nested_attribute_object.go | 44 - tfsdk/nested_attributes.go | 62 - tfsdk/nested_block_object.go | 60 - tfsdk/plan_test.go | 99 +- tfsdk/pointer_test.go | 5 + tfsdk/schema.go | 176 - tfsdk/schema_test.go | 3416 ----------------- tfsdk/state_test.go | 81 +- 51 files changed, 1001 insertions(+), 8576 deletions(-) create mode 100644 .changelog/576.txt create mode 100644 internal/fwschema/attribute_nesting_mode.go delete mode 100644 internal/fwschema/nested_attributes.go delete mode 100644 internal/fwschema/nested_attributes_test.go delete mode 100644 internal/testing/testprovider/attributeplanmodifier.go delete mode 100644 internal/testing/testprovider/attributevalidator.go delete mode 100644 resource/plan_modifiers.go delete mode 100644 resource/plan_modifiers_test.go delete mode 100644 tfsdk/attribute.go delete mode 100644 tfsdk/attribute_plan_modification.go delete mode 100644 tfsdk/attribute_test.go delete mode 100644 tfsdk/attribute_validation.go delete mode 100644 tfsdk/block.go delete mode 100644 tfsdk/block_nested_mode.go delete mode 100644 tfsdk/block_test.go delete mode 100644 tfsdk/nested_attribute_object.go delete mode 100644 tfsdk/nested_attributes.go delete mode 100644 tfsdk/nested_block_object.go create mode 100644 tfsdk/pointer_test.go delete mode 100644 tfsdk/schema.go delete mode 100644 tfsdk/schema_test.go diff --git a/.changelog/576.txt b/.changelog/576.txt new file mode 100644 index 000000000..b58614dbf --- /dev/null +++ b/.changelog/576.txt @@ -0,0 +1,31 @@ +```release-note:breaking-change +resource: The `RequiresReplace()` plan modifier has been removed. Use a type-specific plan modifier instead, such as `resource/schema/stringplanmodifier.RequiresReplace()` or `resource/schema/stringplanmodifier.RequiresReplaceIfConfigured()` +``` + +```release-note:breaking-change +resource: The `RequiresReplaceIf()` plan modifier has been removed. Use a type-specific plan modifier instead, such as `resource/schema/stringplanmodifier.RequiresReplaceIf()` +``` + +```release-note:breaking-change +resource: The `Resource` type `GetSchema` method has been removed. Use the `Schema` method instead. +``` + +```release-note:breaking-change +resource: The `UseStateForUnknown()` plan modifier has been removed. Use a type-specific plan modifier instead, such as `resource/schema/stringplanmodifier.UseStateForUnknown()` +``` + +```release-note:breaking-change +tfsdk: The `Attribute`, `Block`, and `Schema` types have been removed. Use the similarly named types in the `datasource/schema`, `provider/schema`, and `resource/schema` packages instead. +``` + +```release-note:breaking-change +tfsdk: The `AttributePlanModifier` interface has been removed. Use the type-specific plan modifier interfaces in the `resource/schema/planmodifier` package instead. +``` + +```release-note:breaking-change +tfsdk: The `AttributeValidator` interface has been removed. Use the type-specific validator interfaces in the `schema/validator` package instead. +``` + +```release-note:breaking-change +tfsdk: The `ListNestedAttributes`, `MapNestedAttributes`, `SetNestedAttributes`, and `SingleNestedAttributes` functions have been removed. Use the similarly named types in the `datasource/schema`, `provider/schema`, and `resource/schema` packages instead. +``` diff --git a/.golangci.yml b/.golangci.yml index 98674333f..b9a329c4d 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,12 +1,4 @@ issues: - # Temporary rules for unit testing until tfsdk.Schema is removed. - exclude-rules: - - linters: - - staticcheck - text: 'SA1019: tfsdk.(Attribute|Block|Schema) is deprecated' - - linters: - - staticcheck - text: 'SA1019: tfsdk.(List|Map|Set|Single)NestedAttributes is deprecated' max-per-linter: 0 max-same-issues: 0 diff --git a/datasource/data_source.go b/datasource/data_source.go index 695811481..8229c54a9 100644 --- a/datasource/data_source.go +++ b/datasource/data_source.go @@ -2,26 +2,24 @@ package datasource import ( "context" - - "github.com/hashicorp/terraform-plugin-framework/diag" - "github.com/hashicorp/terraform-plugin-framework/tfsdk" ) // DataSource represents an instance of a data source type. This is the core -// interface that all data sources must implement. Data sources must also -// implement the Schema method or the deprecated GetSchema method. The Schema -// method will be required in a future version. +// interface that all data sources must implement. // // Data sources can optionally implement these additional concepts: // // - Configure: Include provider-level data or clients. -// - Validation: Schema-based via tfsdk.Attribute or entire configuration +// - Validation: Schema-based or entire configuration // via DataSourceWithConfigValidators or DataSourceWithValidateConfig. type DataSource interface { // Metadata should return the full name of the data source, such as // examplecloud_thing. Metadata(context.Context, MetadataRequest, *MetadataResponse) + // Schema should return the schema for this data source. + Schema(context.Context, SchemaRequest, *SchemaResponse) + // Read is called when the provider must read data source values in // order to update state. Config values should be read from the // ReadRequest and new state values set on the ReadResponse. @@ -59,26 +57,6 @@ type DataSourceWithConfigValidators interface { ConfigValidators(context.Context) []ConfigValidator } -// DataSourceWithGetSchema is a temporary interface type that extends -// DataSource to include the deprecated GetSchema method. -type DataSourceWithGetSchema interface { - DataSource - - // GetSchema returns the schema for this data source. - // - // Deprecated: Use Schema method instead. - GetSchema(context.Context) (tfsdk.Schema, diag.Diagnostics) -} - -// DataSourceWithSchema is a temporary interface type that extends -// DataSource to include the new Schema method. -type DataSourceWithSchema interface { - DataSource - - // Schema should return the schema for this data source. - Schema(context.Context, SchemaRequest, *SchemaResponse) -} - // DataSourceWithValidateConfig is an interface type that extends DataSource to include imperative validation. // // Declaring validation using this methodology simplifies one-off diff --git a/internal/fwschema/attribute_nesting_mode.go b/internal/fwschema/attribute_nesting_mode.go new file mode 100644 index 000000000..47e40cd03 --- /dev/null +++ b/internal/fwschema/attribute_nesting_mode.go @@ -0,0 +1,32 @@ +package fwschema + +// NestingMode is an enum type of the ways nested attributes can be nested in +// an attribute. They can be a list, a set, a map (with string +// keys), or they can be nested directly, like an object. +type NestingMode uint8 + +const ( + // NestingModeUnknown is an invalid nesting mode, used to catch when a + // nesting mode is expected and not set. + NestingModeUnknown NestingMode = 0 + + // NestingModeSingle is for attributes that represent a struct or + // object, a single instance of those attributes directly nested under + // another attribute. + NestingModeSingle NestingMode = 1 + + // NestingModeList is for attributes that represent a list of objects, + // with multiple instances of those attributes nested inside a list + // under another attribute. + NestingModeList NestingMode = 2 + + // NestingModeSet is for attributes that represent a set of objects, + // with multiple, unique instances of those attributes nested inside a + // set under another attribute. + NestingModeSet NestingMode = 3 + + // NestingModeMap is for attributes that represent a map of objects, + // with multiple instances of those attributes, each associated with a + // unique string key, nested inside a map under another attribute. + NestingModeMap NestingMode = 4 +) diff --git a/internal/fwschema/fwxschema/attribute_plan_modification.go b/internal/fwschema/fwxschema/attribute_plan_modification.go index d0c62958c..813b729ea 100644 --- a/internal/fwschema/fwxschema/attribute_plan_modification.go +++ b/internal/fwschema/fwxschema/attribute_plan_modification.go @@ -3,22 +3,8 @@ package fwxschema import ( "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" - "github.com/hashicorp/terraform-plugin-framework/tfsdk" ) -// AttributeWithPlanModifiers is an optional interface on Attribute which enables -// plan modification support. -type AttributeWithPlanModifiers interface { - // Implementations should include the fwschema.Attribute interface methods - // for proper attribute handling. - fwschema.Attribute - - // GetPlanModifiers should return a list of attribute-based plan modifiers. - // This is named differently than PlanModifiers to prevent a conflict with - // the tfsdk.Attribute field name. - GetPlanModifiers() tfsdk.AttributePlanModifiers -} - // AttributeWithBoolPlanModifiers is an optional interface on Attribute which // enables Bool plan modifier support. type AttributeWithBoolPlanModifiers interface { diff --git a/internal/fwschema/fwxschema/attribute_validation.go b/internal/fwschema/fwxschema/attribute_validation.go index ff04d0b99..458b665c0 100644 --- a/internal/fwschema/fwxschema/attribute_validation.go +++ b/internal/fwschema/fwxschema/attribute_validation.go @@ -3,22 +3,8 @@ package fwxschema import ( "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" "github.com/hashicorp/terraform-plugin-framework/schema/validator" - "github.com/hashicorp/terraform-plugin-framework/tfsdk" ) -// AttributeWithValidators is an optional interface on Attribute which enables -// validation support. -type AttributeWithValidators interface { - // Implementations should include the fwschema.Attribute interface methods - // for proper attribute handling. - fwschema.Attribute - - // GetValidators should return a list of attribute-based validators. This - // is named differently than PlanModifiers to prevent a conflict with the - // tfsdk.Attribute field name. - GetValidators() []tfsdk.AttributeValidator -} - // AttributeWithBoolValidators is an optional interface on Attribute which // enables Bool validation support. type AttributeWithBoolValidators interface { diff --git a/internal/fwschema/fwxschema/block_plan_modification.go b/internal/fwschema/fwxschema/block_plan_modification.go index d14f7829b..4a0909941 100644 --- a/internal/fwschema/fwxschema/block_plan_modification.go +++ b/internal/fwschema/fwxschema/block_plan_modification.go @@ -3,22 +3,8 @@ package fwxschema import ( "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" - "github.com/hashicorp/terraform-plugin-framework/tfsdk" ) -// BlockWithPlanModifiers is an optional interface on Block which enables -// plan modification support. -type BlockWithPlanModifiers interface { - // Implementations should include the fwschema.Block interface methods - // for proper block handling. - fwschema.Block - - // GetPlanModifiers should return a list of attribute-based plan modifiers. - // This is named differently than PlanModifiers to prevent a conflict with - // the tfsdk.Block field name. - GetPlanModifiers() tfsdk.AttributePlanModifiers -} - // BlockWithListPlanModifiers is an optional interface on Block which // enables List plan modifier support. type BlockWithListPlanModifiers interface { diff --git a/internal/fwschema/fwxschema/block_validation.go b/internal/fwschema/fwxschema/block_validation.go index a967468e6..22f664ccc 100644 --- a/internal/fwschema/fwxschema/block_validation.go +++ b/internal/fwschema/fwxschema/block_validation.go @@ -3,22 +3,8 @@ package fwxschema import ( "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" "github.com/hashicorp/terraform-plugin-framework/schema/validator" - "github.com/hashicorp/terraform-plugin-framework/tfsdk" ) -// BlockWithValidators is an optional interface on Block which enables -// validation support. -type BlockWithValidators interface { - // Implementations should include the fwschema.Block interface methods - // for proper block handling. - fwschema.Block - - // GetValidators should return a list of attribute-based validators. This - // is named differently than Validators to prevent a conflict with the - // tfsdk.Block field name. - GetValidators() []tfsdk.AttributeValidator -} - // BlockWithListValidators is an optional interface on Block which // enables List validation support. type BlockWithListValidators interface { diff --git a/internal/fwschema/nested_attributes.go b/internal/fwschema/nested_attributes.go deleted file mode 100644 index dd80c709a..000000000 --- a/internal/fwschema/nested_attributes.go +++ /dev/null @@ -1,215 +0,0 @@ -package fwschema - -import ( - "fmt" - - "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/hashicorp/terraform-plugin-go/tftypes" -) - -// NestingMode is an enum type of the ways nested attributes can be nested in -// an attribute. They can be a list, a set, a map (with string -// keys), or they can be nested directly, like an object. -type NestingMode uint8 - -const ( - // NestingModeUnknown is an invalid nesting mode, used to catch when a - // nesting mode is expected and not set. - NestingModeUnknown NestingMode = 0 - - // NestingModeSingle is for attributes that represent a struct or - // object, a single instance of those attributes directly nested under - // another attribute. - NestingModeSingle NestingMode = 1 - - // NestingModeList is for attributes that represent a list of objects, - // with multiple instances of those attributes nested inside a list - // under another attribute. - NestingModeList NestingMode = 2 - - // NestingModeSet is for attributes that represent a set of objects, - // with multiple, unique instances of those attributes nested inside a - // set under another attribute. - NestingModeSet NestingMode = 3 - - // NestingModeMap is for attributes that represent a map of objects, - // with multiple instances of those attributes, each associated with a - // unique string key, nested inside a map under another attribute. - NestingModeMap NestingMode = 4 -) - -// NestedAttributes surfaces a group of attributes to nest beneath another -// attribute, and how that nesting should behave. Nesting can have the -// following modes: -// -// * SingleNestedAttributes are nested attributes that represent a struct or -// object; there should only be one instance of them nested beneath that -// specific attribute. -// -// * ListNestedAttributes are nested attributes that represent a list of -// structs or objects; there can be multiple instances of them beneath that -// specific attribute. -// -// * SetNestedAttributes are nested attributes that represent a set of structs -// or objects; there can be multiple instances of them beneath that specific -// attribute. Unlike ListNestedAttributes, these nested attributes must have -// unique values. -// -// * MapNestedAttributes are nested attributes that represent a string-indexed -// map of structs or objects; there can be multiple instances of them beneath -// that specific attribute. Unlike ListNestedAttributes, these nested -// attributes must be associated with a unique key. Unlike SetNestedAttributes, -// the key must be explicitly set by the user. -type NestedAttributes interface { - // Implementations should include the tftypes.AttributePathStepper - // interface methods for proper path and data handling. - tftypes.AttributePathStepper - - // Equal should return true if the other NestedAttributes is equivalent. - Equal(NestedAttributes) bool - - // GetNestingMode should return the nesting mode (list, map, set, or - // single) of the nested attributes. - GetNestingMode() NestingMode - - // GetAttributes() should return the mapping of names to nested attributes. - GetAttributes() map[string]Attribute - - // Type should return the framework type of the nested attributes. - Type() attr.Type -} - -type SingleNestedAttributes struct { - UnderlyingAttributes -} - -func (s SingleNestedAttributes) ApplyTerraform5AttributePathStep(step tftypes.AttributePathStep) (interface{}, error) { - return s.UnderlyingAttributes.ApplyTerraform5AttributePathStep(step) -} - -func (s SingleNestedAttributes) GetAttributes() map[string]Attribute { - return s.UnderlyingAttributes -} - -func (s SingleNestedAttributes) GetNestingMode() NestingMode { - return NestingModeSingle -} - -func (s SingleNestedAttributes) Equal(o NestedAttributes) bool { - other, ok := o.(SingleNestedAttributes) - if !ok { - return false - } - return s.UnderlyingAttributes.Equal(other.UnderlyingAttributes) -} - -// Type returns the framework type of the nested attributes. -func (s SingleNestedAttributes) Type() attr.Type { - return s.UnderlyingAttributes.Type() -} - -type ListNestedAttributes struct { - UnderlyingAttributes -} - -func (l ListNestedAttributes) GetAttributes() map[string]Attribute { - return l.UnderlyingAttributes -} - -func (l ListNestedAttributes) GetNestingMode() NestingMode { - return NestingModeList -} - -func (l ListNestedAttributes) ApplyTerraform5AttributePathStep(step tftypes.AttributePathStep) (interface{}, error) { - _, ok := step.(tftypes.ElementKeyInt) - if !ok { - return nil, fmt.Errorf("can't apply %T to ListNestedAttributes", step) - } - return l.UnderlyingAttributes, nil -} - -func (l ListNestedAttributes) Equal(o NestedAttributes) bool { - other, ok := o.(ListNestedAttributes) - if !ok { - return false - } - return l.UnderlyingAttributes.Equal(other.UnderlyingAttributes) -} - -// Type returns the framework type of the nested attributes. -func (l ListNestedAttributes) Type() attr.Type { - return types.ListType{ - ElemType: l.UnderlyingAttributes.Type(), - } -} - -type SetNestedAttributes struct { - UnderlyingAttributes -} - -func (s SetNestedAttributes) GetAttributes() map[string]Attribute { - return s.UnderlyingAttributes -} - -func (s SetNestedAttributes) GetNestingMode() NestingMode { - return NestingModeSet -} - -func (s SetNestedAttributes) ApplyTerraform5AttributePathStep(step tftypes.AttributePathStep) (interface{}, error) { - _, ok := step.(tftypes.ElementKeyValue) - if !ok { - return nil, fmt.Errorf("can't use %T on sets", step) - } - return s.UnderlyingAttributes, nil -} - -func (s SetNestedAttributes) Equal(o NestedAttributes) bool { - other, ok := o.(SetNestedAttributes) - if !ok { - return false - } - return s.UnderlyingAttributes.Equal(other.UnderlyingAttributes) -} - -// Type returns the framework type of the nested attributes. -func (s SetNestedAttributes) Type() attr.Type { - return types.SetType{ - ElemType: s.UnderlyingAttributes.Type(), - } -} - -type MapNestedAttributes struct { - UnderlyingAttributes -} - -func (m MapNestedAttributes) GetAttributes() map[string]Attribute { - return m.UnderlyingAttributes -} - -func (m MapNestedAttributes) GetNestingMode() NestingMode { - return NestingModeMap -} - -func (m MapNestedAttributes) ApplyTerraform5AttributePathStep(step tftypes.AttributePathStep) (interface{}, error) { - _, ok := step.(tftypes.ElementKeyString) - if !ok { - return nil, fmt.Errorf("can't use %T on maps", step) - } - return m.UnderlyingAttributes, nil -} - -func (m MapNestedAttributes) Equal(o NestedAttributes) bool { - other, ok := o.(MapNestedAttributes) - if !ok { - return false - } - return m.UnderlyingAttributes.Equal(other.UnderlyingAttributes) -} - -// Type returns the framework type of the nested attributes. -func (m MapNestedAttributes) Type() attr.Type { - return types.MapType{ - ElemType: m.UnderlyingAttributes.Type(), - } -} diff --git a/internal/fwschema/nested_attributes_test.go b/internal/fwschema/nested_attributes_test.go deleted file mode 100644 index 6f21823bc..000000000 --- a/internal/fwschema/nested_attributes_test.go +++ /dev/null @@ -1,173 +0,0 @@ -package fwschema_test - -import ( - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" - "github.com/hashicorp/terraform-plugin-framework/tfsdk" - "github.com/hashicorp/terraform-plugin-framework/types" -) - -func TestListNestedAttributesType(t *testing.T) { - t.Parallel() - - testCases := map[string]struct { - listNestedAttributes fwschema.ListNestedAttributes - expected attr.Type - }{ - "tfsdk-attribute": { - listNestedAttributes: fwschema.ListNestedAttributes{ - UnderlyingAttributes: map[string]fwschema.Attribute{ - "test_nested_attribute": tfsdk.Attribute{ - Required: true, - Type: types.StringType, - }, - }, - }, - expected: types.ListType{ - ElemType: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "test_nested_attribute": types.StringType, - }, - }, - }, - }, - } - - for name, testCase := range testCases { - name, testCase := name, testCase - - t.Run(name, func(t *testing.T) { - t.Parallel() - - got := testCase.listNestedAttributes.Type() - - if diff := cmp.Diff(got, testCase.expected); diff != "" { - t.Errorf("unexpected difference: %s", diff) - } - }) - } -} - -func TestMapNestedAttributesType(t *testing.T) { - t.Parallel() - - testCases := map[string]struct { - mapNestedAttributes fwschema.MapNestedAttributes - expected attr.Type - }{ - "tfsdk-attribute": { - mapNestedAttributes: fwschema.MapNestedAttributes{ - UnderlyingAttributes: map[string]fwschema.Attribute{ - "test_nested_attribute": tfsdk.Attribute{ - Required: true, - Type: types.StringType, - }, - }, - }, - expected: types.MapType{ - ElemType: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "test_nested_attribute": types.StringType, - }, - }, - }, - }, - } - - for name, testCase := range testCases { - name, testCase := name, testCase - - t.Run(name, func(t *testing.T) { - t.Parallel() - - got := testCase.mapNestedAttributes.Type() - - if diff := cmp.Diff(got, testCase.expected); diff != "" { - t.Errorf("unexpected difference: %s", diff) - } - }) - } -} - -func TestSetNestedAttributesType(t *testing.T) { - t.Parallel() - - testCases := map[string]struct { - setNestedAttributes fwschema.SetNestedAttributes - expected attr.Type - }{ - "tfsdk-attribute": { - setNestedAttributes: fwschema.SetNestedAttributes{ - UnderlyingAttributes: map[string]fwschema.Attribute{ - "test_nested_attribute": tfsdk.Attribute{ - Required: true, - Type: types.StringType, - }, - }, - }, - expected: types.SetType{ - ElemType: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "test_nested_attribute": types.StringType, - }, - }, - }, - }, - } - - for name, testCase := range testCases { - name, testCase := name, testCase - - t.Run(name, func(t *testing.T) { - t.Parallel() - - got := testCase.setNestedAttributes.Type() - - if diff := cmp.Diff(got, testCase.expected); diff != "" { - t.Errorf("unexpected difference: %s", diff) - } - }) - } -} - -func TestSingleNestedAttributesType(t *testing.T) { - t.Parallel() - - testCases := map[string]struct { - singleNestedAttributes fwschema.SingleNestedAttributes - expected attr.Type - }{ - "tfsdk-attribute": { - singleNestedAttributes: fwschema.SingleNestedAttributes{ - UnderlyingAttributes: map[string]fwschema.Attribute{ - "test_nested_attribute": tfsdk.Attribute{ - Required: true, - Type: types.StringType, - }, - }, - }, - expected: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "test_nested_attribute": types.StringType, - }, - }, - }, - } - - for name, testCase := range testCases { - name, testCase := name, testCase - - t.Run(name, func(t *testing.T) { - t.Parallel() - - got := testCase.singleNestedAttributes.Type() - - if diff := cmp.Diff(got, testCase.expected); diff != "" { - t.Errorf("unexpected difference: %s", diff) - } - }) - } -} diff --git a/internal/fwserver/attribute_plan_modification.go b/internal/fwserver/attribute_plan_modification.go index 04469c7eb..1afbf2c9a 100644 --- a/internal/fwserver/attribute_plan_modification.go +++ b/internal/fwserver/attribute_plan_modification.go @@ -18,6 +18,54 @@ import ( "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) +// ModifyAttributePlanRequest represents a request for the provider to modify an +// attribute value, or mark it as requiring replacement, at plan time. An +// instance of this request struct is supplied as an argument to the Modify +// function of an attribute's plan modifier(s). +type ModifyAttributePlanRequest struct { + // AttributePath is the path of the attribute. Use this path for any + // response diagnostics. + AttributePath path.Path + + // AttributePathExpression is the expression matching the exact path of the + // attribute. + AttributePathExpression path.Expression + + // Config is the configuration the user supplied for the resource. + Config tfsdk.Config + + // State is the current state of the resource. + State tfsdk.State + + // Plan is the planned new state for the resource. + Plan tfsdk.Plan + + // AttributeConfig is the configuration the user supplied for the attribute. + AttributeConfig attr.Value + + // AttributeState is the current state of the attribute. + AttributeState attr.Value + + // AttributePlan is the planned new state for the attribute. + AttributePlan attr.Value + + // ProviderMeta is metadata from the provider_meta block of the module. + ProviderMeta tfsdk.Config + + // Private is provider-defined resource private state data which was previously + // stored with the resource state. This data is opaque to Terraform and does + // not affect plan output. Any existing data is copied to + // ModifyAttributePlanResponse.Private to prevent accidental private state data loss. + // + // The private state data is always the original data when the schema-based plan + // modification began or, is updated as the logic traverses deeper into underlying + // attributes. + // + // Use the GetKey method to read data. Use the SetKey method on + // ModifyAttributePlanResponse.Private to update or remove a value. + Private *privatestate.ProviderData +} + type ModifyAttributePlanResponse struct { AttributePlan attr.Value Diagnostics diag.Diagnostics @@ -31,59 +79,14 @@ type ModifyAttributePlanResponse struct { // The extra Attribute parameter is a carry-over of creating the proto6server // package from the tfsdk package and not wanting to export the method. // Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/365 -func AttributeModifyPlan(ctx context.Context, a fwschema.Attribute, req tfsdk.ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { +func AttributeModifyPlan(ctx context.Context, a fwschema.Attribute, req ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { ctx = logging.FrameworkWithAttributePath(ctx, req.AttributePath.String()) - privateProviderData := privatestate.EmptyProviderData(ctx) - if req.Private != nil { resp.Private = req.Private - privateProviderData = req.Private } switch attributeWithPlanModifiers := a.(type) { - // Legacy tfsdk.AttributePlanModifier handling - case fwxschema.AttributeWithPlanModifiers: - var requiresReplace bool - - for _, planModifier := range attributeWithPlanModifiers.GetPlanModifiers() { - modifyResp := &tfsdk.ModifyAttributePlanResponse{ - AttributePlan: req.AttributePlan, - RequiresReplace: requiresReplace, - Private: privateProviderData, - } - - logging.FrameworkDebug( - ctx, - "Calling provider defined AttributePlanModifier", - map[string]interface{}{ - logging.KeyDescription: planModifier.Description(ctx), - }, - ) - planModifier.Modify(ctx, req, modifyResp) - logging.FrameworkDebug( - ctx, - "Called provider defined AttributePlanModifier", - map[string]interface{}{ - logging.KeyDescription: planModifier.Description(ctx), - }, - ) - - req.AttributePlan = modifyResp.AttributePlan - resp.Diagnostics.Append(modifyResp.Diagnostics...) - requiresReplace = modifyResp.RequiresReplace - resp.AttributePlan = modifyResp.AttributePlan - resp.Private = modifyResp.Private - - // Only on new errors. - if modifyResp.Diagnostics.HasError() { - return - } - } - - if requiresReplace { - resp.RequiresReplace = append(resp.RequiresReplace, req.AttributePath) - } case fwxschema.AttributeWithBoolPlanModifiers: AttributePlanModifyBool(ctx, attributeWithPlanModifiers, req, resp) case fwxschema.AttributeWithFloat64PlanModifiers: @@ -119,11 +122,6 @@ func AttributeModifyPlan(ctx context.Context, a fwschema.Attribute, req tfsdk.Mo return } - // Temporarily handle tfsdk.Attribute, which always has a nesting mode, until its removed. - if tfsdkAttribute, ok := a.(tfsdk.Attribute); ok && tfsdkAttribute.GetNestingMode() == fwschema.NestingModeUnknown { - return - } - nestedAttributeObject := nestedAttribute.GetNestedObject() nm := nestedAttribute.GetNestingMode() @@ -443,7 +441,7 @@ func AttributeModifyPlan(ctx context.Context, a fwschema.Attribute, req tfsdk.Mo } // AttributePlanModifyBool performs all types.Bool plan modification. -func AttributePlanModifyBool(ctx context.Context, attribute fwxschema.AttributeWithBoolPlanModifiers, req tfsdk.ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { +func AttributePlanModifyBool(ctx context.Context, attribute fwxschema.AttributeWithBoolPlanModifiers, req ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { // Use basetypes.BoolValuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -578,7 +576,7 @@ func AttributePlanModifyBool(ctx context.Context, attribute fwxschema.AttributeW } // AttributePlanModifyFloat64 performs all types.Float64 plan modification. -func AttributePlanModifyFloat64(ctx context.Context, attribute fwxschema.AttributeWithFloat64PlanModifiers, req tfsdk.ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { +func AttributePlanModifyFloat64(ctx context.Context, attribute fwxschema.AttributeWithFloat64PlanModifiers, req ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { // Use basetypes.Float64Valuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -713,7 +711,7 @@ func AttributePlanModifyFloat64(ctx context.Context, attribute fwxschema.Attribu } // AttributePlanModifyInt64 performs all types.Int64 plan modification. -func AttributePlanModifyInt64(ctx context.Context, attribute fwxschema.AttributeWithInt64PlanModifiers, req tfsdk.ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { +func AttributePlanModifyInt64(ctx context.Context, attribute fwxschema.AttributeWithInt64PlanModifiers, req ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { // Use basetypes.Int64Valuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -848,7 +846,7 @@ func AttributePlanModifyInt64(ctx context.Context, attribute fwxschema.Attribute } // AttributePlanModifyList performs all types.List plan modification. -func AttributePlanModifyList(ctx context.Context, attribute fwxschema.AttributeWithListPlanModifiers, req tfsdk.ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { +func AttributePlanModifyList(ctx context.Context, attribute fwxschema.AttributeWithListPlanModifiers, req ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { // Use basetypes.ListValuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -983,7 +981,7 @@ func AttributePlanModifyList(ctx context.Context, attribute fwxschema.AttributeW } // AttributePlanModifyMap performs all types.Map plan modification. -func AttributePlanModifyMap(ctx context.Context, attribute fwxschema.AttributeWithMapPlanModifiers, req tfsdk.ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { +func AttributePlanModifyMap(ctx context.Context, attribute fwxschema.AttributeWithMapPlanModifiers, req ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { // Use basetypes.MapValuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -1118,7 +1116,7 @@ func AttributePlanModifyMap(ctx context.Context, attribute fwxschema.AttributeWi } // AttributePlanModifyNumber performs all types.Number plan modification. -func AttributePlanModifyNumber(ctx context.Context, attribute fwxschema.AttributeWithNumberPlanModifiers, req tfsdk.ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { +func AttributePlanModifyNumber(ctx context.Context, attribute fwxschema.AttributeWithNumberPlanModifiers, req ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { // Use basetypes.NumberValuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -1253,7 +1251,7 @@ func AttributePlanModifyNumber(ctx context.Context, attribute fwxschema.Attribut } // AttributePlanModifyObject performs all types.Object plan modification. -func AttributePlanModifyObject(ctx context.Context, attribute fwxschema.AttributeWithObjectPlanModifiers, req tfsdk.ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { +func AttributePlanModifyObject(ctx context.Context, attribute fwxschema.AttributeWithObjectPlanModifiers, req ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { // Use basetypes.ObjectValuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -1388,7 +1386,7 @@ func AttributePlanModifyObject(ctx context.Context, attribute fwxschema.Attribut } // AttributePlanModifySet performs all types.Set plan modification. -func AttributePlanModifySet(ctx context.Context, attribute fwxschema.AttributeWithSetPlanModifiers, req tfsdk.ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { +func AttributePlanModifySet(ctx context.Context, attribute fwxschema.AttributeWithSetPlanModifiers, req ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { // Use basetypes.SetValuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -1523,7 +1521,7 @@ func AttributePlanModifySet(ctx context.Context, attribute fwxschema.AttributeWi } // AttributePlanModifyString performs all types.String plan modification. -func AttributePlanModifyString(ctx context.Context, attribute fwxschema.AttributeWithStringPlanModifiers, req tfsdk.ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { +func AttributePlanModifyString(ctx context.Context, attribute fwxschema.AttributeWithStringPlanModifiers, req ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { // Use basetypes.StringValuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -1728,7 +1726,7 @@ func NestedAttributeObjectPlanModify(ctx context.Context, o fwschema.NestedAttri return } - nestedAttrReq := tfsdk.ModifyAttributePlanRequest{ + nestedAttrReq := ModifyAttributePlanRequest{ AttributeConfig: nestedAttrConfig, AttributePath: req.Path.AtName(nestedName), AttributePathExpression: req.PathExpression.AtName(nestedName), diff --git a/internal/fwserver/attribute_plan_modification_test.go b/internal/fwserver/attribute_plan_modification_test.go index 20343401a..e98497cef 100644 --- a/internal/fwserver/attribute_plan_modification_test.go +++ b/internal/fwserver/attribute_plan_modification_test.go @@ -37,7 +37,7 @@ func TestAttributeModifyPlan(t *testing.T) { testCases := map[string]struct { attribute fwschema.Attribute - req tfsdk.ModifyAttributePlanRequest + req ModifyAttributePlanRequest expectedResp ModifyAttributePlanResponse }{ "no-plan-modifiers": { @@ -45,7 +45,7 @@ func TestAttributeModifyPlan(t *testing.T) { Type: types.StringType, Required: true, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.StringValue("testvalue"), AttributePath: path.Root("test"), AttributePlan: types.StringValue("testvalue"), @@ -75,7 +75,7 @@ func TestAttributeModifyPlan(t *testing.T) { }, }, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.StringValue("TESTATTRONE"), AttributePath: path.Root("test"), AttributePlan: types.StringValue("TESTATTRONE"), @@ -92,7 +92,7 @@ func TestAttributeModifyPlan(t *testing.T) { planmodifiers.TestAttrPlanPrivateModifierGet{}, }, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.StringValue("TESTATTRONE"), AttributePath: path.Root("test"), AttributePlan: types.StringValue("TESTATTRONE"), @@ -111,7 +111,7 @@ func TestAttributeModifyPlan(t *testing.T) { planmodifiers.TestAttrPlanPrivateModifierSet{}, }, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.StringValue("TESTATTRONE"), AttributePath: path.Root("test"), AttributePlan: types.StringValue("TESTATTRONE"), @@ -140,7 +140,7 @@ func TestAttributeModifyPlan(t *testing.T) { planmodifiers.TestAttrPlanPrivateModifierSet{}, }, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.ListValueMust( types.ObjectType{ AttrTypes: map[string]attr.Type{ @@ -233,7 +233,7 @@ func TestAttributeModifyPlan(t *testing.T) { planmodifiers.TestAttrPlanPrivateModifierSet{}, }, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.SetValueMust( types.ObjectType{ AttrTypes: map[string]attr.Type{ @@ -328,7 +328,7 @@ func TestAttributeModifyPlan(t *testing.T) { NestingMode: fwschema.NestingModeSet, Required: true, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.SetValueMust( types.ObjectType{ AttrTypes: map[string]attr.Type{ @@ -471,7 +471,7 @@ func TestAttributeModifyPlan(t *testing.T) { planmodifiers.TestAttrPlanPrivateModifierSet{}, }, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.MapValueMust( types.ObjectType{ AttrTypes: map[string]attr.Type{ @@ -564,7 +564,7 @@ func TestAttributeModifyPlan(t *testing.T) { planmodifiers.TestAttrPlanPrivateModifierSet{}, }, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ "testing": types.StringType, @@ -611,7 +611,7 @@ func TestAttributeModifyPlan(t *testing.T) { stringplanmodifier.RequiresReplace(), }, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.StringValue("newtestvalue"), AttributePath: path.Root("test"), AttributePlan: types.StringValue("newtestvalue"), @@ -678,7 +678,7 @@ func TestAttributeModifyPlan(t *testing.T) { stringplanmodifier.RequiresReplace(), }, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.StringValue("TESTATTRONE"), AttributePath: path.Root("test"), AttributePlan: types.StringValue("TESTATTRONE"), @@ -753,7 +753,7 @@ func TestAttributeModifyPlan(t *testing.T) { }, }, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.StringValue("testvalue"), AttributePath: path.Root("test"), AttributePlan: types.StringValue("testvalue"), @@ -779,7 +779,7 @@ func TestAttributeModifyPlan(t *testing.T) { }, }, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.StringValue("TESTDIAG"), AttributePath: path.Root("test"), AttributePlan: types.StringValue("TESTDIAG"), @@ -814,7 +814,7 @@ func TestAttributeModifyPlan(t *testing.T) { }, }, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.StringValue("TESTDIAG"), AttributePath: path.Root("test"), AttributePlan: types.StringValue("TESTDIAG"), @@ -857,7 +857,7 @@ func TestAttributePlanModifyBool(t *testing.T) { testCases := map[string]struct { attribute fwxschema.AttributeWithBoolPlanModifiers - request tfsdk.ModifyAttributePlanRequest + request ModifyAttributePlanRequest response *ModifyAttributePlanResponse expected *ModifyAttributePlanResponse }{ @@ -879,7 +879,7 @@ func TestAttributePlanModifyBool(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.BoolValue(true), AttributePlan: types.BoolValue(true), @@ -910,7 +910,7 @@ func TestAttributePlanModifyBool(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.BoolValue(true), @@ -953,7 +953,7 @@ func TestAttributePlanModifyBool(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.BoolValue(true), AttributePlan: types.BoolValue(true), @@ -996,7 +996,7 @@ func TestAttributePlanModifyBool(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.BoolValue(true), AttributePlan: types.BoolNull(), @@ -1038,7 +1038,7 @@ func TestAttributePlanModifyBool(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.BoolValue(true), AttributePlan: types.BoolValue(true), @@ -1081,7 +1081,7 @@ func TestAttributePlanModifyBool(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.BoolNull(), AttributePlan: types.BoolValue(true), @@ -1114,7 +1114,7 @@ func TestAttributePlanModifyBool(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.BoolNull(), AttributePlan: types.BoolValue(true), @@ -1174,7 +1174,7 @@ func TestAttributePlanModifyBool(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.BoolValue(true), AttributePlan: types.BoolValue(true), @@ -1217,7 +1217,7 @@ func TestAttributePlanModifyBool(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.BoolNull(), AttributePlan: types.BoolNull(), @@ -1241,7 +1241,7 @@ func TestAttributePlanModifyBool(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.BoolValue(true), AttributePlan: types.BoolValue(true), @@ -1298,7 +1298,7 @@ func TestAttributePlanModifyBool(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.BoolNull(), AttributePlan: types.BoolUnknown(), @@ -1323,7 +1323,7 @@ func TestAttributePlanModifyBool(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.BoolNull(), AttributePlan: types.BoolValue(true), @@ -1364,7 +1364,7 @@ func TestAttributePlanModifyBool(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.BoolValue(true), AttributePlan: types.BoolValue(true), @@ -1390,7 +1390,7 @@ func TestAttributePlanModifyBool(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.BoolValue(true), AttributePlan: types.BoolValue(true), @@ -1419,7 +1419,7 @@ func TestAttributePlanModifyBool(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.BoolValue(true), AttributePlan: types.BoolValue(true), @@ -1460,7 +1460,7 @@ func TestAttributePlanModifyFloat64(t *testing.T) { testCases := map[string]struct { attribute fwxschema.AttributeWithFloat64PlanModifiers - request tfsdk.ModifyAttributePlanRequest + request ModifyAttributePlanRequest response *ModifyAttributePlanResponse expected *ModifyAttributePlanResponse }{ @@ -1482,7 +1482,7 @@ func TestAttributePlanModifyFloat64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Float64Value(1.2), AttributePlan: types.Float64Value(1.2), @@ -1513,7 +1513,7 @@ func TestAttributePlanModifyFloat64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.Float64Value(1.2), @@ -1556,7 +1556,7 @@ func TestAttributePlanModifyFloat64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Float64Value(1.2), AttributePlan: types.Float64Value(1.2), @@ -1599,7 +1599,7 @@ func TestAttributePlanModifyFloat64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Float64Value(1.2), AttributePlan: types.Float64Null(), @@ -1641,7 +1641,7 @@ func TestAttributePlanModifyFloat64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Float64Value(1.2), AttributePlan: types.Float64Value(1.2), @@ -1684,7 +1684,7 @@ func TestAttributePlanModifyFloat64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Float64Null(), AttributePlan: types.Float64Value(1.2), @@ -1717,7 +1717,7 @@ func TestAttributePlanModifyFloat64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Float64Null(), AttributePlan: types.Float64Value(1.2), @@ -1777,7 +1777,7 @@ func TestAttributePlanModifyFloat64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Float64Value(1.2), AttributePlan: types.Float64Value(1.2), @@ -1820,7 +1820,7 @@ func TestAttributePlanModifyFloat64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Float64Null(), AttributePlan: types.Float64Null(), @@ -1844,7 +1844,7 @@ func TestAttributePlanModifyFloat64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Float64Value(1.2), AttributePlan: types.Float64Value(1.2), @@ -1901,7 +1901,7 @@ func TestAttributePlanModifyFloat64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Float64Null(), AttributePlan: types.Float64Unknown(), @@ -1926,7 +1926,7 @@ func TestAttributePlanModifyFloat64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Float64Null(), AttributePlan: types.Float64Value(1.2), @@ -1967,7 +1967,7 @@ func TestAttributePlanModifyFloat64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Float64Value(1.2), AttributePlan: types.Float64Value(1.2), @@ -1993,7 +1993,7 @@ func TestAttributePlanModifyFloat64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Float64Value(1.2), AttributePlan: types.Float64Value(1.2), @@ -2022,7 +2022,7 @@ func TestAttributePlanModifyFloat64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Float64Value(1.2), AttributePlan: types.Float64Value(1.2), @@ -2063,7 +2063,7 @@ func TestAttributePlanModifyInt64(t *testing.T) { testCases := map[string]struct { attribute fwxschema.AttributeWithInt64PlanModifiers - request tfsdk.ModifyAttributePlanRequest + request ModifyAttributePlanRequest response *ModifyAttributePlanResponse expected *ModifyAttributePlanResponse }{ @@ -2085,7 +2085,7 @@ func TestAttributePlanModifyInt64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Int64Value(1), AttributePlan: types.Int64Value(1), @@ -2116,7 +2116,7 @@ func TestAttributePlanModifyInt64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.Int64Value(1), @@ -2159,7 +2159,7 @@ func TestAttributePlanModifyInt64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Int64Value(1), AttributePlan: types.Int64Value(1), @@ -2202,7 +2202,7 @@ func TestAttributePlanModifyInt64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Int64Value(1), AttributePlan: types.Int64Null(), @@ -2244,7 +2244,7 @@ func TestAttributePlanModifyInt64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Int64Value(1), AttributePlan: types.Int64Value(1), @@ -2287,7 +2287,7 @@ func TestAttributePlanModifyInt64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Int64Null(), AttributePlan: types.Int64Value(1), @@ -2320,7 +2320,7 @@ func TestAttributePlanModifyInt64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Int64Null(), AttributePlan: types.Int64Value(1), @@ -2380,7 +2380,7 @@ func TestAttributePlanModifyInt64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Int64Value(1), AttributePlan: types.Int64Value(1), @@ -2423,7 +2423,7 @@ func TestAttributePlanModifyInt64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Int64Null(), AttributePlan: types.Int64Null(), @@ -2447,7 +2447,7 @@ func TestAttributePlanModifyInt64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Int64Value(1), AttributePlan: types.Int64Value(1), @@ -2504,7 +2504,7 @@ func TestAttributePlanModifyInt64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Int64Null(), AttributePlan: types.Int64Unknown(), @@ -2529,7 +2529,7 @@ func TestAttributePlanModifyInt64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Int64Null(), AttributePlan: types.Int64Value(1), @@ -2570,7 +2570,7 @@ func TestAttributePlanModifyInt64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Int64Value(1), AttributePlan: types.Int64Value(1), @@ -2596,7 +2596,7 @@ func TestAttributePlanModifyInt64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Int64Value(1), AttributePlan: types.Int64Value(1), @@ -2625,7 +2625,7 @@ func TestAttributePlanModifyInt64(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Int64Value(1), AttributePlan: types.Int64Value(1), @@ -2666,7 +2666,7 @@ func TestAttributePlanModifyList(t *testing.T) { testCases := map[string]struct { attribute fwxschema.AttributeWithListPlanModifiers - request tfsdk.ModifyAttributePlanRequest + request ModifyAttributePlanRequest response *ModifyAttributePlanResponse expected *ModifyAttributePlanResponse }{ @@ -2688,7 +2688,7 @@ func TestAttributePlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -2719,7 +2719,7 @@ func TestAttributePlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -2765,7 +2765,7 @@ func TestAttributePlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -2811,7 +2811,7 @@ func TestAttributePlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.ListNull(types.StringType), @@ -2856,7 +2856,7 @@ func TestAttributePlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -2902,7 +2902,7 @@ func TestAttributePlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListNull(types.StringType), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -2935,7 +2935,7 @@ func TestAttributePlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListNull(types.StringType), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -2998,7 +2998,7 @@ func TestAttributePlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -3044,7 +3044,7 @@ func TestAttributePlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListNull(types.StringType), AttributePlan: types.ListNull(types.StringType), @@ -3068,7 +3068,7 @@ func TestAttributePlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -3125,7 +3125,7 @@ func TestAttributePlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListNull(types.StringType), AttributePlan: types.ListUnknown(types.StringType), @@ -3150,7 +3150,7 @@ func TestAttributePlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListNull(types.StringType), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -3191,7 +3191,7 @@ func TestAttributePlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -3217,7 +3217,7 @@ func TestAttributePlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -3246,7 +3246,7 @@ func TestAttributePlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -3287,7 +3287,7 @@ func TestAttributePlanModifyMap(t *testing.T) { testCases := map[string]struct { attribute fwxschema.AttributeWithMapPlanModifiers - request tfsdk.ModifyAttributePlanRequest + request ModifyAttributePlanRequest response *ModifyAttributePlanResponse expected *ModifyAttributePlanResponse }{ @@ -3309,7 +3309,7 @@ func TestAttributePlanModifyMap(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.MapValueMust( types.StringType, @@ -3365,7 +3365,7 @@ func TestAttributePlanModifyMap(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.MapValueMust( @@ -3438,7 +3438,7 @@ func TestAttributePlanModifyMap(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.MapValueMust( types.StringType, @@ -3516,7 +3516,7 @@ func TestAttributePlanModifyMap(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.MapValueMust( types.StringType, @@ -3568,7 +3568,7 @@ func TestAttributePlanModifyMap(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.MapValueMust( types.StringType, @@ -3646,7 +3646,7 @@ func TestAttributePlanModifyMap(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.MapNull(types.StringType), AttributePlan: types.MapValueMust( @@ -3694,7 +3694,7 @@ func TestAttributePlanModifyMap(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.MapNull(types.StringType), AttributePlan: types.MapValueMust( @@ -3774,7 +3774,7 @@ func TestAttributePlanModifyMap(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.MapValueMust( types.StringType, @@ -3852,7 +3852,7 @@ func TestAttributePlanModifyMap(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.MapNull(types.StringType), AttributePlan: types.MapNull(types.StringType), @@ -3881,7 +3881,7 @@ func TestAttributePlanModifyMap(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.MapValueMust( types.StringType, @@ -3968,7 +3968,7 @@ func TestAttributePlanModifyMap(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.MapNull(types.StringType), AttributePlan: types.MapUnknown(types.StringType), @@ -3998,7 +3998,7 @@ func TestAttributePlanModifyMap(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.MapNull(types.StringType), AttributePlan: types.MapValueMust( @@ -4054,7 +4054,7 @@ func TestAttributePlanModifyMap(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.MapValueMust( types.StringType, @@ -4105,7 +4105,7 @@ func TestAttributePlanModifyMap(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.MapValueMust( types.StringType, @@ -4159,7 +4159,7 @@ func TestAttributePlanModifyMap(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.MapValueMust( types.StringType, @@ -4225,7 +4225,7 @@ func TestAttributePlanModifyNumber(t *testing.T) { testCases := map[string]struct { attribute fwxschema.AttributeWithNumberPlanModifiers - request tfsdk.ModifyAttributePlanRequest + request ModifyAttributePlanRequest response *ModifyAttributePlanResponse expected *ModifyAttributePlanResponse }{ @@ -4247,7 +4247,7 @@ func TestAttributePlanModifyNumber(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.NumberValue(big.NewFloat(1)), AttributePlan: types.NumberValue(big.NewFloat(1)), @@ -4278,7 +4278,7 @@ func TestAttributePlanModifyNumber(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.NumberValue(big.NewFloat(1)), @@ -4321,7 +4321,7 @@ func TestAttributePlanModifyNumber(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.NumberValue(big.NewFloat(1)), AttributePlan: types.NumberValue(big.NewFloat(1)), @@ -4364,7 +4364,7 @@ func TestAttributePlanModifyNumber(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.NumberValue(big.NewFloat(1)), AttributePlan: types.NumberNull(), @@ -4406,7 +4406,7 @@ func TestAttributePlanModifyNumber(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.NumberValue(big.NewFloat(1)), AttributePlan: types.NumberValue(big.NewFloat(1)), @@ -4449,7 +4449,7 @@ func TestAttributePlanModifyNumber(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.NumberNull(), AttributePlan: types.NumberValue(big.NewFloat(1)), @@ -4482,7 +4482,7 @@ func TestAttributePlanModifyNumber(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.NumberNull(), AttributePlan: types.NumberValue(big.NewFloat(1)), @@ -4542,7 +4542,7 @@ func TestAttributePlanModifyNumber(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.NumberValue(big.NewFloat(1)), AttributePlan: types.NumberValue(big.NewFloat(1)), @@ -4585,7 +4585,7 @@ func TestAttributePlanModifyNumber(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.NumberNull(), AttributePlan: types.NumberNull(), @@ -4609,7 +4609,7 @@ func TestAttributePlanModifyNumber(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.NumberValue(big.NewFloat(1)), AttributePlan: types.NumberValue(big.NewFloat(1)), @@ -4666,7 +4666,7 @@ func TestAttributePlanModifyNumber(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.NumberNull(), AttributePlan: types.NumberUnknown(), @@ -4691,7 +4691,7 @@ func TestAttributePlanModifyNumber(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.NumberNull(), AttributePlan: types.NumberValue(big.NewFloat(1)), @@ -4732,7 +4732,7 @@ func TestAttributePlanModifyNumber(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.NumberValue(big.NewFloat(1)), AttributePlan: types.NumberValue(big.NewFloat(1)), @@ -4758,7 +4758,7 @@ func TestAttributePlanModifyNumber(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.NumberValue(big.NewFloat(1)), AttributePlan: types.NumberValue(big.NewFloat(1)), @@ -4787,7 +4787,7 @@ func TestAttributePlanModifyNumber(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.NumberValue(big.NewFloat(1)), AttributePlan: types.NumberValue(big.NewFloat(1)), @@ -4828,7 +4828,7 @@ func TestAttributePlanModifyObject(t *testing.T) { testCases := map[string]struct { attribute fwxschema.AttributeWithObjectPlanModifiers - request tfsdk.ModifyAttributePlanRequest + request ModifyAttributePlanRequest response *ModifyAttributePlanResponse expected *ModifyAttributePlanResponse }{ @@ -4850,7 +4850,7 @@ func TestAttributePlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ @@ -4916,7 +4916,7 @@ func TestAttributePlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.ObjectValueMust( @@ -5007,7 +5007,7 @@ func TestAttributePlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ @@ -5105,7 +5105,7 @@ func TestAttributePlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ @@ -5175,7 +5175,7 @@ func TestAttributePlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ @@ -5273,7 +5273,7 @@ func TestAttributePlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectNull(map[string]attr.Type{ "testattr": types.StringType, @@ -5331,7 +5331,7 @@ func TestAttributePlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectNull(map[string]attr.Type{ "testattr": types.StringType, @@ -5429,7 +5429,7 @@ func TestAttributePlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ @@ -5527,7 +5527,7 @@ func TestAttributePlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectNull(map[string]attr.Type{ "testattr": types.StringType, @@ -5566,7 +5566,7 @@ func TestAttributePlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ @@ -5665,7 +5665,7 @@ func TestAttributePlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectNull(map[string]attr.Type{ "testattr": types.StringType, @@ -5705,7 +5705,7 @@ func TestAttributePlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectNull(map[string]attr.Type{ "testattr": types.StringType, @@ -5771,7 +5771,7 @@ func TestAttributePlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ @@ -5832,7 +5832,7 @@ func TestAttributePlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ @@ -5896,7 +5896,7 @@ func TestAttributePlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ @@ -5972,7 +5972,7 @@ func TestAttributePlanModifySet(t *testing.T) { testCases := map[string]struct { attribute fwxschema.AttributeWithSetPlanModifiers - request tfsdk.ModifyAttributePlanRequest + request ModifyAttributePlanRequest response *ModifyAttributePlanResponse expected *ModifyAttributePlanResponse }{ @@ -5994,7 +5994,7 @@ func TestAttributePlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -6025,7 +6025,7 @@ func TestAttributePlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -6071,7 +6071,7 @@ func TestAttributePlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -6117,7 +6117,7 @@ func TestAttributePlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.SetNull(types.StringType), @@ -6162,7 +6162,7 @@ func TestAttributePlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -6208,7 +6208,7 @@ func TestAttributePlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetNull(types.StringType), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -6241,7 +6241,7 @@ func TestAttributePlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetNull(types.StringType), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -6304,7 +6304,7 @@ func TestAttributePlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -6350,7 +6350,7 @@ func TestAttributePlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetNull(types.StringType), AttributePlan: types.SetNull(types.StringType), @@ -6374,7 +6374,7 @@ func TestAttributePlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -6431,7 +6431,7 @@ func TestAttributePlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetNull(types.StringType), AttributePlan: types.SetUnknown(types.StringType), @@ -6456,7 +6456,7 @@ func TestAttributePlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetNull(types.StringType), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -6497,7 +6497,7 @@ func TestAttributePlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -6523,7 +6523,7 @@ func TestAttributePlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -6552,7 +6552,7 @@ func TestAttributePlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -6593,7 +6593,7 @@ func TestAttributePlanModifyString(t *testing.T) { testCases := map[string]struct { attribute fwxschema.AttributeWithStringPlanModifiers - request tfsdk.ModifyAttributePlanRequest + request ModifyAttributePlanRequest response *ModifyAttributePlanResponse expected *ModifyAttributePlanResponse }{ @@ -6615,7 +6615,7 @@ func TestAttributePlanModifyString(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.StringValue("testvalue"), AttributePlan: types.StringValue("testvalue"), @@ -6646,7 +6646,7 @@ func TestAttributePlanModifyString(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.StringValue("testvalue"), @@ -6689,7 +6689,7 @@ func TestAttributePlanModifyString(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.StringValue("testvalue"), AttributePlan: types.StringValue("testvalue"), @@ -6732,7 +6732,7 @@ func TestAttributePlanModifyString(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.StringValue("testvalue"), AttributePlan: types.StringNull(), @@ -6774,7 +6774,7 @@ func TestAttributePlanModifyString(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.StringValue("testvalue"), AttributePlan: types.StringValue("testvalue"), @@ -6817,7 +6817,7 @@ func TestAttributePlanModifyString(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.StringNull(), AttributePlan: types.StringValue("testvalue"), @@ -6850,7 +6850,7 @@ func TestAttributePlanModifyString(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.StringNull(), AttributePlan: types.StringValue("testvalue"), @@ -6910,7 +6910,7 @@ func TestAttributePlanModifyString(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.StringValue("testvalue"), AttributePlan: types.StringValue("testvalue"), @@ -6953,7 +6953,7 @@ func TestAttributePlanModifyString(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.StringNull(), AttributePlan: types.StringNull(), @@ -6977,7 +6977,7 @@ func TestAttributePlanModifyString(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.StringValue("testvalue"), AttributePlan: types.StringValue("testvalue"), @@ -7034,7 +7034,7 @@ func TestAttributePlanModifyString(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.StringNull(), AttributePlan: types.StringUnknown(), @@ -7059,7 +7059,7 @@ func TestAttributePlanModifyString(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.StringNull(), AttributePlan: types.StringValue("testvalue"), @@ -7100,7 +7100,7 @@ func TestAttributePlanModifyString(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.StringValue("testvalue"), AttributePlan: types.StringValue("testvalue"), @@ -7126,7 +7126,7 @@ func TestAttributePlanModifyString(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.StringValue("testvalue"), AttributePlan: types.StringValue("testvalue"), @@ -7155,7 +7155,7 @@ func TestAttributePlanModifyString(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.StringValue("testvalue"), AttributePlan: types.StringValue("testvalue"), diff --git a/internal/fwserver/attribute_validation.go b/internal/fwserver/attribute_validation.go index 90dd6d4bc..1425c5692 100644 --- a/internal/fwserver/attribute_validation.go +++ b/internal/fwserver/attribute_validation.go @@ -4,46 +4,54 @@ import ( "context" "fmt" + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" "github.com/hashicorp/terraform-plugin-framework/internal/fwschema/fwxschema" "github.com/hashicorp/terraform-plugin-framework/internal/fwschemadata" "github.com/hashicorp/terraform-plugin-framework/internal/logging" + "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/tfsdk" "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) +// ValidateAttributeRequest repesents a request for attribute validation. +type ValidateAttributeRequest struct { + // AttributePath contains the path of the attribute. Use this path for any + // response diagnostics. + AttributePath path.Path + + // AttributePathExpression contains the expression matching the exact path + // of the attribute. + AttributePathExpression path.Expression + + // AttributeConfig contains the value of the attribute in the configuration. + AttributeConfig attr.Value + + // Config contains the entire configuration of the data source, provider, or resource. + Config tfsdk.Config +} + +// ValidateAttributeResponse represents a response to a +// ValidateAttributeRequest. An instance of this response struct is +// automatically passed through to each AttributeValidator. +type ValidateAttributeResponse struct { + // Diagnostics report errors or warnings related to validating the data + // source configuration. An empty slice indicates success, with no warnings + // or errors generated. + Diagnostics diag.Diagnostics +} + // AttributeValidate performs all Attribute validation. // // TODO: Clean up this abstraction back into an internal Attribute type method. // The extra Attribute parameter is a carry-over of creating the proto6server // package from the tfsdk package and not wanting to export the method. // Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/365 -func AttributeValidate(ctx context.Context, a fwschema.Attribute, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) { +func AttributeValidate(ctx context.Context, a fwschema.Attribute, req ValidateAttributeRequest, resp *ValidateAttributeResponse) { ctx = logging.FrameworkWithAttributePath(ctx, req.AttributePath.String()) - tfsdkAttribute, ok := a.(tfsdk.Attribute) - - if ok && tfsdkAttribute.GetType() == nil { - resp.Diagnostics.AddAttributeError( - req.AttributePath, - "Invalid Attribute Definition", - "Attribute must define either Attributes or Type. This is always a problem with the provider and should be reported to the provider developer.", - ) - - return - } - - if ok && tfsdkAttribute.GetNestingMode() == fwschema.NestingModeUnknown && tfsdkAttribute.Attributes != nil { - resp.Diagnostics.AddAttributeError( - req.AttributePath, - "Invalid Attribute Definition", - "Attribute cannot define both Attributes and Type. This is always a problem with the provider and should be reported to the provider developer.", - ) - - return - } - if !a.IsRequired() && !a.IsOptional() && !a.IsComputed() { resp.Diagnostics.AddAttributeError( req.AttributePath, @@ -98,25 +106,6 @@ func AttributeValidate(ctx context.Context, a fwschema.Attribute, req tfsdk.Vali req.AttributeConfig = attributeConfig switch attributeWithValidators := a.(type) { - // Legacy tfsdk.AttributeValidator handling - case fwxschema.AttributeWithValidators: - for _, validator := range attributeWithValidators.GetValidators() { - logging.FrameworkDebug( - ctx, - "Calling provider defined AttributeValidator", - map[string]interface{}{ - logging.KeyDescription: validator.Description(ctx), - }, - ) - validator.Validate(ctx, req, resp) - logging.FrameworkDebug( - ctx, - "Called provider defined AttributeValidator", - map[string]interface{}{ - logging.KeyDescription: validator.Description(ctx), - }, - ) - } case fwxschema.AttributeWithBoolValidators: AttributeValidateBool(ctx, attributeWithValidators, req, resp) case fwxschema.AttributeWithFloat64Validators: @@ -150,7 +139,7 @@ func AttributeValidate(ctx context.Context, a fwschema.Attribute, req tfsdk.Vali } // AttributeValidateBool performs all types.Bool validation. -func AttributeValidateBool(ctx context.Context, attribute fwxschema.AttributeWithBoolValidators, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) { +func AttributeValidateBool(ctx context.Context, attribute fwxschema.AttributeWithBoolValidators, req ValidateAttributeRequest, resp *ValidateAttributeResponse) { // Use basetypes.BoolValuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -215,7 +204,7 @@ func AttributeValidateBool(ctx context.Context, attribute fwxschema.AttributeWit } // AttributeValidateFloat64 performs all types.Float64 validation. -func AttributeValidateFloat64(ctx context.Context, attribute fwxschema.AttributeWithFloat64Validators, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) { +func AttributeValidateFloat64(ctx context.Context, attribute fwxschema.AttributeWithFloat64Validators, req ValidateAttributeRequest, resp *ValidateAttributeResponse) { // Use basetypes.Float64Valuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -280,7 +269,7 @@ func AttributeValidateFloat64(ctx context.Context, attribute fwxschema.Attribute } // AttributeValidateInt64 performs all types.Int64 validation. -func AttributeValidateInt64(ctx context.Context, attribute fwxschema.AttributeWithInt64Validators, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) { +func AttributeValidateInt64(ctx context.Context, attribute fwxschema.AttributeWithInt64Validators, req ValidateAttributeRequest, resp *ValidateAttributeResponse) { // Use basetypes.Int64Valuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -345,7 +334,7 @@ func AttributeValidateInt64(ctx context.Context, attribute fwxschema.AttributeWi } // AttributeValidateList performs all types.List validation. -func AttributeValidateList(ctx context.Context, attribute fwxschema.AttributeWithListValidators, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) { +func AttributeValidateList(ctx context.Context, attribute fwxschema.AttributeWithListValidators, req ValidateAttributeRequest, resp *ValidateAttributeResponse) { // Use basetypes.ListValuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -410,7 +399,7 @@ func AttributeValidateList(ctx context.Context, attribute fwxschema.AttributeWit } // AttributeValidateMap performs all types.Map validation. -func AttributeValidateMap(ctx context.Context, attribute fwxschema.AttributeWithMapValidators, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) { +func AttributeValidateMap(ctx context.Context, attribute fwxschema.AttributeWithMapValidators, req ValidateAttributeRequest, resp *ValidateAttributeResponse) { // Use basetypes.MapValuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -475,7 +464,7 @@ func AttributeValidateMap(ctx context.Context, attribute fwxschema.AttributeWith } // AttributeValidateNumber performs all types.Number validation. -func AttributeValidateNumber(ctx context.Context, attribute fwxschema.AttributeWithNumberValidators, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) { +func AttributeValidateNumber(ctx context.Context, attribute fwxschema.AttributeWithNumberValidators, req ValidateAttributeRequest, resp *ValidateAttributeResponse) { // Use basetypes.NumberValuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -540,7 +529,7 @@ func AttributeValidateNumber(ctx context.Context, attribute fwxschema.AttributeW } // AttributeValidateObject performs all types.Object validation. -func AttributeValidateObject(ctx context.Context, attribute fwxschema.AttributeWithObjectValidators, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) { +func AttributeValidateObject(ctx context.Context, attribute fwxschema.AttributeWithObjectValidators, req ValidateAttributeRequest, resp *ValidateAttributeResponse) { // Use basetypes.ObjectValuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -605,7 +594,7 @@ func AttributeValidateObject(ctx context.Context, attribute fwxschema.AttributeW } // AttributeValidateSet performs all types.Set validation. -func AttributeValidateSet(ctx context.Context, attribute fwxschema.AttributeWithSetValidators, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) { +func AttributeValidateSet(ctx context.Context, attribute fwxschema.AttributeWithSetValidators, req ValidateAttributeRequest, resp *ValidateAttributeResponse) { // Use basetypes.SetValuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -670,7 +659,7 @@ func AttributeValidateSet(ctx context.Context, attribute fwxschema.AttributeWith } // AttributeValidateString performs all types.String validation. -func AttributeValidateString(ctx context.Context, attribute fwxschema.AttributeWithStringValidators, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) { +func AttributeValidateString(ctx context.Context, attribute fwxschema.AttributeWithStringValidators, req ValidateAttributeRequest, resp *ValidateAttributeResponse) { // Use basetypes.StringValuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -740,19 +729,13 @@ func AttributeValidateString(ctx context.Context, attribute fwxschema.AttributeW // The extra Attribute parameter is a carry-over of creating the proto6server // package from the tfsdk package and not wanting to export the method. // Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/365 -func AttributeValidateNestedAttributes(ctx context.Context, a fwschema.Attribute, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) { +func AttributeValidateNestedAttributes(ctx context.Context, a fwschema.Attribute, req ValidateAttributeRequest, resp *ValidateAttributeResponse) { nestedAttribute, ok := a.(fwschema.NestedAttribute) if !ok { return } - tfsdkAttribute, ok := a.(tfsdk.Attribute) //nolint:staticcheck // Handle tfsdk.Attribute until its removed. - - if ok && tfsdkAttribute.GetNestingMode() == fwschema.NestingModeUnknown { - return - } - nestedAttributeObject := nestedAttribute.GetNestedObject() nm := nestedAttribute.GetNestingMode() @@ -779,13 +762,13 @@ func AttributeValidateNestedAttributes(ctx context.Context, a fwschema.Attribute } for idx, value := range l.Elements() { - nestedAttributeObjectReq := tfsdk.ValidateAttributeRequest{ + nestedAttributeObjectReq := ValidateAttributeRequest{ AttributeConfig: value, AttributePath: req.AttributePath.AtListIndex(idx), AttributePathExpression: req.AttributePathExpression.AtListIndex(idx), Config: req.Config, } - nestedAttributeObjectResp := &tfsdk.ValidateAttributeResponse{} + nestedAttributeObjectResp := &ValidateAttributeResponse{} NestedAttributeObjectValidate(ctx, nestedAttributeObject, nestedAttributeObjectReq, nestedAttributeObjectResp) @@ -813,13 +796,13 @@ func AttributeValidateNestedAttributes(ctx context.Context, a fwschema.Attribute } for _, value := range s.Elements() { - nestedAttributeObjectReq := tfsdk.ValidateAttributeRequest{ + nestedAttributeObjectReq := ValidateAttributeRequest{ AttributeConfig: value, AttributePath: req.AttributePath.AtSetValue(value), AttributePathExpression: req.AttributePathExpression.AtSetValue(value), Config: req.Config, } - nestedAttributeObjectResp := &tfsdk.ValidateAttributeResponse{} + nestedAttributeObjectResp := &ValidateAttributeResponse{} NestedAttributeObjectValidate(ctx, nestedAttributeObject, nestedAttributeObjectReq, nestedAttributeObjectResp) @@ -847,13 +830,13 @@ func AttributeValidateNestedAttributes(ctx context.Context, a fwschema.Attribute } for key, value := range m.Elements() { - nestedAttributeObjectReq := tfsdk.ValidateAttributeRequest{ + nestedAttributeObjectReq := ValidateAttributeRequest{ AttributeConfig: value, AttributePath: req.AttributePath.AtMapKey(key), AttributePathExpression: req.AttributePathExpression.AtMapKey(key), Config: req.Config, } - nestedAttributeObjectResp := &tfsdk.ValidateAttributeResponse{} + nestedAttributeObjectResp := &ValidateAttributeResponse{} NestedAttributeObjectValidate(ctx, nestedAttributeObject, nestedAttributeObjectReq, nestedAttributeObjectResp) @@ -884,13 +867,13 @@ func AttributeValidateNestedAttributes(ctx context.Context, a fwschema.Attribute return } - nestedAttributeObjectReq := tfsdk.ValidateAttributeRequest{ + nestedAttributeObjectReq := ValidateAttributeRequest{ AttributeConfig: o, AttributePath: req.AttributePath, AttributePathExpression: req.AttributePathExpression, Config: req.Config, } - nestedAttributeObjectResp := &tfsdk.ValidateAttributeResponse{} + nestedAttributeObjectResp := &ValidateAttributeResponse{} NestedAttributeObjectValidate(ctx, nestedAttributeObject, nestedAttributeObjectReq, nestedAttributeObjectResp) @@ -907,7 +890,7 @@ func AttributeValidateNestedAttributes(ctx context.Context, a fwschema.Attribute } } -func NestedAttributeObjectValidate(ctx context.Context, o fwschema.NestedAttributeObject, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) { +func NestedAttributeObjectValidate(ctx context.Context, o fwschema.NestedAttributeObject, req ValidateAttributeRequest, resp *ValidateAttributeResponse) { objectWithValidators, ok := o.(fwxschema.NestedAttributeObjectWithValidators) if ok { @@ -970,12 +953,12 @@ func NestedAttributeObjectValidate(ctx context.Context, o fwschema.NestedAttribu } for nestedName, nestedAttr := range o.GetAttributes() { - nestedAttrReq := tfsdk.ValidateAttributeRequest{ + nestedAttrReq := ValidateAttributeRequest{ AttributePath: req.AttributePath.AtName(nestedName), AttributePathExpression: req.AttributePathExpression.AtName(nestedName), Config: req.Config, } - nestedAttrResp := &tfsdk.ValidateAttributeResponse{} + nestedAttrResp := &ValidateAttributeResponse{} AttributeValidate(ctx, nestedAttr, nestedAttrReq, nestedAttrResp) diff --git a/internal/fwserver/attribute_validation_test.go b/internal/fwserver/attribute_validation_test.go index a6c3f90ed..7a4ac765d 100644 --- a/internal/fwserver/attribute_validation_test.go +++ b/internal/fwserver/attribute_validation_test.go @@ -26,11 +26,11 @@ func TestAttributeValidate(t *testing.T) { t.Parallel() testCases := map[string]struct { - req tfsdk.ValidateAttributeRequest - resp tfsdk.ValidateAttributeResponse + req ValidateAttributeRequest + resp ValidateAttributeResponse }{ "missing-required-optional-and-computed": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue(tftypes.Object{ @@ -49,7 +49,7 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeErrorDiagnostic( path.Root("test"), @@ -60,7 +60,7 @@ func TestAttributeValidate(t *testing.T) { }, }, "config-error": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue(tftypes.Object{ @@ -80,7 +80,7 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeErrorDiagnostic( path.Root("test"), @@ -92,7 +92,7 @@ func TestAttributeValidate(t *testing.T) { }, }, "config-computed-null": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue(tftypes.Object{ @@ -112,10 +112,10 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "config-computed-unknown": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue(tftypes.Object{ @@ -135,7 +135,7 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeErrorDiagnostic( path.Root("test"), @@ -147,7 +147,7 @@ func TestAttributeValidate(t *testing.T) { }, }, "config-computed-value": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue(tftypes.Object{ @@ -167,7 +167,7 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeErrorDiagnostic( path.Root("test"), @@ -179,7 +179,7 @@ func TestAttributeValidate(t *testing.T) { }, }, "config-optional-computed-null": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue(tftypes.Object{ @@ -200,10 +200,10 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "config-optional-computed-unknown": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue(tftypes.Object{ @@ -224,10 +224,10 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "config-optional-computed-value": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue(tftypes.Object{ @@ -248,10 +248,10 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "config-required-null": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue(tftypes.Object{ @@ -271,7 +271,7 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeErrorDiagnostic( path.Root("test"), @@ -283,7 +283,7 @@ func TestAttributeValidate(t *testing.T) { }, }, "config-required-unknown": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue(tftypes.Object{ @@ -303,10 +303,10 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "config-required-value": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue(tftypes.Object{ @@ -326,10 +326,10 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "no-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue(tftypes.Object{ @@ -349,10 +349,10 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "deprecation-message-known": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue(tftypes.Object{ @@ -373,7 +373,7 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("test"), @@ -384,7 +384,7 @@ func TestAttributeValidate(t *testing.T) { }, }, "deprecation-message-null": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue(tftypes.Object{ @@ -405,10 +405,10 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "deprecation-message-unknown": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue(tftypes.Object{ @@ -429,10 +429,10 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "warnings": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue(tftypes.Object{ @@ -463,7 +463,7 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ testWarningDiagnostic1, testWarningDiagnostic2, @@ -471,7 +471,7 @@ func TestAttributeValidate(t *testing.T) { }, }, "errors": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue(tftypes.Object{ @@ -502,7 +502,7 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ testErrorDiagnostic1, testErrorDiagnostic2, @@ -510,7 +510,7 @@ func TestAttributeValidate(t *testing.T) { }, }, "type-with-validate-error": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue(tftypes.Object{ @@ -530,14 +530,14 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ testtypes.TestErrorDiagnostic(path.Root("test")), }, }, }, "type-with-validate-warning": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue(tftypes.Object{ @@ -557,14 +557,14 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ testtypes.TestWarningDiagnostic(path.Root("test")), }, }, }, "nested-attr-list-no-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -621,10 +621,10 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "nested-custom-attr-list-no-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -690,10 +690,10 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "nested-attr-list-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -756,14 +756,14 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ testErrorDiagnostic1, }, }, }, "nested-custom-attr-list-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -835,14 +835,14 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ testErrorDiagnostic1, }, }, }, "nested-attr-map-no-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -899,10 +899,10 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "nested-custom-attr-map-no-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -968,10 +968,10 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "nested-attr-map-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -1034,14 +1034,14 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ testErrorDiagnostic1, }, }, }, "nested-custom-attr-map-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -1113,14 +1113,14 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ testErrorDiagnostic1, }, }, }, "nested-attr-set-no-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -1177,10 +1177,10 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "nested-custom-attr-set-no-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -1246,10 +1246,10 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "nested-attr-set-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -1312,14 +1312,14 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ testErrorDiagnostic1, }, }, }, "nested-custom-attr-set-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -1391,14 +1391,14 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ testErrorDiagnostic1, }, }, }, "nested-attr-single-no-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -1442,10 +1442,10 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "nested-custom-attr-single-no-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -1496,10 +1496,10 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "nested-attr-single-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -1548,14 +1548,14 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ testErrorDiagnostic1, }, }, }, "nested-custom-attr-single-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -1611,7 +1611,7 @@ func TestAttributeValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ testErrorDiagnostic1, }, @@ -1626,7 +1626,7 @@ func TestAttributeValidate(t *testing.T) { ctx := context.Background() - var got tfsdk.ValidateAttributeResponse + var got ValidateAttributeResponse attribute, diags := tc.req.Config.Schema.AttributeAtPath(ctx, tc.req.AttributePath) @@ -1648,9 +1648,9 @@ func TestAttributeValidateBool(t *testing.T) { testCases := map[string]struct { attribute fwxschema.AttributeWithBoolValidators - request tfsdk.ValidateAttributeRequest - response *tfsdk.ValidateAttributeResponse - expected *tfsdk.ValidateAttributeResponse + request ValidateAttributeRequest + response *ValidateAttributeResponse + expected *ValidateAttributeResponse }{ "request-path": { attribute: testschema.AttributeWithBoolValidators{ @@ -1670,12 +1670,12 @@ func TestAttributeValidateBool(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.BoolValue(true), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-pathexpression": { attribute: testschema.AttributeWithBoolValidators{ @@ -1695,13 +1695,13 @@ func TestAttributeValidateBool(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.BoolValue(true), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-config": { attribute: testschema.AttributeWithBoolValidators{ @@ -1732,7 +1732,7 @@ func TestAttributeValidateBool(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.BoolValue(true), Config: tfsdk.Config{ @@ -1748,8 +1748,8 @@ func TestAttributeValidateBool(t *testing.T) { ), }, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-configvalue": { attribute: testschema.AttributeWithBoolValidators{ @@ -1769,12 +1769,12 @@ func TestAttributeValidateBool(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.BoolValue(true), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "response-diagnostics": { attribute: testschema.AttributeWithBoolValidators{ @@ -1787,11 +1787,11 @@ func TestAttributeValidateBool(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.BoolValue(true), }, - response: &tfsdk.ValidateAttributeResponse{ + response: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -1805,7 +1805,7 @@ func TestAttributeValidateBool(t *testing.T) { ), }, }, - expected: &tfsdk.ValidateAttributeResponse{ + expected: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -1852,9 +1852,9 @@ func TestAttributeValidateFloat64(t *testing.T) { testCases := map[string]struct { attribute fwxschema.AttributeWithFloat64Validators - request tfsdk.ValidateAttributeRequest - response *tfsdk.ValidateAttributeResponse - expected *tfsdk.ValidateAttributeResponse + request ValidateAttributeRequest + response *ValidateAttributeResponse + expected *ValidateAttributeResponse }{ "request-path": { attribute: testschema.AttributeWithFloat64Validators{ @@ -1874,12 +1874,12 @@ func TestAttributeValidateFloat64(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Float64Value(1.2), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-pathexpression": { attribute: testschema.AttributeWithFloat64Validators{ @@ -1899,13 +1899,13 @@ func TestAttributeValidateFloat64(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.Float64Value(1.2), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-config": { attribute: testschema.AttributeWithFloat64Validators{ @@ -1936,7 +1936,7 @@ func TestAttributeValidateFloat64(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Float64Value(1.2), Config: tfsdk.Config{ @@ -1952,8 +1952,8 @@ func TestAttributeValidateFloat64(t *testing.T) { ), }, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-configvalue": { attribute: testschema.AttributeWithFloat64Validators{ @@ -1973,12 +1973,12 @@ func TestAttributeValidateFloat64(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Float64Value(1.2), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "response-diagnostics": { attribute: testschema.AttributeWithFloat64Validators{ @@ -1991,11 +1991,11 @@ func TestAttributeValidateFloat64(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Float64Value(1.2), }, - response: &tfsdk.ValidateAttributeResponse{ + response: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -2009,7 +2009,7 @@ func TestAttributeValidateFloat64(t *testing.T) { ), }, }, - expected: &tfsdk.ValidateAttributeResponse{ + expected: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -2056,9 +2056,9 @@ func TestAttributeValidateInt64(t *testing.T) { testCases := map[string]struct { attribute fwxschema.AttributeWithInt64Validators - request tfsdk.ValidateAttributeRequest - response *tfsdk.ValidateAttributeResponse - expected *tfsdk.ValidateAttributeResponse + request ValidateAttributeRequest + response *ValidateAttributeResponse + expected *ValidateAttributeResponse }{ "request-path": { attribute: testschema.AttributeWithInt64Validators{ @@ -2078,12 +2078,12 @@ func TestAttributeValidateInt64(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Int64Value(123), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-pathexpression": { attribute: testschema.AttributeWithInt64Validators{ @@ -2103,13 +2103,13 @@ func TestAttributeValidateInt64(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.Int64Value(123), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-config": { attribute: testschema.AttributeWithInt64Validators{ @@ -2140,7 +2140,7 @@ func TestAttributeValidateInt64(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Int64Value(123), Config: tfsdk.Config{ @@ -2156,8 +2156,8 @@ func TestAttributeValidateInt64(t *testing.T) { ), }, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-configvalue": { attribute: testschema.AttributeWithInt64Validators{ @@ -2177,12 +2177,12 @@ func TestAttributeValidateInt64(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Int64Value(123), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "response-diagnostics": { attribute: testschema.AttributeWithInt64Validators{ @@ -2195,11 +2195,11 @@ func TestAttributeValidateInt64(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.Int64Value(123), }, - response: &tfsdk.ValidateAttributeResponse{ + response: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -2213,7 +2213,7 @@ func TestAttributeValidateInt64(t *testing.T) { ), }, }, - expected: &tfsdk.ValidateAttributeResponse{ + expected: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -2260,9 +2260,9 @@ func TestAttributeValidateList(t *testing.T) { testCases := map[string]struct { attribute fwxschema.AttributeWithListValidators - request tfsdk.ValidateAttributeRequest - response *tfsdk.ValidateAttributeResponse - expected *tfsdk.ValidateAttributeResponse + request ValidateAttributeRequest + response *ValidateAttributeResponse + expected *ValidateAttributeResponse }{ "request-path": { attribute: testschema.AttributeWithListValidators{ @@ -2283,12 +2283,12 @@ func TestAttributeValidateList(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("test")}), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-pathexpression": { attribute: testschema.AttributeWithListValidators{ @@ -2309,13 +2309,13 @@ func TestAttributeValidateList(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("test")}), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-config": { attribute: testschema.AttributeWithListValidators{ @@ -2352,7 +2352,7 @@ func TestAttributeValidateList(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("test")}), Config: tfsdk.Config{ @@ -2373,8 +2373,8 @@ func TestAttributeValidateList(t *testing.T) { ), }, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-configvalue": { attribute: testschema.AttributeWithListValidators{ @@ -2395,12 +2395,12 @@ func TestAttributeValidateList(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("test")}), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "response-diagnostics": { attribute: testschema.AttributeWithListValidators{ @@ -2414,11 +2414,11 @@ func TestAttributeValidateList(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("test")}), }, - response: &tfsdk.ValidateAttributeResponse{ + response: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -2432,7 +2432,7 @@ func TestAttributeValidateList(t *testing.T) { ), }, }, - expected: &tfsdk.ValidateAttributeResponse{ + expected: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -2479,9 +2479,9 @@ func TestAttributeValidateMap(t *testing.T) { testCases := map[string]struct { attribute fwxschema.AttributeWithMapValidators - request tfsdk.ValidateAttributeRequest - response *tfsdk.ValidateAttributeResponse - expected *tfsdk.ValidateAttributeResponse + request ValidateAttributeRequest + response *ValidateAttributeResponse + expected *ValidateAttributeResponse }{ "request-path": { attribute: testschema.AttributeWithMapValidators{ @@ -2502,15 +2502,15 @@ func TestAttributeValidateMap(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.MapValueMust( types.StringType, map[string]attr.Value{"testkey": types.StringValue("testvalue")}, ), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-pathexpression": { attribute: testschema.AttributeWithMapValidators{ @@ -2531,7 +2531,7 @@ func TestAttributeValidateMap(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.MapValueMust( @@ -2539,8 +2539,8 @@ func TestAttributeValidateMap(t *testing.T) { map[string]attr.Value{"testkey": types.StringValue("testvalue")}, ), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-config": { attribute: testschema.AttributeWithMapValidators{ @@ -2577,7 +2577,7 @@ func TestAttributeValidateMap(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.MapValueMust( types.StringType, @@ -2601,8 +2601,8 @@ func TestAttributeValidateMap(t *testing.T) { ), }, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-configvalue": { attribute: testschema.AttributeWithMapValidators{ @@ -2626,15 +2626,15 @@ func TestAttributeValidateMap(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.MapValueMust( types.StringType, map[string]attr.Value{"testkey": types.StringValue("testvalue")}, ), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "response-diagnostics": { attribute: testschema.AttributeWithMapValidators{ @@ -2648,14 +2648,14 @@ func TestAttributeValidateMap(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.MapValueMust( types.StringType, map[string]attr.Value{"testkey": types.StringValue("testvalue")}, ), }, - response: &tfsdk.ValidateAttributeResponse{ + response: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -2669,7 +2669,7 @@ func TestAttributeValidateMap(t *testing.T) { ), }, }, - expected: &tfsdk.ValidateAttributeResponse{ + expected: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -2716,9 +2716,9 @@ func TestAttributeValidateNumber(t *testing.T) { testCases := map[string]struct { attribute fwxschema.AttributeWithNumberValidators - request tfsdk.ValidateAttributeRequest - response *tfsdk.ValidateAttributeResponse - expected *tfsdk.ValidateAttributeResponse + request ValidateAttributeRequest + response *ValidateAttributeResponse + expected *ValidateAttributeResponse }{ "request-path": { attribute: testschema.AttributeWithNumberValidators{ @@ -2738,12 +2738,12 @@ func TestAttributeValidateNumber(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.NumberValue(big.NewFloat(1.2)), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-pathexpression": { attribute: testschema.AttributeWithNumberValidators{ @@ -2763,13 +2763,13 @@ func TestAttributeValidateNumber(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.NumberValue(big.NewFloat(1.2)), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-config": { attribute: testschema.AttributeWithNumberValidators{ @@ -2800,7 +2800,7 @@ func TestAttributeValidateNumber(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.NumberValue(big.NewFloat(1.2)), Config: tfsdk.Config{ @@ -2816,8 +2816,8 @@ func TestAttributeValidateNumber(t *testing.T) { ), }, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-configvalue": { attribute: testschema.AttributeWithNumberValidators{ @@ -2837,12 +2837,12 @@ func TestAttributeValidateNumber(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.NumberValue(big.NewFloat(1.2)), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "response-diagnostics": { attribute: testschema.AttributeWithNumberValidators{ @@ -2855,11 +2855,11 @@ func TestAttributeValidateNumber(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.NumberValue(big.NewFloat(1.2)), }, - response: &tfsdk.ValidateAttributeResponse{ + response: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -2873,7 +2873,7 @@ func TestAttributeValidateNumber(t *testing.T) { ), }, }, - expected: &tfsdk.ValidateAttributeResponse{ + expected: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -2920,9 +2920,9 @@ func TestAttributeValidateObject(t *testing.T) { testCases := map[string]struct { attribute fwxschema.AttributeWithObjectValidators - request tfsdk.ValidateAttributeRequest - response *tfsdk.ValidateAttributeResponse - expected *tfsdk.ValidateAttributeResponse + request ValidateAttributeRequest + response *ValidateAttributeResponse + expected *ValidateAttributeResponse }{ "request-path": { attribute: testschema.AttributeWithObjectValidators{ @@ -2945,15 +2945,15 @@ func TestAttributeValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{"testattr": types.StringType}, map[string]attr.Value{"testattr": types.StringValue("testvalue")}, ), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-pathexpression": { attribute: testschema.AttributeWithObjectValidators{ @@ -2976,7 +2976,7 @@ func TestAttributeValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.ObjectValueMust( @@ -2984,8 +2984,8 @@ func TestAttributeValidateObject(t *testing.T) { map[string]attr.Value{"testattr": types.StringValue("testvalue")}, ), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-config": { attribute: testschema.AttributeWithObjectValidators{ @@ -3024,7 +3024,7 @@ func TestAttributeValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{"testattr": types.StringType}, @@ -3048,8 +3048,8 @@ func TestAttributeValidateObject(t *testing.T) { ), }, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-configvalue": { attribute: testschema.AttributeWithObjectValidators{ @@ -3075,15 +3075,15 @@ func TestAttributeValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{"testattr": types.StringType}, map[string]attr.Value{"testattr": types.StringValue("testvalue")}, ), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "response-diagnostics": { attribute: testschema.AttributeWithObjectValidators{ @@ -3099,14 +3099,14 @@ func TestAttributeValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{"testattr": types.StringType}, map[string]attr.Value{"testattr": types.StringValue("testvalue")}, ), }, - response: &tfsdk.ValidateAttributeResponse{ + response: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -3120,7 +3120,7 @@ func TestAttributeValidateObject(t *testing.T) { ), }, }, - expected: &tfsdk.ValidateAttributeResponse{ + expected: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -3167,9 +3167,9 @@ func TestAttributeValidateSet(t *testing.T) { testCases := map[string]struct { attribute fwxschema.AttributeWithSetValidators - request tfsdk.ValidateAttributeRequest - response *tfsdk.ValidateAttributeResponse - expected *tfsdk.ValidateAttributeResponse + request ValidateAttributeRequest + response *ValidateAttributeResponse + expected *ValidateAttributeResponse }{ "request-path": { attribute: testschema.AttributeWithSetValidators{ @@ -3190,12 +3190,12 @@ func TestAttributeValidateSet(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("test")}), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-pathexpression": { attribute: testschema.AttributeWithSetValidators{ @@ -3216,13 +3216,13 @@ func TestAttributeValidateSet(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("test")}), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-config": { attribute: testschema.AttributeWithSetValidators{ @@ -3259,7 +3259,7 @@ func TestAttributeValidateSet(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("test")}), Config: tfsdk.Config{ @@ -3280,8 +3280,8 @@ func TestAttributeValidateSet(t *testing.T) { ), }, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-configvalue": { attribute: testschema.AttributeWithSetValidators{ @@ -3302,12 +3302,12 @@ func TestAttributeValidateSet(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("test")}), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "response-diagnostics": { attribute: testschema.AttributeWithSetValidators{ @@ -3321,11 +3321,11 @@ func TestAttributeValidateSet(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("test")}), }, - response: &tfsdk.ValidateAttributeResponse{ + response: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -3339,7 +3339,7 @@ func TestAttributeValidateSet(t *testing.T) { ), }, }, - expected: &tfsdk.ValidateAttributeResponse{ + expected: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -3386,9 +3386,9 @@ func TestAttributeValidateString(t *testing.T) { testCases := map[string]struct { attribute fwxschema.AttributeWithStringValidators - request tfsdk.ValidateAttributeRequest - response *tfsdk.ValidateAttributeResponse - expected *tfsdk.ValidateAttributeResponse + request ValidateAttributeRequest + response *ValidateAttributeResponse + expected *ValidateAttributeResponse }{ "request-path": { attribute: testschema.AttributeWithStringValidators{ @@ -3408,12 +3408,12 @@ func TestAttributeValidateString(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.StringValue("test"), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-pathexpression": { attribute: testschema.AttributeWithStringValidators{ @@ -3433,13 +3433,13 @@ func TestAttributeValidateString(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.StringValue("test"), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-config": { attribute: testschema.AttributeWithStringValidators{ @@ -3470,7 +3470,7 @@ func TestAttributeValidateString(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.StringValue("test"), Config: tfsdk.Config{ @@ -3486,8 +3486,8 @@ func TestAttributeValidateString(t *testing.T) { ), }, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-configvalue": { attribute: testschema.AttributeWithStringValidators{ @@ -3507,12 +3507,12 @@ func TestAttributeValidateString(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.StringValue("test"), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "response-diagnostics": { attribute: testschema.AttributeWithStringValidators{ @@ -3525,11 +3525,11 @@ func TestAttributeValidateString(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.StringValue("test"), }, - response: &tfsdk.ValidateAttributeResponse{ + response: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -3543,7 +3543,7 @@ func TestAttributeValidateString(t *testing.T) { ), }, }, - expected: &tfsdk.ValidateAttributeResponse{ + expected: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -3622,9 +3622,9 @@ func TestNestedAttributeObjectValidateObject(t *testing.T) { testCases := map[string]struct { object fwschema.NestedAttributeObject - request tfsdk.ValidateAttributeRequest - response *tfsdk.ValidateAttributeResponse - expected *tfsdk.ValidateAttributeResponse + request ValidateAttributeRequest + response *ValidateAttributeResponse + expected *ValidateAttributeResponse }{ "request-path": { object: testschema.NestedAttributeObjectWithValidators{ @@ -3644,13 +3644,13 @@ func TestNestedAttributeObjectValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: testAttributeConfig, Config: testConfig, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-pathexpression": { object: testschema.NestedAttributeObjectWithValidators{ @@ -3670,14 +3670,14 @@ func TestNestedAttributeObjectValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: testAttributeConfig, Config: testConfig, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-config": { object: testschema.NestedAttributeObjectWithValidators{ @@ -3697,13 +3697,13 @@ func TestNestedAttributeObjectValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: testAttributeConfig, Config: testConfig, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-configvalue": { object: testschema.NestedAttributeObjectWithValidators{ @@ -3723,13 +3723,13 @@ func TestNestedAttributeObjectValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: testAttributeConfig, Config: testConfig, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "response-diagnostics": { object: testschema.NestedAttributeObjectWithValidators{ @@ -3742,12 +3742,12 @@ func TestNestedAttributeObjectValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: testAttributeConfig, Config: testConfig, }, - response: &tfsdk.ValidateAttributeResponse{ + response: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -3761,7 +3761,7 @@ func TestNestedAttributeObjectValidateObject(t *testing.T) { ), }, }, - expected: &tfsdk.ValidateAttributeResponse{ + expected: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -3802,13 +3802,13 @@ func TestNestedAttributeObjectValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: testAttributeConfig, Config: testConfig, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{ + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("test").AtName("testattr"), diff --git a/internal/fwserver/block_plan_modification.go b/internal/fwserver/block_plan_modification.go index 944fc2b08..91dafc524 100644 --- a/internal/fwserver/block_plan_modification.go +++ b/internal/fwserver/block_plan_modification.go @@ -8,9 +8,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/internal/fwschema/fwxschema" "github.com/hashicorp/terraform-plugin-framework/internal/fwschemadata" "github.com/hashicorp/terraform-plugin-framework/internal/logging" - "github.com/hashicorp/terraform-plugin-framework/internal/privatestate" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" - "github.com/hashicorp/terraform-plugin-framework/tfsdk" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) @@ -21,43 +19,12 @@ import ( // The extra Block parameter is a carry-over of creating the proto6server // package from the tfsdk package and not wanting to export the method. // Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/365 -func BlockModifyPlan(ctx context.Context, b fwschema.Block, req tfsdk.ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { - privateProviderData := privatestate.EmptyProviderData(ctx) - +func BlockModifyPlan(ctx context.Context, b fwschema.Block, req ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { if req.Private != nil { resp.Private = req.Private - privateProviderData = req.Private } switch blockWithPlanModifiers := b.(type) { - // Legacy tfsdk.BlockPlanModifier handling - case fwxschema.BlockWithPlanModifiers: - var requiresReplace bool - - for _, planModifier := range blockWithPlanModifiers.GetPlanModifiers() { - modifyResp := &tfsdk.ModifyAttributePlanResponse{ - AttributePlan: req.AttributePlan, - RequiresReplace: requiresReplace, - Private: privateProviderData, - } - - planModifier.Modify(ctx, req, modifyResp) - - req.AttributePlan = modifyResp.AttributePlan - resp.Diagnostics.Append(modifyResp.Diagnostics...) - requiresReplace = modifyResp.RequiresReplace - resp.AttributePlan = modifyResp.AttributePlan - resp.Private = modifyResp.Private - - // Only on new errors. - if modifyResp.Diagnostics.HasError() { - return - } - } - - if requiresReplace { - resp.RequiresReplace = append(resp.RequiresReplace, req.AttributePath) - } case fwxschema.BlockWithListPlanModifiers: BlockPlanModifyList(ctx, blockWithPlanModifiers, req, resp) case fwxschema.BlockWithObjectPlanModifiers: @@ -309,7 +276,7 @@ func BlockModifyPlan(ctx context.Context, b fwschema.Block, req tfsdk.ModifyAttr } // BlockPlanModifyList performs all types.List plan modification. -func BlockPlanModifyList(ctx context.Context, block fwxschema.BlockWithListPlanModifiers, req tfsdk.ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { +func BlockPlanModifyList(ctx context.Context, block fwxschema.BlockWithListPlanModifiers, req ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { // Use basetypes.ListValuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -444,7 +411,7 @@ func BlockPlanModifyList(ctx context.Context, block fwxschema.BlockWithListPlanM } // BlockPlanModifyObject performs all types.Object plan modification. -func BlockPlanModifyObject(ctx context.Context, block fwxschema.BlockWithObjectPlanModifiers, req tfsdk.ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { +func BlockPlanModifyObject(ctx context.Context, block fwxschema.BlockWithObjectPlanModifiers, req ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { // Use basetypes.ObjectValuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -579,7 +546,7 @@ func BlockPlanModifyObject(ctx context.Context, block fwxschema.BlockWithObjectP } // BlockPlanModifySet performs all types.Set plan modification. -func BlockPlanModifySet(ctx context.Context, block fwxschema.BlockWithSetPlanModifiers, req tfsdk.ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { +func BlockPlanModifySet(ctx context.Context, block fwxschema.BlockWithSetPlanModifiers, req ModifyAttributePlanRequest, resp *ModifyAttributePlanResponse) { // Use basetypes.SetValuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -784,7 +751,7 @@ func NestedBlockObjectPlanModify(ctx context.Context, o fwschema.NestedBlockObje return } - nestedAttrReq := tfsdk.ModifyAttributePlanRequest{ + nestedAttrReq := ModifyAttributePlanRequest{ AttributeConfig: nestedAttrConfig, AttributePath: req.Path.AtName(nestedName), AttributePathExpression: req.PathExpression.AtName(nestedName), @@ -834,7 +801,7 @@ func NestedBlockObjectPlanModify(ctx context.Context, o fwschema.NestedBlockObje return } - nestedBlockReq := tfsdk.ModifyAttributePlanRequest{ + nestedBlockReq := ModifyAttributePlanRequest{ AttributeConfig: nestedBlockConfig, AttributePath: req.Path.AtName(nestedName), AttributePathExpression: req.PathExpression.AtName(nestedName), diff --git a/internal/fwserver/block_plan_modification_test.go b/internal/fwserver/block_plan_modification_test.go index 7f4bfe729..e0477622c 100644 --- a/internal/fwserver/block_plan_modification_test.go +++ b/internal/fwserver/block_plan_modification_test.go @@ -87,8 +87,8 @@ func TestBlockModifyPlan(t *testing.T) { state string } - modifyAttributePlanRequest := func(attrPath path.Path, schema fwschema.Schema, values modifyAttributePlanValues) tfsdk.ModifyAttributePlanRequest { - return tfsdk.ModifyAttributePlanRequest{ + modifyAttributePlanRequest := func(attrPath path.Path, schema fwschema.Schema, values modifyAttributePlanValues) ModifyAttributePlanRequest { + return ModifyAttributePlanRequest{ AttributeConfig: types.ListValueMust( types.ObjectType{ AttrTypes: map[string]attr.Type{ @@ -156,7 +156,7 @@ func TestBlockModifyPlan(t *testing.T) { } } - modifyAttributePlanWithPrivateRequest := func(attrPath path.Path, schema fwschema.Schema, values modifyAttributePlanValues, privateProviderData *privatestate.ProviderData) tfsdk.ModifyAttributePlanRequest { + modifyAttributePlanWithPrivateRequest := func(attrPath path.Path, schema fwschema.Schema, values modifyAttributePlanValues, privateProviderData *privatestate.ProviderData) ModifyAttributePlanRequest { req := modifyAttributePlanRequest(attrPath, schema, values) req.Private = privateProviderData @@ -171,7 +171,7 @@ func TestBlockModifyPlan(t *testing.T) { testCases := map[string]struct { block fwschema.Block - req tfsdk.ModifyAttributePlanRequest + req ModifyAttributePlanRequest expectedResp ModifyAttributePlanResponse }{ "no-plan-modifiers": { @@ -352,7 +352,7 @@ func TestBlockModifyPlan(t *testing.T) { planmodifiers.TestAttrPlanPrivateModifierSet{}, }, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.ListValueMust( types.ObjectType{ AttrTypes: map[string]attr.Type{ @@ -422,7 +422,7 @@ func TestBlockModifyPlan(t *testing.T) { planmodifiers.TestAttrPlanPrivateModifierSet{}, }, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.ListValueMust( types.ObjectType{ AttrTypes: map[string]attr.Type{ @@ -502,7 +502,7 @@ func TestBlockModifyPlan(t *testing.T) { planmodifiers.TestAttrPlanPrivateModifierSet{}, }, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.ListValueMust( types.ObjectType{ AttrTypes: map[string]attr.Type{ @@ -592,7 +592,7 @@ func TestBlockModifyPlan(t *testing.T) { planmodifiers.TestAttrPlanPrivateModifierSet{}, }, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.SetValueMust( types.ObjectType{ AttrTypes: map[string]attr.Type{ @@ -662,7 +662,7 @@ func TestBlockModifyPlan(t *testing.T) { planmodifiers.TestAttrPlanPrivateModifierSet{}, }, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.SetValueMust( types.ObjectType{ AttrTypes: map[string]attr.Type{ @@ -742,7 +742,7 @@ func TestBlockModifyPlan(t *testing.T) { planmodifiers.TestAttrPlanPrivateModifierSet{}, }, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.SetValueMust( types.ObjectType{ AttrTypes: map[string]attr.Type{ @@ -852,7 +852,7 @@ func TestBlockModifyPlan(t *testing.T) { }, NestingMode: fwschema.BlockNestingModeList, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.ListValueMust( types.ObjectType{ AttrTypes: map[string]attr.Type{ @@ -1089,7 +1089,7 @@ func TestBlockModifyPlan(t *testing.T) { NestingMode: fwschema.BlockNestingModeSet, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.SetValueMust( types.ObjectType{ AttrTypes: map[string]attr.Type{ @@ -1229,7 +1229,7 @@ func TestBlockModifyPlan(t *testing.T) { planmodifiers.TestAttrPlanPrivateModifierSet{}, }, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ "nested_attr": types.StringType, @@ -1277,7 +1277,7 @@ func TestBlockModifyPlan(t *testing.T) { planmodifiers.TestAttrPlanPrivateModifierSet{}, }, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ "nested_attr": types.StringType, @@ -1328,7 +1328,7 @@ func TestBlockModifyPlan(t *testing.T) { planmodifiers.TestAttrPlanPrivateModifierSet{}, }, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ "nested_attr": types.StringType, @@ -1386,7 +1386,7 @@ func TestBlockModifyPlan(t *testing.T) { }, NestingMode: fwschema.BlockNestingModeSingle, }, - req: tfsdk.ModifyAttributePlanRequest{ + req: ModifyAttributePlanRequest{ AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ "nested_computed": types.StringType, @@ -2167,7 +2167,7 @@ func TestBlockPlanModifyList(t *testing.T) { testCases := map[string]struct { block fwxschema.BlockWithListPlanModifiers - request tfsdk.ModifyAttributePlanRequest + request ModifyAttributePlanRequest response *ModifyAttributePlanResponse expected *ModifyAttributePlanResponse }{ @@ -2189,7 +2189,7 @@ func TestBlockPlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -2220,7 +2220,7 @@ func TestBlockPlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -2266,7 +2266,7 @@ func TestBlockPlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -2312,7 +2312,7 @@ func TestBlockPlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.ListNull(types.StringType), @@ -2357,7 +2357,7 @@ func TestBlockPlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -2403,7 +2403,7 @@ func TestBlockPlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListNull(types.StringType), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -2436,7 +2436,7 @@ func TestBlockPlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListNull(types.StringType), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -2499,7 +2499,7 @@ func TestBlockPlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -2545,7 +2545,7 @@ func TestBlockPlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListNull(types.StringType), AttributePlan: types.ListNull(types.StringType), @@ -2569,7 +2569,7 @@ func TestBlockPlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -2626,7 +2626,7 @@ func TestBlockPlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListNull(types.StringType), AttributePlan: types.ListUnknown(types.StringType), @@ -2651,7 +2651,7 @@ func TestBlockPlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListNull(types.StringType), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -2692,7 +2692,7 @@ func TestBlockPlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -2718,7 +2718,7 @@ func TestBlockPlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -2747,7 +2747,7 @@ func TestBlockPlanModifyList(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -2788,7 +2788,7 @@ func TestBlockPlanModifyObject(t *testing.T) { testCases := map[string]struct { block fwxschema.BlockWithObjectPlanModifiers - request tfsdk.ModifyAttributePlanRequest + request ModifyAttributePlanRequest response *ModifyAttributePlanResponse expected *ModifyAttributePlanResponse }{ @@ -2810,7 +2810,7 @@ func TestBlockPlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ @@ -2876,7 +2876,7 @@ func TestBlockPlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.ObjectValueMust( @@ -2967,7 +2967,7 @@ func TestBlockPlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ @@ -3065,7 +3065,7 @@ func TestBlockPlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ @@ -3135,7 +3135,7 @@ func TestBlockPlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ @@ -3233,7 +3233,7 @@ func TestBlockPlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectNull(map[string]attr.Type{ "testattr": types.StringType, @@ -3291,7 +3291,7 @@ func TestBlockPlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectNull(map[string]attr.Type{ "testattr": types.StringType, @@ -3389,7 +3389,7 @@ func TestBlockPlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ @@ -3487,7 +3487,7 @@ func TestBlockPlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectNull(map[string]attr.Type{ "testattr": types.StringType, @@ -3526,7 +3526,7 @@ func TestBlockPlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ @@ -3625,7 +3625,7 @@ func TestBlockPlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectNull(map[string]attr.Type{ "testattr": types.StringType, @@ -3665,7 +3665,7 @@ func TestBlockPlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectNull(map[string]attr.Type{ "testattr": types.StringType, @@ -3731,7 +3731,7 @@ func TestBlockPlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ @@ -3792,7 +3792,7 @@ func TestBlockPlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ @@ -3856,7 +3856,7 @@ func TestBlockPlanModifyObject(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{ @@ -3932,7 +3932,7 @@ func TestBlockPlanModifySet(t *testing.T) { testCases := map[string]struct { block fwxschema.BlockWithSetPlanModifiers - request tfsdk.ModifyAttributePlanRequest + request ModifyAttributePlanRequest response *ModifyAttributePlanResponse expected *ModifyAttributePlanResponse }{ @@ -3954,7 +3954,7 @@ func TestBlockPlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -3985,7 +3985,7 @@ func TestBlockPlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -4031,7 +4031,7 @@ func TestBlockPlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -4077,7 +4077,7 @@ func TestBlockPlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.SetNull(types.StringType), @@ -4122,7 +4122,7 @@ func TestBlockPlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -4168,7 +4168,7 @@ func TestBlockPlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetNull(types.StringType), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -4201,7 +4201,7 @@ func TestBlockPlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetNull(types.StringType), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -4264,7 +4264,7 @@ func TestBlockPlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -4310,7 +4310,7 @@ func TestBlockPlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetNull(types.StringType), AttributePlan: types.SetNull(types.StringType), @@ -4334,7 +4334,7 @@ func TestBlockPlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -4391,7 +4391,7 @@ func TestBlockPlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetNull(types.StringType), AttributePlan: types.SetUnknown(types.StringType), @@ -4416,7 +4416,7 @@ func TestBlockPlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetNull(types.StringType), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -4457,7 +4457,7 @@ func TestBlockPlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -4483,7 +4483,7 @@ func TestBlockPlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), @@ -4512,7 +4512,7 @@ func TestBlockPlanModifySet(t *testing.T) { }, }, }, - request: tfsdk.ModifyAttributePlanRequest{ + request: ModifyAttributePlanRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), AttributePlan: types.SetValueMust(types.StringType, []attr.Value{types.StringValue("testvalue")}), diff --git a/internal/fwserver/block_validation.go b/internal/fwserver/block_validation.go index 6fc725220..6b5b6314e 100644 --- a/internal/fwserver/block_validation.go +++ b/internal/fwserver/block_validation.go @@ -12,7 +12,6 @@ import ( "github.com/hashicorp/terraform-plugin-framework/internal/logging" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/schema/validator" - "github.com/hashicorp/terraform-plugin-framework/tfsdk" "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) @@ -22,7 +21,7 @@ import ( // The extra Block parameter is a carry-over of creating the proto6server // package from the tfsdk package and not wanting to export the method. // Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/365 -func BlockValidate(ctx context.Context, b fwschema.Block, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) { +func BlockValidate(ctx context.Context, b fwschema.Block, req ValidateAttributeRequest, resp *ValidateAttributeResponse) { configData := &fwschemadata.Data{ Description: fwschemadata.DataDescriptionConfiguration, Schema: req.Config.Schema, @@ -39,25 +38,6 @@ func BlockValidate(ctx context.Context, b fwschema.Block, req tfsdk.ValidateAttr req.AttributeConfig = attributeConfig switch blockWithValidators := b.(type) { - // Legacy tfsdk.AttributeValidator handling - case fwxschema.BlockWithValidators: - for _, validator := range blockWithValidators.GetValidators() { - logging.FrameworkDebug( - ctx, - "Calling provider defined AttributeValidator", - map[string]interface{}{ - logging.KeyDescription: validator.Description(ctx), - }, - ) - validator.Validate(ctx, req, resp) - logging.FrameworkDebug( - ctx, - "Called provider defined AttributeValidator", - map[string]interface{}{ - logging.KeyDescription: validator.Description(ctx), - }, - ) - } case fwxschema.BlockWithListValidators: BlockValidateList(ctx, blockWithValidators, req, resp) case fwxschema.BlockWithObjectValidators: @@ -92,13 +72,13 @@ func BlockValidate(ctx context.Context, b fwschema.Block, req tfsdk.ValidateAttr } for idx, value := range l.Elements() { - nestedBlockObjectReq := tfsdk.ValidateAttributeRequest{ + nestedBlockObjectReq := ValidateAttributeRequest{ AttributeConfig: value, AttributePath: req.AttributePath.AtListIndex(idx), AttributePathExpression: req.AttributePathExpression.AtListIndex(idx), Config: req.Config, } - nestedBlockObjectResp := &tfsdk.ValidateAttributeResponse{} + nestedBlockObjectResp := &ValidateAttributeResponse{} NestedBlockObjectValidate(ctx, nestedBlockObject, nestedBlockObjectReq, nestedBlockObjectResp) @@ -149,13 +129,13 @@ func BlockValidate(ctx context.Context, b fwschema.Block, req tfsdk.ValidateAttr } for _, value := range s.Elements() { - nestedBlockObjectReq := tfsdk.ValidateAttributeRequest{ + nestedBlockObjectReq := ValidateAttributeRequest{ AttributeConfig: value, AttributePath: req.AttributePath.AtSetValue(value), AttributePathExpression: req.AttributePathExpression.AtSetValue(value), Config: req.Config, } - nestedBlockObjectResp := &tfsdk.ValidateAttributeResponse{} + nestedBlockObjectResp := &ValidateAttributeResponse{} NestedBlockObjectValidate(ctx, nestedBlockObject, nestedBlockObjectReq, nestedBlockObjectResp) @@ -205,13 +185,13 @@ func BlockValidate(ctx context.Context, b fwschema.Block, req tfsdk.ValidateAttr return } - nestedBlockObjectReq := tfsdk.ValidateAttributeRequest{ + nestedBlockObjectReq := ValidateAttributeRequest{ AttributeConfig: o, AttributePath: req.AttributePath, AttributePathExpression: req.AttributePathExpression, Config: req.Config, } - nestedBlockObjectResp := &tfsdk.ValidateAttributeResponse{} + nestedBlockObjectResp := &ValidateAttributeResponse{} NestedBlockObjectValidate(ctx, nestedBlockObject, nestedBlockObjectReq, nestedBlockObjectResp) @@ -242,7 +222,7 @@ func BlockValidate(ctx context.Context, b fwschema.Block, req tfsdk.ValidateAttr } // BlockValidateList performs all types.List validation. -func BlockValidateList(ctx context.Context, block fwxschema.BlockWithListValidators, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) { +func BlockValidateList(ctx context.Context, block fwxschema.BlockWithListValidators, req ValidateAttributeRequest, resp *ValidateAttributeResponse) { // Use basetypes.ListValuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -307,7 +287,7 @@ func BlockValidateList(ctx context.Context, block fwxschema.BlockWithListValidat } // BlockValidateObject performs all types.Object validation. -func BlockValidateObject(ctx context.Context, block fwxschema.BlockWithObjectValidators, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) { +func BlockValidateObject(ctx context.Context, block fwxschema.BlockWithObjectValidators, req ValidateAttributeRequest, resp *ValidateAttributeResponse) { // Use basetypes.ObjectValuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -372,7 +352,7 @@ func BlockValidateObject(ctx context.Context, block fwxschema.BlockWithObjectVal } // BlockValidateSet performs all types.Set validation. -func BlockValidateSet(ctx context.Context, block fwxschema.BlockWithSetValidators, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) { +func BlockValidateSet(ctx context.Context, block fwxschema.BlockWithSetValidators, req ValidateAttributeRequest, resp *ValidateAttributeResponse) { // Use basetypes.SetValuable until custom types cannot re-implement // ValueFromTerraform. Until then, custom types are not technically // required to implement this interface. This opts to enforce the @@ -436,7 +416,7 @@ func BlockValidateSet(ctx context.Context, block fwxschema.BlockWithSetValidator } } -func NestedBlockObjectValidate(ctx context.Context, o fwschema.NestedBlockObject, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) { +func NestedBlockObjectValidate(ctx context.Context, o fwschema.NestedBlockObject, req ValidateAttributeRequest, resp *ValidateAttributeResponse) { objectWithValidators, ok := o.(fwxschema.NestedBlockObjectWithValidators) if ok { @@ -499,12 +479,12 @@ func NestedBlockObjectValidate(ctx context.Context, o fwschema.NestedBlockObject } for nestedName, nestedAttr := range o.GetAttributes() { - nestedAttrReq := tfsdk.ValidateAttributeRequest{ + nestedAttrReq := ValidateAttributeRequest{ AttributePath: req.AttributePath.AtName(nestedName), AttributePathExpression: req.AttributePathExpression.AtName(nestedName), Config: req.Config, } - nestedAttrResp := &tfsdk.ValidateAttributeResponse{} + nestedAttrResp := &ValidateAttributeResponse{} AttributeValidate(ctx, nestedAttr, nestedAttrReq, nestedAttrResp) @@ -512,12 +492,12 @@ func NestedBlockObjectValidate(ctx context.Context, o fwschema.NestedBlockObject } for nestedName, nestedBlock := range o.GetBlocks() { - nestedBlockReq := tfsdk.ValidateAttributeRequest{ + nestedBlockReq := ValidateAttributeRequest{ AttributePath: req.AttributePath.AtName(nestedName), AttributePathExpression: req.AttributePathExpression.AtName(nestedName), Config: req.Config, } - nestedBlockResp := &tfsdk.ValidateAttributeResponse{} + nestedBlockResp := &ValidateAttributeResponse{} BlockValidate(ctx, nestedBlock, nestedBlockReq, nestedBlockResp) diff --git a/internal/fwserver/block_validation_test.go b/internal/fwserver/block_validation_test.go index f1f27d7a4..cacded194 100644 --- a/internal/fwserver/block_validation_test.go +++ b/internal/fwserver/block_validation_test.go @@ -24,11 +24,11 @@ func TestBlockValidate(t *testing.T) { t.Parallel() testCases := map[string]struct { - req tfsdk.ValidateAttributeRequest - resp tfsdk.ValidateAttributeResponse + req ValidateAttributeRequest + resp ValidateAttributeResponse }{ "deprecation-message-known": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -85,7 +85,7 @@ func TestBlockValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("test"), @@ -96,7 +96,7 @@ func TestBlockValidate(t *testing.T) { }, }, "deprecation-message-null": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -142,10 +142,10 @@ func TestBlockValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "deprecation-message-unknown": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -191,10 +191,10 @@ func TestBlockValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "warnings": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -259,7 +259,7 @@ func TestBlockValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ testWarningDiagnostic1, testWarningDiagnostic2, @@ -267,7 +267,7 @@ func TestBlockValidate(t *testing.T) { }, }, "errors": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -332,7 +332,7 @@ func TestBlockValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ testErrorDiagnostic1, testErrorDiagnostic2, @@ -340,7 +340,7 @@ func TestBlockValidate(t *testing.T) { }, }, "nested-attr-warnings": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -407,7 +407,7 @@ func TestBlockValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ testWarningDiagnostic1, testWarningDiagnostic2, @@ -415,7 +415,7 @@ func TestBlockValidate(t *testing.T) { }, }, "nested-attr-errors": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -482,7 +482,7 @@ func TestBlockValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ testErrorDiagnostic1, testErrorDiagnostic2, @@ -490,7 +490,7 @@ func TestBlockValidate(t *testing.T) { }, }, "nested-attr-type-with-validate-error": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -546,14 +546,14 @@ func TestBlockValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ testtypes.TestErrorDiagnostic(path.Root("test").AtListIndex(0).AtName("nested_attr")), }, }, }, "nested-attr-type-with-validate-warning": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -609,14 +609,14 @@ func TestBlockValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ testtypes.TestWarningDiagnostic(path.Root("test").AtListIndex(0).AtName("nested_attr")), }, }, }, "list-no-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -672,10 +672,10 @@ func TestBlockValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "list-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -737,14 +737,14 @@ func TestBlockValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ testErrorDiagnostic1, }, }, }, "set-no-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -800,10 +800,10 @@ func TestBlockValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "set-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -865,14 +865,14 @@ func TestBlockValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ testErrorDiagnostic1, }, }, }, "single-no-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -915,10 +915,10 @@ func TestBlockValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{}, + resp: ValidateAttributeResponse{}, }, "single-validation": { - req: tfsdk.ValidateAttributeRequest{ + req: ValidateAttributeRequest{ AttributePath: path.Root("test"), Config: tfsdk.Config{ Raw: tftypes.NewValue( @@ -967,7 +967,7 @@ func TestBlockValidate(t *testing.T) { }, }, }, - resp: tfsdk.ValidateAttributeResponse{ + resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ testErrorDiagnostic1, }, @@ -980,7 +980,7 @@ func TestBlockValidate(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() - var got tfsdk.ValidateAttributeResponse + var got ValidateAttributeResponse block, ok := tc.req.Config.Schema.GetBlocks()["test"] if !ok { @@ -1001,9 +1001,9 @@ func TestBlockValidateList(t *testing.T) { testCases := map[string]struct { block fwxschema.BlockWithListValidators - request tfsdk.ValidateAttributeRequest - response *tfsdk.ValidateAttributeResponse - expected *tfsdk.ValidateAttributeResponse + request ValidateAttributeRequest + response *ValidateAttributeResponse + expected *ValidateAttributeResponse }{ "request-path": { block: testschema.BlockWithListValidators{ @@ -1026,7 +1026,7 @@ func TestBlockValidateList(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust( types.ObjectType{ @@ -1040,8 +1040,8 @@ func TestBlockValidateList(t *testing.T) { }, ), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-pathexpression": { block: testschema.BlockWithListValidators{ @@ -1064,7 +1064,7 @@ func TestBlockValidateList(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.ListValueMust( @@ -1079,8 +1079,8 @@ func TestBlockValidateList(t *testing.T) { }, ), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-config": { block: testschema.BlockWithListValidators{ @@ -1140,7 +1140,7 @@ func TestBlockValidateList(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust( types.ObjectType{ @@ -1192,8 +1192,8 @@ func TestBlockValidateList(t *testing.T) { ), }, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-configvalue": { block: testschema.BlockWithListValidators{ @@ -1226,7 +1226,7 @@ func TestBlockValidateList(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust( types.ObjectType{ @@ -1240,8 +1240,8 @@ func TestBlockValidateList(t *testing.T) { }, ), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "response-diagnostics": { block: testschema.BlockWithListValidators{ @@ -1257,7 +1257,7 @@ func TestBlockValidateList(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ListValueMust( types.ObjectType{ @@ -1271,7 +1271,7 @@ func TestBlockValidateList(t *testing.T) { }, ), }, - response: &tfsdk.ValidateAttributeResponse{ + response: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -1285,7 +1285,7 @@ func TestBlockValidateList(t *testing.T) { ), }, }, - expected: &tfsdk.ValidateAttributeResponse{ + expected: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -1332,9 +1332,9 @@ func TestBlockValidateObject(t *testing.T) { testCases := map[string]struct { block fwxschema.BlockWithObjectValidators - request tfsdk.ValidateAttributeRequest - response *tfsdk.ValidateAttributeResponse - expected *tfsdk.ValidateAttributeResponse + request ValidateAttributeRequest + response *ValidateAttributeResponse + expected *ValidateAttributeResponse }{ "request-path": { block: testschema.BlockWithObjectValidators{ @@ -1357,15 +1357,15 @@ func TestBlockValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{"testattr": types.StringType}, map[string]attr.Value{"testattr": types.StringValue("test")}, ), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-pathexpression": { block: testschema.BlockWithObjectValidators{ @@ -1388,7 +1388,7 @@ func TestBlockValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.ObjectValueMust( @@ -1396,8 +1396,8 @@ func TestBlockValidateObject(t *testing.T) { map[string]attr.Value{"testattr": types.StringValue("test")}, ), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-config": { block: testschema.BlockWithObjectValidators{ @@ -1444,7 +1444,7 @@ func TestBlockValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{"testattr": types.StringType}, @@ -1476,8 +1476,8 @@ func TestBlockValidateObject(t *testing.T) { ), }, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-configvalue": { block: testschema.BlockWithObjectValidators{ @@ -1503,15 +1503,15 @@ func TestBlockValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{"testattr": types.StringType}, map[string]attr.Value{"testattr": types.StringValue("test")}, ), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "response-diagnostics": { block: testschema.BlockWithObjectValidators{ @@ -1527,14 +1527,14 @@ func TestBlockValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.ObjectValueMust( map[string]attr.Type{"testattr": types.StringType}, map[string]attr.Value{"testattr": types.StringValue("test")}, ), }, - response: &tfsdk.ValidateAttributeResponse{ + response: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -1548,7 +1548,7 @@ func TestBlockValidateObject(t *testing.T) { ), }, }, - expected: &tfsdk.ValidateAttributeResponse{ + expected: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -1595,9 +1595,9 @@ func TestBlockValidateSet(t *testing.T) { testCases := map[string]struct { block fwxschema.BlockWithSetValidators - request tfsdk.ValidateAttributeRequest - response *tfsdk.ValidateAttributeResponse - expected *tfsdk.ValidateAttributeResponse + request ValidateAttributeRequest + response *ValidateAttributeResponse + expected *ValidateAttributeResponse }{ "request-path": { block: testschema.BlockWithSetValidators{ @@ -1620,7 +1620,7 @@ func TestBlockValidateSet(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust( types.ObjectType{ @@ -1634,8 +1634,8 @@ func TestBlockValidateSet(t *testing.T) { }, ), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-pathexpression": { block: testschema.BlockWithSetValidators{ @@ -1658,7 +1658,7 @@ func TestBlockValidateSet(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: types.SetValueMust( @@ -1673,8 +1673,8 @@ func TestBlockValidateSet(t *testing.T) { }, ), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-config": { block: testschema.BlockWithSetValidators{ @@ -1734,7 +1734,7 @@ func TestBlockValidateSet(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust( types.ObjectType{ @@ -1786,8 +1786,8 @@ func TestBlockValidateSet(t *testing.T) { ), }, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-configvalue": { block: testschema.BlockWithSetValidators{ @@ -1820,7 +1820,7 @@ func TestBlockValidateSet(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust( types.ObjectType{ @@ -1834,8 +1834,8 @@ func TestBlockValidateSet(t *testing.T) { }, ), }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "response-diagnostics": { block: testschema.BlockWithSetValidators{ @@ -1851,7 +1851,7 @@ func TestBlockValidateSet(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: types.SetValueMust( types.ObjectType{ @@ -1865,7 +1865,7 @@ func TestBlockValidateSet(t *testing.T) { }, ), }, - response: &tfsdk.ValidateAttributeResponse{ + response: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -1879,7 +1879,7 @@ func TestBlockValidateSet(t *testing.T) { ), }, }, - expected: &tfsdk.ValidateAttributeResponse{ + expected: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -2009,9 +2009,9 @@ func TestNestedBlockObjectValidateObject(t *testing.T) { testCases := map[string]struct { object fwschema.NestedBlockObject - request tfsdk.ValidateAttributeRequest - response *tfsdk.ValidateAttributeResponse - expected *tfsdk.ValidateAttributeResponse + request ValidateAttributeRequest + response *ValidateAttributeResponse + expected *ValidateAttributeResponse }{ "request-path": { object: testschema.NestedBlockObjectWithValidators{ @@ -2031,13 +2031,13 @@ func TestNestedBlockObjectValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: testAttributeConfig, Config: testConfig, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-pathexpression": { object: testschema.NestedBlockObjectWithValidators{ @@ -2057,14 +2057,14 @@ func TestNestedBlockObjectValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributePathExpression: path.MatchRoot("test"), AttributeConfig: testAttributeConfig, Config: testConfig, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-config": { object: testschema.NestedBlockObjectWithValidators{ @@ -2084,13 +2084,13 @@ func TestNestedBlockObjectValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: testAttributeConfig, Config: testConfig, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "request-configvalue": { object: testschema.NestedBlockObjectWithValidators{ @@ -2110,13 +2110,13 @@ func TestNestedBlockObjectValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: testAttributeConfig, Config: testConfig, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{}, + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{}, }, "response-diagnostics": { object: testschema.NestedBlockObjectWithValidators{ @@ -2129,12 +2129,12 @@ func TestNestedBlockObjectValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: testAttributeConfig, Config: testConfig, }, - response: &tfsdk.ValidateAttributeResponse{ + response: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -2148,7 +2148,7 @@ func TestNestedBlockObjectValidateObject(t *testing.T) { ), }, }, - expected: &tfsdk.ValidateAttributeResponse{ + expected: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("other"), @@ -2189,13 +2189,13 @@ func TestNestedBlockObjectValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: testAttributeConfig, Config: testConfig, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{ + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("test").AtName("testattr"), @@ -2225,13 +2225,13 @@ func TestNestedBlockObjectValidateObject(t *testing.T) { }, }, }, - request: tfsdk.ValidateAttributeRequest{ + request: ValidateAttributeRequest{ AttributePath: path.Root("test"), AttributeConfig: testAttributeConfig, Config: testConfig, }, - response: &tfsdk.ValidateAttributeResponse{}, - expected: &tfsdk.ValidateAttributeResponse{ + response: &ValidateAttributeResponse{}, + expected: &ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ diag.NewAttributeWarningDiagnostic( path.Root("test").AtName("testblock"), diff --git a/internal/fwserver/schema_plan_modification.go b/internal/fwserver/schema_plan_modification.go index d8104eff5..d9e910c67 100644 --- a/internal/fwserver/schema_plan_modification.go +++ b/internal/fwserver/schema_plan_modification.go @@ -79,7 +79,7 @@ func SchemaModifyPlan(ctx context.Context, s fwschema.Schema, req ModifySchemaPl } for name, attribute := range s.GetAttributes() { - attrReq := tfsdk.ModifyAttributePlanRequest{ + attrReq := ModifyAttributePlanRequest{ AttributePath: path.Root(name), Config: req.Config, State: req.State, @@ -136,7 +136,7 @@ func SchemaModifyPlan(ctx context.Context, s fwschema.Schema, req ModifySchemaPl } for name, block := range s.GetBlocks() { - blockReq := tfsdk.ModifyAttributePlanRequest{ + blockReq := ModifyAttributePlanRequest{ AttributePath: path.Root(name), Config: req.Config, State: req.State, diff --git a/internal/fwserver/schema_validation.go b/internal/fwserver/schema_validation.go index ce6fbf99a..41af356e0 100644 --- a/internal/fwserver/schema_validation.go +++ b/internal/fwserver/schema_validation.go @@ -36,12 +36,12 @@ type ValidateSchemaResponse struct { func SchemaValidate(ctx context.Context, s fwschema.Schema, req ValidateSchemaRequest, resp *ValidateSchemaResponse) { for name, attribute := range s.GetAttributes() { - attributeReq := tfsdk.ValidateAttributeRequest{ + attributeReq := ValidateAttributeRequest{ AttributePath: path.Root(name), AttributePathExpression: path.MatchRoot(name), Config: req.Config, } - attributeResp := &tfsdk.ValidateAttributeResponse{ + attributeResp := &ValidateAttributeResponse{ Diagnostics: resp.Diagnostics, } @@ -51,12 +51,12 @@ func SchemaValidate(ctx context.Context, s fwschema.Schema, req ValidateSchemaRe } for name, block := range s.GetBlocks() { - attributeReq := tfsdk.ValidateAttributeRequest{ + attributeReq := ValidateAttributeRequest{ AttributePath: path.Root(name), AttributePathExpression: path.MatchRoot(name), Config: req.Config, } - attributeResp := &tfsdk.ValidateAttributeResponse{ + attributeResp := &ValidateAttributeResponse{ Diagnostics: resp.Diagnostics, } diff --git a/internal/fwserver/server.go b/internal/fwserver/server.go index e1976e046..4911757b4 100644 --- a/internal/fwserver/server.go +++ b/internal/fwserver/server.go @@ -230,48 +230,26 @@ func (s *Server) DataSourceSchemas(ctx context.Context) (map[string]fwschema.Sch for dataSourceTypeName, dataSourceFunc := range dataSourceFuncs { dataSource := dataSourceFunc() - switch dataSourceIface := dataSource.(type) { - case datasource.DataSourceWithSchema: - schemaReq := datasource.SchemaRequest{} - schemaResp := datasource.SchemaResponse{} - - logging.FrameworkDebug(ctx, "Calling provider defined DataSource Schema", map[string]interface{}{logging.KeyDataSourceType: dataSourceTypeName}) - dataSourceIface.Schema(ctx, schemaReq, &schemaResp) - logging.FrameworkDebug(ctx, "Called provider defined DataSource Schema", map[string]interface{}{logging.KeyDataSourceType: dataSourceTypeName}) - - s.dataSourceSchemasDiags.Append(schemaResp.Diagnostics...) - - if s.dataSourceSchemasDiags.HasError() { - return s.dataSourceSchemas, s.dataSourceSchemasDiags - } - - s.dataSourceSchemasDiags.Append(schemaResp.Schema.Validate()...) - - if s.dataSourceSchemasDiags.HasError() { - return s.dataSourceSchemas, s.dataSourceSchemasDiags - } - - s.dataSourceSchemas[dataSourceTypeName] = schemaResp.Schema - case datasource.DataSourceWithGetSchema: - logging.FrameworkDebug(ctx, "Calling provider defined DataSource GetSchema", map[string]interface{}{logging.KeyDataSourceType: dataSourceTypeName}) - schema, diags := dataSourceIface.GetSchema(ctx) //nolint:staticcheck // Required internal usage until removal - logging.FrameworkDebug(ctx, "Called provider defined DataSource GetSchema", map[string]interface{}{logging.KeyDataSourceType: dataSourceTypeName}) - - s.dataSourceSchemasDiags.Append(diags...) - - if s.dataSourceSchemasDiags.HasError() { - return s.dataSourceSchemas, s.dataSourceSchemasDiags - } - - s.dataSourceSchemas[dataSourceTypeName] = schema - default: - s.dataSourceSchemasDiags.AddError( - "Data Source Missing Schema", - "While attempting to load provider data source schemas, a data source was missing a Schema method. "+ - "This is always an issue in the provider and should be reported to the provider developers.\n\n"+ - "Data Source Type Name: "+dataSourceTypeName, - ) + schemaReq := datasource.SchemaRequest{} + schemaResp := datasource.SchemaResponse{} + + logging.FrameworkDebug(ctx, "Calling provider defined DataSource Schema", map[string]interface{}{logging.KeyDataSourceType: dataSourceTypeName}) + dataSource.Schema(ctx, schemaReq, &schemaResp) + logging.FrameworkDebug(ctx, "Called provider defined DataSource Schema", map[string]interface{}{logging.KeyDataSourceType: dataSourceTypeName}) + + s.dataSourceSchemasDiags.Append(schemaResp.Diagnostics...) + + if s.dataSourceSchemasDiags.HasError() { + return s.dataSourceSchemas, s.dataSourceSchemasDiags + } + + s.dataSourceSchemasDiags.Append(schemaResp.Schema.Validate()...) + + if s.dataSourceSchemasDiags.HasError() { + return s.dataSourceSchemas, s.dataSourceSchemasDiags } + + s.dataSourceSchemas[dataSourceTypeName] = schemaResp.Schema } return s.dataSourceSchemas, s.dataSourceSchemasDiags @@ -288,33 +266,17 @@ func (s *Server) ProviderSchema(ctx context.Context) (fwschema.Schema, diag.Diag return s.providerSchema, s.providerSchemaDiags } - switch providerIface := s.Provider.(type) { - case provider.ProviderWithSchema: - schemaReq := provider.SchemaRequest{} - schemaResp := provider.SchemaResponse{} - - logging.FrameworkDebug(ctx, "Calling provider defined Provider Schema") - providerIface.Schema(ctx, schemaReq, &schemaResp) - logging.FrameworkDebug(ctx, "Called provider defined Provider Schema") - - s.providerSchema = schemaResp.Schema - s.providerSchemaDiags = schemaResp.Diagnostics - - s.providerSchemaDiags.Append(schemaResp.Schema.Validate()...) - case provider.ProviderWithGetSchema: - logging.FrameworkDebug(ctx, "Calling provider defined Provider GetSchema") - schema, diags := providerIface.GetSchema(ctx) //nolint:staticcheck // Required internal usage until removal - logging.FrameworkDebug(ctx, "Called provider defined Provider GetSchema") - - s.providerSchema = schema - s.providerSchemaDiags = diags - default: - s.providerSchemaDiags.AddError( - "Provider Missing Schema", - "While attempting to load provider schemas, the provider itself was missing a Schema method. "+ - "This is always an issue in the provider and should be reported to the provider developers.", - ) - } + schemaReq := provider.SchemaRequest{} + schemaResp := provider.SchemaResponse{} + + logging.FrameworkDebug(ctx, "Calling provider defined Provider Schema") + s.Provider.Schema(ctx, schemaReq, &schemaResp) + logging.FrameworkDebug(ctx, "Called provider defined Provider Schema") + + s.providerSchema = schemaResp.Schema + s.providerSchemaDiags = schemaResp.Diagnostics + + s.providerSchemaDiags.Append(schemaResp.Schema.Validate()...) return s.providerSchema, s.providerSchemaDiags } @@ -465,48 +427,26 @@ func (s *Server) ResourceSchemas(ctx context.Context) (map[string]fwschema.Schem for resourceTypeName, resourceFunc := range resourceFuncs { res := resourceFunc() - switch resourceIface := res.(type) { - case resource.ResourceWithSchema: - schemaReq := resource.SchemaRequest{} - schemaResp := resource.SchemaResponse{} - - logging.FrameworkDebug(ctx, "Calling provider defined Resource Schema", map[string]interface{}{logging.KeyResourceType: resourceTypeName}) - resourceIface.Schema(ctx, schemaReq, &schemaResp) - logging.FrameworkDebug(ctx, "Called provider defined Resource Schema", map[string]interface{}{logging.KeyResourceType: resourceTypeName}) - - s.resourceSchemasDiags.Append(schemaResp.Diagnostics...) + schemaReq := resource.SchemaRequest{} + schemaResp := resource.SchemaResponse{} - if s.resourceSchemasDiags.HasError() { - return s.resourceSchemas, s.resourceSchemasDiags - } + logging.FrameworkDebug(ctx, "Calling provider defined Resource Schema", map[string]interface{}{logging.KeyResourceType: resourceTypeName}) + res.Schema(ctx, schemaReq, &schemaResp) + logging.FrameworkDebug(ctx, "Called provider defined Resource Schema", map[string]interface{}{logging.KeyResourceType: resourceTypeName}) - s.resourceSchemasDiags.Append(schemaResp.Schema.Validate()...) + s.resourceSchemasDiags.Append(schemaResp.Diagnostics...) - if s.resourceSchemasDiags.HasError() { - return s.resourceSchemas, s.resourceSchemasDiags - } - - s.resourceSchemas[resourceTypeName] = schemaResp.Schema - case resource.ResourceWithGetSchema: - logging.FrameworkDebug(ctx, "Calling provider defined Resource GetSchema", map[string]interface{}{logging.KeyResourceType: resourceTypeName}) - schema, diags := resourceIface.GetSchema(ctx) //nolint:staticcheck // Required internal usage until removal - logging.FrameworkDebug(ctx, "Called provider defined Resource GetSchema", map[string]interface{}{logging.KeyResourceType: resourceTypeName}) - - s.resourceSchemasDiags.Append(diags...) + if s.resourceSchemasDiags.HasError() { + return s.resourceSchemas, s.resourceSchemasDiags + } - if s.resourceSchemasDiags.HasError() { - return s.resourceSchemas, s.resourceSchemasDiags - } + s.resourceSchemasDiags.Append(schemaResp.Schema.Validate()...) - s.resourceSchemas[resourceTypeName] = schema - default: - s.resourceSchemasDiags.AddError( - "Resource Missing Schema", - "While attempting to load provider resource schemas, a resource was missing a Schema method. "+ - "This is always an issue in the provider and should be reported to the provider developers.\n\n"+ - "Resource Type Name: "+resourceTypeName, - ) + if s.resourceSchemasDiags.HasError() { + return s.resourceSchemas, s.resourceSchemasDiags } + + s.resourceSchemas[resourceTypeName] = schemaResp.Schema } return s.resourceSchemas, s.resourceSchemasDiags diff --git a/internal/testing/planmodifiers/planmodifiers.go b/internal/testing/planmodifiers/planmodifiers.go index d134d6c9d..95587741c 100644 --- a/internal/testing/planmodifiers/planmodifiers.go +++ b/internal/testing/planmodifiers/planmodifiers.go @@ -4,122 +4,8 @@ import ( "context" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" - "github.com/hashicorp/terraform-plugin-framework/tfsdk" - "github.com/hashicorp/terraform-plugin-framework/types" ) -type TestWarningDiagModifier struct{} - -func (t TestWarningDiagModifier) Modify(ctx context.Context, req tfsdk.ModifyAttributePlanRequest, resp *tfsdk.ModifyAttributePlanResponse) { - resp.Diagnostics.AddWarning( - "Warning diag", - "This is a warning", - ) -} - -func (t TestWarningDiagModifier) Description(ctx context.Context) string { - return "This plan modifier is for use during testing only" -} - -func (t TestWarningDiagModifier) MarkdownDescription(ctx context.Context) string { - return "This plan modifier is for use during testing only" -} - -type TestErrorDiagModifier struct{} - -func (t TestErrorDiagModifier) Modify(ctx context.Context, req tfsdk.ModifyAttributePlanRequest, resp *tfsdk.ModifyAttributePlanResponse) { - resp.Diagnostics.AddError( - "Error diag", - "This is an error", - ) -} - -func (t TestErrorDiagModifier) Description(ctx context.Context) string { - return "This plan modifier is for use during testing only" -} - -func (t TestErrorDiagModifier) MarkdownDescription(ctx context.Context) string { - return "This plan modifier is for use during testing only" -} - -type TestAttrPlanValueModifierOne struct{} - -func (t TestAttrPlanValueModifierOne) PlanModifyString(ctx context.Context, req planmodifier.StringRequest, resp *planmodifier.StringResponse) { - if req.PlanValue.ValueString() == "TESTATTRONE" { - resp.PlanValue = types.StringValue("TESTATTRTWO") - } -} - -func (t TestAttrPlanValueModifierOne) Description(ctx context.Context) string { - return "This plan modifier is for use during testing only" -} - -func (t TestAttrPlanValueModifierOne) MarkdownDescription(ctx context.Context) string { - return "This plan modifier is for use during testing only" -} - -type TestAttrPlanValueModifierTwo struct{} - -func (t TestAttrPlanValueModifierTwo) Modify(ctx context.Context, req tfsdk.ModifyAttributePlanRequest, resp *tfsdk.ModifyAttributePlanResponse) { - attrVal, ok := req.AttributePlan.(types.String) - if !ok { - return - } - - if attrVal.ValueString() == "TESTATTRTWO" { - resp.AttributePlan = types.StringValue("MODIFIED_TWO") - } -} - -func (t TestAttrPlanValueModifierTwo) Description(ctx context.Context) string { - return "This plan modifier is for use during testing only" -} - -func (t TestAttrPlanValueModifierTwo) MarkdownDescription(ctx context.Context) string { - return "This plan modifier is for use during testing only" -} - -type TestAttrDefaultValueModifier struct{} - -func (t TestAttrDefaultValueModifier) Modify(ctx context.Context, req tfsdk.ModifyAttributePlanRequest, resp *tfsdk.ModifyAttributePlanResponse) { - if req.AttributeState == nil && req.AttributeConfig == nil { - return - } - - configVal := req.AttributeConfig.(types.String) - - if configVal.IsNull() { - resp.AttributePlan = types.StringValue("DEFAULTVALUE") - } -} - -func (t TestAttrDefaultValueModifier) Description(ctx context.Context) string { - return "This plan modifier is for use during testing only" -} - -func (t TestAttrDefaultValueModifier) MarkdownDescription(ctx context.Context) string { - return "This plan modifier is for use during testing only" -} - -// testRequiresReplaceModifier is an AttributePlanModifier that sets RequiresReplace -// on the attribute. -type TestRequiresReplaceFalseModifier struct{} - -// Modify sets RequiresReplace on the response to true. -func (m TestRequiresReplaceFalseModifier) Modify(ctx context.Context, req tfsdk.ModifyAttributePlanRequest, resp *tfsdk.ModifyAttributePlanResponse) { - resp.RequiresReplace = false -} - -// Description returns a human-readable description of the plan modifier. -func (m TestRequiresReplaceFalseModifier) Description(ctx context.Context) string { - return "Always unsets requires replace." -} - -// MarkdownDescription returns a markdown description of the plan modifier. -func (m TestRequiresReplaceFalseModifier) MarkdownDescription(ctx context.Context) string { - return "Always unsets requires replace." -} - type TestAttrPlanPrivateModifierGet struct{} func (t TestAttrPlanPrivateModifierGet) PlanModifyList(ctx context.Context, req planmodifier.ListRequest, resp *planmodifier.ListResponse) { diff --git a/internal/testing/testprovider/attributeplanmodifier.go b/internal/testing/testprovider/attributeplanmodifier.go deleted file mode 100644 index d7e3ecd02..000000000 --- a/internal/testing/testprovider/attributeplanmodifier.go +++ /dev/null @@ -1,44 +0,0 @@ -package testprovider - -import ( - "context" - - "github.com/hashicorp/terraform-plugin-framework/tfsdk" -) - -var _ tfsdk.AttributePlanModifier = &AttributePlanModifier{} - -// Declarative tfsdk.AttributePlanModifier for unit testing. -type AttributePlanModifier struct { - // AttributePlanModifier interface methods - DescriptionMethod func(context.Context) string - MarkdownDescriptionMethod func(context.Context) string - ModifyMethod func(context.Context, tfsdk.ModifyAttributePlanRequest, *tfsdk.ModifyAttributePlanResponse) -} - -// Description satisfies the tfsdk.AttributePlanModifier interface. -func (m *AttributePlanModifier) Description(ctx context.Context) string { - if m.DescriptionMethod == nil { - return "" - } - - return m.DescriptionMethod(ctx) -} - -// MarkdownDescription satisfies the tfsdk.AttributePlanModifier interface. -func (m *AttributePlanModifier) MarkdownDescription(ctx context.Context) string { - if m.MarkdownDescriptionMethod == nil { - return "" - } - - return m.MarkdownDescriptionMethod(ctx) -} - -// Modify satisfies the tfsdk.AttributePlanModifier interface. -func (m *AttributePlanModifier) Modify(ctx context.Context, req tfsdk.ModifyAttributePlanRequest, resp *tfsdk.ModifyAttributePlanResponse) { - if m.ModifyMethod == nil { - return - } - - m.ModifyMethod(ctx, req, resp) -} diff --git a/internal/testing/testprovider/attributevalidator.go b/internal/testing/testprovider/attributevalidator.go deleted file mode 100644 index 251161b2b..000000000 --- a/internal/testing/testprovider/attributevalidator.go +++ /dev/null @@ -1,44 +0,0 @@ -package testprovider - -import ( - "context" - - "github.com/hashicorp/terraform-plugin-framework/tfsdk" -) - -var _ tfsdk.AttributeValidator = &AttributeValidator{} - -// Declarative tfsdk.AttributeValidator for unit testing. -type AttributeValidator struct { - // AttributeValidator interface methods - DescriptionMethod func(context.Context) string - MarkdownDescriptionMethod func(context.Context) string - ValidateMethod func(context.Context, tfsdk.ValidateAttributeRequest, *tfsdk.ValidateAttributeResponse) -} - -// Description satisfies the tfsdk.AttributeValidator interface. -func (v *AttributeValidator) Description(ctx context.Context) string { - if v.DescriptionMethod == nil { - return "" - } - - return v.DescriptionMethod(ctx) -} - -// MarkdownDescription satisfies the tfsdk.AttributeValidator interface. -func (v *AttributeValidator) MarkdownDescription(ctx context.Context) string { - if v.MarkdownDescriptionMethod == nil { - return "" - } - - return v.MarkdownDescriptionMethod(ctx) -} - -// Validate satisfies the tfsdk.AttributeValidator interface. -func (v *AttributeValidator) Validate(ctx context.Context, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) { - if v.ValidateMethod == nil { - return - } - - v.ValidateMethod(ctx, req, resp) -} diff --git a/internal/testing/types/listnestedattributescustom.go b/internal/testing/types/listnestedattributescustom.go index 119d54d75..4325ff226 100644 --- a/internal/testing/types/listnestedattributescustom.go +++ b/internal/testing/types/listnestedattributescustom.go @@ -7,7 +7,6 @@ import ( "github.com/hashicorp/terraform-plugin-go/tftypes" "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) @@ -17,16 +16,6 @@ var ( _ basetypes.ListValuable = &ListNestedAttributesCustomValue{} ) -type ListNestedAttributesCustomType struct { - fwschema.NestedAttributes -} - -func (t ListNestedAttributesCustomType) Type() attr.Type { - return ListNestedAttributesCustomTypeType{ - t.NestedAttributes.Type().(types.ListType), - } -} - type ListNestedAttributesCustomTypeType struct { types.ListType } diff --git a/internal/testing/types/mapnestedattributescustom.go b/internal/testing/types/mapnestedattributescustom.go index d95eb62f4..51cdb58db 100644 --- a/internal/testing/types/mapnestedattributescustom.go +++ b/internal/testing/types/mapnestedattributescustom.go @@ -7,7 +7,6 @@ import ( "github.com/hashicorp/terraform-plugin-go/tftypes" "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) @@ -17,16 +16,6 @@ var ( _ basetypes.MapValuable = &MapNestedAttributesCustomValue{} ) -type MapNestedAttributesCustomType struct { - fwschema.NestedAttributes -} - -func (t MapNestedAttributesCustomType) Type() attr.Type { - return MapNestedAttributesCustomTypeType{ - t.NestedAttributes.Type().(types.MapType), - } -} - type MapNestedAttributesCustomTypeType struct { types.MapType } diff --git a/internal/testing/types/setnestedattributescustom.go b/internal/testing/types/setnestedattributescustom.go index 512915fed..e4a454c12 100644 --- a/internal/testing/types/setnestedattributescustom.go +++ b/internal/testing/types/setnestedattributescustom.go @@ -7,7 +7,6 @@ import ( "github.com/hashicorp/terraform-plugin-go/tftypes" "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) @@ -17,16 +16,6 @@ var ( _ basetypes.SetValuable = &SetNestedAttributesCustomValue{} ) -type SetNestedAttributesCustomType struct { - fwschema.NestedAttributes -} - -func (t SetNestedAttributesCustomType) Type() attr.Type { - return SetNestedAttributesCustomTypeType{ - t.NestedAttributes.Type().(types.SetType), - } -} - type SetNestedAttributesCustomTypeType struct { types.SetType } diff --git a/internal/testing/types/singlenestedattributescustom.go b/internal/testing/types/singlenestedattributescustom.go index 792fc0d79..5b15c8b5e 100644 --- a/internal/testing/types/singlenestedattributescustom.go +++ b/internal/testing/types/singlenestedattributescustom.go @@ -7,7 +7,6 @@ import ( "github.com/hashicorp/terraform-plugin-go/tftypes" "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-framework/types/basetypes" ) @@ -17,16 +16,6 @@ var ( _ basetypes.SetValuable = &SetNestedAttributesCustomValue{} ) -type SingleNestedAttributesCustomType struct { - fwschema.NestedAttributes -} - -func (t SingleNestedAttributesCustomType) Type() attr.Type { - return SingleNestedAttributesCustomTypeType{ - t.NestedAttributes.Type().(types.ObjectType), - } -} - type SingleNestedAttributesCustomTypeType struct { types.ObjectType } diff --git a/internal/toproto5/schema_attribute.go b/internal/toproto5/schema_attribute.go index 86c94ea19..a40922997 100644 --- a/internal/toproto5/schema_attribute.go +++ b/internal/toproto5/schema_attribute.go @@ -4,7 +4,6 @@ import ( "context" "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" - "github.com/hashicorp/terraform-plugin-framework/tfsdk" "github.com/hashicorp/terraform-plugin-go/tfprotov5" "github.com/hashicorp/terraform-plugin-go/tftypes" ) @@ -14,16 +13,7 @@ import ( // `name` is the name of the attribute. func SchemaAttribute(ctx context.Context, name string, path *tftypes.AttributePath, a fwschema.Attribute) (*tfprotov5.SchemaAttribute, error) { if _, ok := a.(fwschema.NestedAttribute); ok { - // Temporarily handle tfsdk.Attribute, which always has a nesting mode, until its removed. - tfsdkAttribute, ok := a.(tfsdk.Attribute) - - if !ok { - return nil, path.NewErrorf("protocol version 5 cannot have Attributes set") - } - - if tfsdkAttribute.GetNestingMode() != fwschema.NestingModeUnknown || tfsdkAttribute.Attributes != nil { - return nil, path.NewErrorf("protocol version 5 cannot have Attributes set") - } + return nil, path.NewErrorf("protocol version 5 cannot have Attributes set") } if a.GetType() == nil { diff --git a/internal/toproto6/block_test.go b/internal/toproto6/block_test.go index d51f8f69d..91d4ecdce 100644 --- a/internal/toproto6/block_test.go +++ b/internal/toproto6/block_test.go @@ -8,7 +8,6 @@ import ( "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" "github.com/hashicorp/terraform-plugin-framework/internal/testing/testschema" "github.com/hashicorp/terraform-plugin-framework/internal/toproto6" - "github.com/hashicorp/terraform-plugin-framework/tfsdk" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-go/tfprotov6" "github.com/hashicorp/terraform-plugin-go/tftypes" @@ -52,7 +51,7 @@ func TestBlock(t *testing.T) { }, }, }, - NestingMode: tfsdk.BlockNestingModeList, + NestingMode: fwschema.BlockNestingModeList, }, path: tftypes.NewAttributePath(), expected: &tfprotov6.SchemaNestedBlock{ @@ -89,11 +88,11 @@ func TestBlock(t *testing.T) { }, }, }, - NestingMode: tfsdk.BlockNestingModeList, + NestingMode: fwschema.BlockNestingModeList, }, }, }, - NestingMode: tfsdk.BlockNestingModeList, + NestingMode: fwschema.BlockNestingModeList, }, path: tftypes.NewAttributePath(), expected: &tfprotov6.SchemaNestedBlock{ @@ -139,11 +138,11 @@ func TestBlock(t *testing.T) { }, }, }, - NestingMode: tfsdk.BlockNestingModeList, + NestingMode: fwschema.BlockNestingModeList, }, }, }, - NestingMode: tfsdk.BlockNestingModeList, + NestingMode: fwschema.BlockNestingModeList, }, path: tftypes.NewAttributePath(), expected: &tfprotov6.SchemaNestedBlock{ @@ -179,7 +178,7 @@ func TestBlock(t *testing.T) { }, }, }, - NestingMode: tfsdk.BlockNestingModeSet, + NestingMode: fwschema.BlockNestingModeSet, }, path: tftypes.NewAttributePath(), expected: &tfprotov6.SchemaNestedBlock{ @@ -216,11 +215,11 @@ func TestBlock(t *testing.T) { }, }, }, - NestingMode: tfsdk.BlockNestingModeSet, + NestingMode: fwschema.BlockNestingModeSet, }, }, }, - NestingMode: tfsdk.BlockNestingModeSet, + NestingMode: fwschema.BlockNestingModeSet, }, path: tftypes.NewAttributePath(), expected: &tfprotov6.SchemaNestedBlock{ @@ -266,11 +265,11 @@ func TestBlock(t *testing.T) { }, }, }, - NestingMode: tfsdk.BlockNestingModeSet, + NestingMode: fwschema.BlockNestingModeSet, }, }, }, - NestingMode: tfsdk.BlockNestingModeSet, + NestingMode: fwschema.BlockNestingModeSet, }, path: tftypes.NewAttributePath(), expected: &tfprotov6.SchemaNestedBlock{ @@ -306,7 +305,7 @@ func TestBlock(t *testing.T) { }, }, }, - NestingMode: tfsdk.BlockNestingModeSingle, + NestingMode: fwschema.BlockNestingModeSingle, }, path: tftypes.NewAttributePath(), expected: &tfprotov6.SchemaNestedBlock{ @@ -343,11 +342,11 @@ func TestBlock(t *testing.T) { }, }, }, - NestingMode: tfsdk.BlockNestingModeSingle, + NestingMode: fwschema.BlockNestingModeSingle, }, }, }, - NestingMode: tfsdk.BlockNestingModeSingle, + NestingMode: fwschema.BlockNestingModeSingle, }, path: tftypes.NewAttributePath(), expected: &tfprotov6.SchemaNestedBlock{ @@ -393,11 +392,11 @@ func TestBlock(t *testing.T) { }, }, }, - NestingMode: tfsdk.BlockNestingModeSingle, + NestingMode: fwschema.BlockNestingModeSingle, }, }, }, - NestingMode: tfsdk.BlockNestingModeSingle, + NestingMode: fwschema.BlockNestingModeSingle, }, path: tftypes.NewAttributePath(), expected: &tfprotov6.SchemaNestedBlock{ @@ -434,7 +433,7 @@ func TestBlock(t *testing.T) { }, }, DeprecationMessage: "deprecated, use something else instead", - NestingMode: tfsdk.BlockNestingModeList, + NestingMode: fwschema.BlockNestingModeList, }, path: tftypes.NewAttributePath(), expected: &tfprotov6.SchemaNestedBlock{ @@ -464,7 +463,7 @@ func TestBlock(t *testing.T) { }, }, Description: "test description", - NestingMode: tfsdk.BlockNestingModeList, + NestingMode: fwschema.BlockNestingModeList, }, path: tftypes.NewAttributePath(), expected: &tfprotov6.SchemaNestedBlock{ @@ -496,7 +495,7 @@ func TestBlock(t *testing.T) { }, Description: "test plain description", MarkdownDescription: "test markdown description", - NestingMode: tfsdk.BlockNestingModeList, + NestingMode: fwschema.BlockNestingModeList, }, path: tftypes.NewAttributePath(), expected: &tfprotov6.SchemaNestedBlock{ @@ -527,7 +526,7 @@ func TestBlock(t *testing.T) { }, }, MarkdownDescription: "test description", - NestingMode: tfsdk.BlockNestingModeList, + NestingMode: fwschema.BlockNestingModeList, }, path: tftypes.NewAttributePath(), expected: &tfprotov6.SchemaNestedBlock{ @@ -558,7 +557,7 @@ func TestBlock(t *testing.T) { }, }, MaxItems: 10, - NestingMode: tfsdk.BlockNestingModeList, + NestingMode: fwschema.BlockNestingModeList, }, path: tftypes.NewAttributePath(), expected: &tfprotov6.SchemaNestedBlock{ @@ -588,7 +587,7 @@ func TestBlock(t *testing.T) { }, }, MinItems: 10, - NestingMode: tfsdk.BlockNestingModeList, + NestingMode: fwschema.BlockNestingModeList, }, path: tftypes.NewAttributePath(), expected: &tfprotov6.SchemaNestedBlock{ diff --git a/internal/toproto6/schema_attribute.go b/internal/toproto6/schema_attribute.go index 30ef06da3..f7d25b631 100644 --- a/internal/toproto6/schema_attribute.go +++ b/internal/toproto6/schema_attribute.go @@ -5,7 +5,6 @@ import ( "sort" "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" - "github.com/hashicorp/terraform-plugin-framework/tfsdk" "github.com/hashicorp/terraform-plugin-go/tfprotov6" "github.com/hashicorp/terraform-plugin-go/tftypes" ) @@ -14,20 +13,6 @@ import ( // Attribute. Errors will be tftypes.AttributePathErrors based on `path`. // `name` is the name of the attribute. func SchemaAttribute(ctx context.Context, name string, path *tftypes.AttributePath, a fwschema.Attribute) (*tfprotov6.SchemaAttribute, error) { - tfsdkAttribute, ok := a.(tfsdk.Attribute) - - if ok && tfsdkAttribute.GetNestingMode() == fwschema.NestingModeUnknown && tfsdkAttribute.Attributes != nil { - return nil, path.NewErrorf("cannot have both Attributes and Type set") - } - - if ok && a.GetType() == nil { - return nil, path.NewErrorf("must have Attributes or Type set") - } - - if ok && tfsdkAttribute.GetNestingMode() != fwschema.NestingModeUnknown && (tfsdkAttribute.Attributes == nil || len(tfsdkAttribute.Attributes.GetAttributes()) == 0) { - return nil, path.NewErrorf("must have Attributes or Type set") - } - if !a.IsRequired() && !a.IsOptional() && !a.IsComputed() { return nil, path.NewErrorf("must have Required, Optional, or Computed set") } @@ -55,10 +40,6 @@ func SchemaAttribute(ctx context.Context, name string, path *tftypes.AttributePa schemaAttribute.DescriptionKind = tfprotov6.StringKindMarkdown } - if ok && tfsdkAttribute.GetNestingMode() == fwschema.NestingModeUnknown { - return schemaAttribute, nil - } - nestedAttribute, ok := a.(fwschema.NestedAttribute) if !ok { diff --git a/provider/provider.go b/provider/provider.go index 8586fadfc..1ef681334 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -4,14 +4,10 @@ import ( "context" "github.com/hashicorp/terraform-plugin-framework/datasource" - "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/resource" - "github.com/hashicorp/terraform-plugin-framework/tfsdk" ) // Provider is the core interface that all Terraform providers must implement. -// Providers must also implement the Schema method or the deprecated GetSchema -// method. The Schema method will be required in a future version. // // Providers can optionally implement these additional concepts: // @@ -19,6 +15,9 @@ import ( // via ProviderWithConfigValidators or ProviderWithValidateConfig. // - Meta Schema: ProviderWithMetaSchema type Provider interface { + // Schema should return the schema for this provider. + Schema(context.Context, SchemaRequest, *SchemaResponse) + // Configure is called at the beginning of the provider lifecycle, when // Terraform sends to the provider the values the user specified in the // provider configuration block. These are supplied in the @@ -58,18 +57,6 @@ type ProviderWithConfigValidators interface { ConfigValidators(context.Context) []ConfigValidator } -// ProviderWithGetSchema is a temporary interface type that extends -// Provider to include the deprecated GetSchema method. -type ProviderWithGetSchema interface { - Provider - - // GetSchema should return the schema for this provider's configuration. - // If there should be no configuration, return an empty schema. - // - // Deprecated: Use Schema method instead. - GetSchema(context.Context) (tfsdk.Schema, diag.Diagnostics) -} - // ProviderWithMetadata is an interface type that extends Provider to // return its type name, such as examplecloud, and other // metadata, such as version. @@ -106,15 +93,6 @@ type ProviderWithMetaSchema interface { MetaSchema(context.Context, MetaSchemaRequest, *MetaSchemaResponse) } -// ProviderWithSchema is a temporary interface type that extends -// Provider to include the new Schema method. -type ProviderWithSchema interface { - Provider - - // Schema should return the schema for this provider. - Schema(context.Context, SchemaRequest, *SchemaResponse) -} - // ProviderWithValidateConfig is an interface type that extends Provider to include imperative validation. // // Declaring validation using this methodology simplifies one-off diff --git a/resource/plan_modifiers.go b/resource/plan_modifiers.go deleted file mode 100644 index 03653b3b7..000000000 --- a/resource/plan_modifiers.go +++ /dev/null @@ -1,347 +0,0 @@ -package resource - -import ( - "context" - "errors" - "fmt" - - "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/diag" - "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" - "github.com/hashicorp/terraform-plugin-framework/internal/logging" - "github.com/hashicorp/terraform-plugin-framework/internal/totftypes" - "github.com/hashicorp/terraform-plugin-framework/path" - "github.com/hashicorp/terraform-plugin-framework/tfsdk" -) - -// RequiresReplace returns an AttributePlanModifier specifying the attribute as -// requiring replacement. This behaviour is identical to the ForceNew behaviour -// in terraform-plugin-sdk and will result in the resource being destroyed and -// recreated when the following conditions are met: -// -// 1. The resource's state is not null; a null state indicates that we're -// creating a resource, and we never need to destroy and recreate a resource -// when we're creating it. -// -// 2. The resource's plan is not null; a null plan indicates that we're -// deleting a resource, and we never need to destroy and recreate a resource -// when we're deleting it. -// -// 3. The attribute's config is not null or the attribute is not computed; a -// computed attribute with a null config almost always means that the provider -// is changing the value, and practitioners are usually unpleasantly surprised -// when a resource is destroyed and recreated when their configuration hasn't -// changed. This has the unfortunate side effect that removing a computed field -// from the config will not trigger a destroy and recreate cycle, even when -// that is warranted. To get around this, provider developer can implement -// their own AttributePlanModifier that handles that behavior in the way that -// most makes sense for their use case. -// -// 4. The attribute's value in the plan does not match the attribute's value in -// the state. -func RequiresReplace() tfsdk.AttributePlanModifier { - return requiresReplaceModifier{} -} - -// requiresReplaceModifier is an AttributePlanModifier that sets RequiresReplace -// on the attribute. -type requiresReplaceModifier struct{} - -// Modify fills the AttributePlanModifier interface. It sets RequiresReplace on -// the response to true if the following criteria are met: -// -// 1. The resource's state is not null; a null state indicates that we're -// creating a resource, and we never need to destroy and recreate a resource -// when we're creating it. -// -// 2. The resource's plan is not null; a null plan indicates that we're -// deleting a resource, and we never need to destroy and recreate a resource -// when we're deleting it. -// -// 3. The attribute's config is not null or the attribute is not computed; a -// computed attribute with a null config almost always means that the provider -// is changing the value, and practitioners are usually unpleasantly surprised -// when a resource is destroyed and recreated when their configuration hasn't -// changed. This has the unfortunate side effect that removing a computed field -// from the config will not trigger a destroy and recreate cycle, even when -// that is warranted. To get around this, provider developer can implement -// their own AttributePlanModifier that handles that behavior in the way that -// most makes sense for their use case. -// -// 4. The attribute's value in the plan does not match the attribute's value in -// the state. -func (r requiresReplaceModifier) Modify(ctx context.Context, req tfsdk.ModifyAttributePlanRequest, resp *tfsdk.ModifyAttributePlanResponse) { - if req.AttributeConfig == nil || req.AttributePlan == nil || req.AttributeState == nil { - // shouldn't happen, but let's not panic if it does - return - } - - if req.State.Raw.IsNull() { - // if we're creating the resource, no need to delete and - // recreate it - return - } - - if req.Plan.Raw.IsNull() { - // if we're deleting the resource, no need to delete and - // recreate it - return - } - - // TODO: Remove after schema refactoring, Attribute is exposed in - // ModifyAttributePlanRequest, or Computed is exposed in - // ModifyAttributePlanRequest. - // Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/365 - // Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/389 - tftypesPath, diags := totftypes.AttributePath(ctx, req.AttributePath) - - resp.Diagnostics.Append(diags...) - - if resp.Diagnostics.HasError() { - return - } - - attrSchema, err := req.State.Schema.AttributeAtTerraformPath(ctx, tftypesPath) - - // Path may lead to block instead of attribute. Blocks cannot be Computed. - // If ErrPathIsBlock, attrSchema.Computed will still be false later. - if err != nil && !errors.Is(err, fwschema.ErrPathIsBlock) { - resp.Diagnostics.AddAttributeError(req.AttributePath, - "Error finding attribute schema", - fmt.Sprintf("An unexpected error was encountered retrieving the schema for this attribute. This is always a bug in the provider.\n\nError: %s", err), - ) - return - } - - if req.AttributeConfig.IsNull() && attrSchema.IsComputed() { - // if the config is null and the attribute is computed, this - // could be an out of band change, don't require replace - return - } - - if req.AttributePlan.Equal(req.AttributeState) { - // if the plan and the state are in agreement, this attribute - // isn't changing, don't require replace - return - } - - resp.RequiresReplace = true -} - -// Description returns a human-readable description of the plan modifier. -func (r requiresReplaceModifier) Description(ctx context.Context) string { - return "If the value of this attribute changes, Terraform will destroy and recreate the resource." -} - -// MarkdownDescription returns a markdown description of the plan modifier. -func (r requiresReplaceModifier) MarkdownDescription(ctx context.Context) string { - return "If the value of this attribute changes, Terraform will destroy and recreate the resource." -} - -// RequiresReplaceIf returns an AttributePlanModifier that mimics -// RequiresReplace, but only when the passed function `f` returns true. The -// resource will be destroyed and recreated if `f` returns true and the -// following conditions are met: -// -// 1. The resource's state is not null; a null state indicates that we're -// creating a resource, and we never need to destroy and recreate a resource -// when we're creating it. -// -// 2. The resource's plan is not null; a null plan indicates that we're -// deleting a resource, and we never need to destroy and recreate a resource -// when we're deleting it. -// -// 3. The attribute's config is not null or the attribute is not computed; a -// computed attribute with a null config almost always means that the provider -// is changing the value, and practitioners are usually unpleasantly surprised -// when a resource is destroyed and recreated when their configuration hasn't -// changed. This has the unfortunate side effect that removing a computed field -// from the config will not trigger a destroy and recreate cycle, even when -// that is warranted. To get around this, provider developer can implement -// their own AttributePlanModifier that handles that behavior in the way that -// most makes sense for their use case. -// -// 4. The attribute's value in the plan does not match the attribute's value in -// the state. -// -// If `f` does not return true, RequiresReplaceIf will *not* override prior -// AttributePlanModifiers' determination of whether the resource needs to be -// recreated or not. This allows for multiple RequiresReplaceIf (or other -// modifiers that sometimes set RequiresReplace) to be used on a single -// attribute without the last one in the list always determining the outcome. -func RequiresReplaceIf(f RequiresReplaceIfFunc, description, markdownDescription string) tfsdk.AttributePlanModifier { - return requiresReplaceIfModifier{ - f: f, - description: description, - markdownDescription: markdownDescription, - } -} - -// RequiresReplaceIfFunc is a conditional function used in the RequiresReplaceIf -// plan modifier to determine whether the attribute requires replacement. -type RequiresReplaceIfFunc func(ctx context.Context, state, config attr.Value, path path.Path) (bool, diag.Diagnostics) - -// requiresReplaceIfModifier is an AttributePlanModifier that sets RequiresReplace -// on the attribute if the conditional function returns true. -type requiresReplaceIfModifier struct { - f RequiresReplaceIfFunc - description string - markdownDescription string -} - -// Modify fills the AttributePlanModifier interface. It sets RequiresReplace on -// the response to true if the following criteria are met: -// -// 1. `f` returns true. If `f` returns false, the response will not be modified -// at all. -// -// 2. The resource's state is not null; a null state indicates that we're -// creating a resource, and we never need to destroy and recreate a resource -// when we're creating it. -// -// 3. The resource's plan is not null; a null plan indicates that we're -// deleting a resource, and we never need to destroy and recreate a resource -// when we're deleting it. -// -// 4. The attribute's config is not null or the attribute is not computed; a -// computed attribute with a null config almost always means that the provider -// is changing the value, and practitioners are usually unpleasantly surprised -// when a resource is destroyed and recreated when their configuration hasn't -// changed. This has the unfortunate side effect that removing a computed field -// from the config will not trigger a destroy and recreate cycle, even when -// that is warranted. To get around this, provider developer can implement -// their own AttributePlanModifier that handles that behavior in the way that -// most makes sense for their use case. -// -// 5. The attribute's value in the plan does not match the attribute's value in -// the state. -func (r requiresReplaceIfModifier) Modify(ctx context.Context, req tfsdk.ModifyAttributePlanRequest, resp *tfsdk.ModifyAttributePlanResponse) { - if req.AttributeConfig == nil || req.AttributePlan == nil || req.AttributeState == nil { - // shouldn't happen, but let's not panic if it does - return - } - - if req.State.Raw.IsNull() { - // if we're creating the resource, no need to delete and - // recreate it - return - } - - if req.Plan.Raw.IsNull() { - // if we're deleting the resource, no need to delete and - // recreate it - return - } - - // TODO: Remove after schema refactoring, Attribute is exposed in - // ModifyAttributePlanRequest, or Computed is exposed in - // ModifyAttributePlanRequest. - // Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/365 - // Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/389 - tftypesPath, diags := totftypes.AttributePath(ctx, req.AttributePath) - - resp.Diagnostics.Append(diags...) - - if resp.Diagnostics.HasError() { - return - } - - attrSchema, err := req.State.Schema.AttributeAtTerraformPath(ctx, tftypesPath) - - // Path may lead to block instead of attribute. Blocks cannot be Computed. - // If ErrPathIsBlock, attrSchema.Computed will still be false later. - if err != nil && !errors.Is(err, fwschema.ErrPathIsBlock) { - resp.Diagnostics.AddAttributeError(req.AttributePath, - "Error finding attribute schema", - fmt.Sprintf("An unexpected error was encountered retrieving the schema for this attribute. This is always a bug in the provider.\n\nError: %s", err), - ) - return - } - - if req.AttributeConfig.IsNull() && attrSchema.IsComputed() { - // if the config is null and the attribute is computed, this - // could be an out of band change, don't require replace - return - } - - if req.AttributePlan.Equal(req.AttributeState) { - // if the plan and the state are in agreement, this attribute - // isn't changing, don't require replace - return - } - - res, diags := r.f(ctx, req.AttributeState, req.AttributeConfig, req.AttributePath) - resp.Diagnostics.Append(diags...) - - // If the function says to require replacing, we require replacing. - // If the function says not to, we don't change the value that prior - // plan modifiers may have set. - if res { - resp.RequiresReplace = true - } else if resp.RequiresReplace { - logging.FrameworkDebug(ctx, "Keeping previous attribute replacement requirement") - } -} - -// Description returns a human-readable description of the plan modifier. -func (r requiresReplaceIfModifier) Description(ctx context.Context) string { - return r.description -} - -// MarkdownDescription returns a markdown description of the plan modifier. -func (r requiresReplaceIfModifier) MarkdownDescription(ctx context.Context) string { - return r.markdownDescription -} - -// UseStateForUnknown returns an AttributePlanModifier that copies the prior -// state value for an attribute into that attribute's plan, if that state is -// non-null. -// -// Computed attributes without the UseStateForUnknown attribute plan modifier -// will have their value set to Unknown in the plan by the framework to prevent -// Terraform errors, so their value always will be displayed as "(known after -// apply)" in the CLI plan output. Using this plan modifier will instead -// display the prior state value in the plan, unless a prior plan modifier -// adjusts the value. -func UseStateForUnknown() tfsdk.AttributePlanModifier { - return useStateForUnknownModifier{} -} - -// useStateForUnknownModifier implements the UseStateForUnknown -// AttributePlanModifier. -type useStateForUnknownModifier struct{} - -// Modify copies the attribute's prior state to the attribute plan if the prior -// state value is not null. -func (r useStateForUnknownModifier) Modify(ctx context.Context, req tfsdk.ModifyAttributePlanRequest, resp *tfsdk.ModifyAttributePlanResponse) { - if req.AttributeState == nil || resp.AttributePlan == nil || req.AttributeConfig == nil { - return - } - - // if we have no state value, there's nothing to preserve - if req.AttributeState.IsNull() { - return - } - - // if it's not planned to be the unknown value, stick with the concrete plan - if !resp.AttributePlan.IsUnknown() { - return - } - - // if the config is the unknown value, use the unknown value otherwise, interpolation gets messed up - if req.AttributeConfig.IsUnknown() { - return - } - - resp.AttributePlan = req.AttributeState -} - -// Description returns a human-readable description of the plan modifier. -func (r useStateForUnknownModifier) Description(ctx context.Context) string { - return "Once set, the value of this attribute in state will not change." -} - -// MarkdownDescription returns a markdown description of the plan modifier. -func (r useStateForUnknownModifier) MarkdownDescription(ctx context.Context) string { - return "Once set, the value of this attribute in state will not change." -} diff --git a/resource/plan_modifiers_test.go b/resource/plan_modifiers_test.go deleted file mode 100644 index ba985bc67..000000000 --- a/resource/plan_modifiers_test.go +++ /dev/null @@ -1,1561 +0,0 @@ -package resource_test - -import ( - "context" - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/diag" - "github.com/hashicorp/terraform-plugin-framework/path" - "github.com/hashicorp/terraform-plugin-framework/resource" - "github.com/hashicorp/terraform-plugin-framework/tfsdk" - "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/hashicorp/terraform-plugin-go/tftypes" -) - -func TestUseStateForUnknownModifier(t *testing.T) { - t.Parallel() - - type testCase struct { - state attr.Value - plan attr.Value - config attr.Value - expected attr.Value - } - - tests := map[string]testCase{ - "nil-state": { - // this honestly just shouldn't happen, but let's be - // sure we're not going to panic if it does - state: nil, - plan: types.StringUnknown(), - config: types.StringNull(), - expected: types.StringUnknown(), - }, - "nil-plan": { - // this honestly just shouldn't happen, but let's be - // sure we're not going to panic if it does - state: types.StringNull(), - plan: nil, - config: types.StringNull(), - expected: nil, - }, - "null-state": { - // when we first create the resource, use the unknown - // value - state: types.StringNull(), - plan: types.StringUnknown(), - config: types.StringNull(), - expected: types.StringUnknown(), - }, - "known-plan": { - // this would really only happen if we had a plan - // modifier setting the value before this plan modifier - // got to it - // - // but we still want to preserve that value, in this - // case - state: types.StringValue("foo"), - plan: types.StringValue("bar"), - config: types.StringNull(), - expected: types.StringValue("bar"), - }, - "non-null-state-unknown-plan": { - // this is the situation we want to preserve the state - // in - state: types.StringValue("foo"), - plan: types.StringUnknown(), - config: types.StringNull(), - expected: types.StringValue("foo"), - }, - "unknown-config": { - // this is the situation in which a user is - // interpolating into a field. We want that to still - // show up as unknown, otherwise they'll get apply-time - // errors for changing the value even though we knew it - // was legitimately possible for it to change and the - // provider can't prevent this from happening - state: types.StringValue("foo"), - plan: types.StringUnknown(), - config: types.StringUnknown(), - expected: types.StringUnknown(), - }, - } - - for name, tc := range tests { - name, tc := name, tc - t.Run(name, func(t *testing.T) { - t.Parallel() - - schema := tfsdk.Schema{ - Attributes: map[string]tfsdk.Attribute{ - "a": { - Type: types.StringType, - Optional: true, - Computed: true, - }, - }, - } - - configVal := tftypes.NewValue(tftypes.String, nil) - stateVal := tftypes.NewValue(tftypes.String, nil) - planVal := tftypes.NewValue(tftypes.String, nil) - if tc.config != nil { - val, err := tc.config.ToTerraformValue(context.Background()) - if err != nil { - t.Fatal(err) - } - configVal = val - } - if tc.state != nil { - val, err := tc.state.ToTerraformValue(context.Background()) - if err != nil { - t.Fatal(err) - } - stateVal = val - } - if tc.plan != nil { - val, err := tc.plan.ToTerraformValue(context.Background()) - if err != nil { - t.Fatal(err) - } - planVal = val - } - - req := tfsdk.ModifyAttributePlanRequest{ - AttributePath: path.Empty(), - Config: tfsdk.Config{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "a": configVal, - }), - }, - State: tfsdk.State{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "a": stateVal, - }), - }, - Plan: tfsdk.Plan{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "a": planVal, - }), - }, - AttributeConfig: tc.config, - AttributeState: tc.state, - AttributePlan: tc.plan, - ProviderMeta: tfsdk.Config{}, - } - resp := &tfsdk.ModifyAttributePlanResponse{ - AttributePlan: req.AttributePlan, - } - modifier := resource.UseStateForUnknown() - - modifier.Modify(context.Background(), req, resp) - if resp.Diagnostics.HasError() { - t.Fatalf("Unexpected diagnostics: %s", resp.Diagnostics) - } - if diff := cmp.Diff(tc.expected, resp.AttributePlan); diff != "" { - t.Errorf("Unexpected diff (-wanted, +got): %s", diff) - } - }) - } -} - -func TestRequiresReplaceModifier(t *testing.T) { - t.Parallel() - - type testCase struct { - state tfsdk.State - plan tfsdk.Plan - config tfsdk.Config - path path.Path - expectedPlan attr.Value - expectedRR bool - } - - schema := tfsdk.Schema{ - Attributes: map[string]tfsdk.Attribute{ - "optional-computed": { - Type: types.StringType, - Optional: true, - Computed: true, - }, - "optional": { - Type: types.StringType, - Optional: true, - }, - }, - } - - blockSchema := tfsdk.Schema{ - Blocks: map[string]tfsdk.Block{ - "block": { - Attributes: map[string]tfsdk.Attribute{ - "optional-computed": { - Type: types.StringType, - Optional: true, - Computed: true, - }, - "optional": { - Type: types.StringType, - Optional: true, - }, - }, - NestingMode: tfsdk.BlockNestingModeList, - }, - }, - } - - tests := map[string]testCase{ - "null-state": { - // when we first create the resource, it shouldn't - // require replacing immediately - state: tfsdk.State{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), nil), - }, - plan: tfsdk.Plan{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - config: tfsdk.Config{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - path: path.Root("optional-computed"), - expectedPlan: types.StringValue("foo"), - expectedRR: false, - }, - "null-plan": { - // when we destroy the resource, it shouldn't require - // replacing - // - // Terraform doesn't usually ask for provider input on - // the plan when destroying resources, but in case it - // does, let's make sure we handle it right - plan: tfsdk.Plan{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), nil), - }, - state: tfsdk.State{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - config: tfsdk.Config{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), nil), - }, - path: path.Root("optional-computed"), - expectedPlan: nil, - expectedRR: false, - }, - "null-attribute-state": { - // make sure we're not confusing an attribute going - // from null to a value with the resource getting - // created - state: tfsdk.State{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, nil), - }), - }, - plan: tfsdk.Plan{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - config: tfsdk.Config{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - path: path.Root("optional"), - expectedPlan: types.StringValue("bar"), - expectedRR: true, - }, - "null-attribute-plan": { - // make sure we're not confusing an attribute going - // from a value to null with the resource getting - // destroyed - state: tfsdk.State{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - plan: tfsdk.Plan{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, nil), - }), - }, - config: tfsdk.Config{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, nil), - }), - }, - path: path.Root("optional"), - expectedPlan: types.StringNull(), - expectedRR: true, - }, - "known-state-change": { - // when updating the attribute, if it has changed, it - // should require replacing - state: tfsdk.State{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - plan: tfsdk.Plan{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "quux"), - }), - }, - config: tfsdk.Config{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "quux"), - }), - }, - path: path.Root("optional"), - expectedPlan: types.StringValue("quux"), - expectedRR: true, - }, - "known-state-no-change": { - // when the attribute hasn't changed, it shouldn't - // require replacing - state: tfsdk.State{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - plan: tfsdk.Plan{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "quux"), - }), - }, - config: tfsdk.Config{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "quux"), - }), - }, - path: path.Root("optional-computed"), - expectedPlan: types.StringValue("foo"), - expectedRR: false, - }, - "null-config-computed": { - // if the config is null for a computed attribute, we - // shouldn't require replacing, even if it's a change. - // - // this is sometimes unintuitive, if the practitioner - // is changing it on purpose. However, it's - // indistinguishable from the provider changing it, and - // practitioners pretty much never expect the resource - // to be recreated if the provider is the one changing - // the value. - state: tfsdk.State{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - plan: tfsdk.Plan{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, tftypes.UnknownValue), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - config: tfsdk.Config{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, nil), - "optional": tftypes.NewValue(tftypes.String, "quux"), - }), - }, - path: path.Root("optional-computed"), - expectedPlan: types.StringUnknown(), - expectedRR: false, - }, - "null-config-not-computed": { - // if the config is null for a non-computed attribute, - // we should require replacing if it's a change. - // - // unlike computed attributes, this is always a - // practitioner making a change, and therefore the - // destroy/recreate cycle is likely expected. - // - // this test is technically covered by - // null-attribute-plan, but let's duplicate it just to - // be explicit about what each case is actually testing - state: tfsdk.State{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - plan: tfsdk.Plan{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, nil), - }), - }, - config: tfsdk.Config{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, nil), - }), - }, - path: path.Root("optional"), - expectedPlan: types.StringNull(), - expectedRR: true, - }, - "block-no-change": { - state: tfsdk.State{ - Schema: blockSchema, - Raw: tftypes.NewValue(blockSchema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "block": tftypes.NewValue( - tftypes.List{ - ElementType: tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, - }, []tftypes.Value{ - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "samevalue"), - "optional": tftypes.NewValue(tftypes.String, "samevalue"), - }), - }), - }), - }, - plan: tfsdk.Plan{ - Schema: blockSchema, - Raw: tftypes.NewValue(blockSchema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "block": tftypes.NewValue( - tftypes.List{ - ElementType: tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, - }, []tftypes.Value{ - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "samevalue"), - "optional": tftypes.NewValue(tftypes.String, "samevalue"), - }), - }), - }), - }, - config: tfsdk.Config{ - Schema: blockSchema, - Raw: tftypes.NewValue(blockSchema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "block": tftypes.NewValue( - tftypes.List{ - ElementType: tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, - }, []tftypes.Value{ - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "samevalue"), - "optional": tftypes.NewValue(tftypes.String, "samevalue"), - }), - }), - }), - }, - path: path.Root("block"), - expectedPlan: types.ListValueMust( - types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "optional-computed": types.StringType, - "optional": types.StringType, - }, - }, - []attr.Value{ - types.ObjectValueMust( - map[string]attr.Type{ - "optional-computed": types.StringType, - "optional": types.StringType, - }, - map[string]attr.Value{ - "optional-computed": types.StringValue("samevalue"), - "optional": types.StringValue("samevalue"), - }, - ), - }, - ), - expectedRR: false, - }, - "block-element-count-change": { - state: tfsdk.State{ - Schema: blockSchema, - Raw: tftypes.NewValue(blockSchema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "block": tftypes.NewValue( - tftypes.List{ - ElementType: tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, - }, []tftypes.Value{ - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "samevalue"), - "optional": tftypes.NewValue(tftypes.String, "samevalue"), - }), - }), - }), - }, - plan: tfsdk.Plan{ - Schema: blockSchema, - Raw: tftypes.NewValue(blockSchema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "block": tftypes.NewValue( - tftypes.List{ - ElementType: tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, - }, []tftypes.Value{ - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "samevalue"), - "optional": tftypes.NewValue(tftypes.String, "samevalue"), - }), - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "newvalue"), - "optional": tftypes.NewValue(tftypes.String, "newvalue"), - }), - }), - }), - }, - config: tfsdk.Config{ - Schema: blockSchema, - Raw: tftypes.NewValue(blockSchema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "block": tftypes.NewValue( - tftypes.List{ - ElementType: tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, - }, []tftypes.Value{ - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "samevalue"), - "optional": tftypes.NewValue(tftypes.String, "samevalue"), - }), - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "newvalue"), - "optional": tftypes.NewValue(tftypes.String, "newvalue"), - }), - }), - }), - }, - path: path.Root("block"), - expectedPlan: types.ListValueMust( - types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "optional-computed": types.StringType, - "optional": types.StringType, - }, - }, - []attr.Value{ - types.ObjectValueMust( - map[string]attr.Type{ - "optional-computed": types.StringType, - "optional": types.StringType, - }, - map[string]attr.Value{ - "optional-computed": types.StringValue("samevalue"), - "optional": types.StringValue("samevalue"), - }, - ), - types.ObjectValueMust( - map[string]attr.Type{ - "optional-computed": types.StringType, - "optional": types.StringType, - }, - map[string]attr.Value{ - "optional-computed": types.StringValue("newvalue"), - "optional": types.StringValue("newvalue"), - }, - ), - }, - ), - expectedRR: true, - }, - "block-nested-attribute-change": { - state: tfsdk.State{ - Schema: blockSchema, - Raw: tftypes.NewValue(blockSchema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "block": tftypes.NewValue( - tftypes.List{ - ElementType: tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, - }, []tftypes.Value{ - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "samevalue"), - "optional": tftypes.NewValue(tftypes.String, "oldvalue"), - }), - }), - }), - }, - plan: tfsdk.Plan{ - Schema: blockSchema, - Raw: tftypes.NewValue(blockSchema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "block": tftypes.NewValue( - tftypes.List{ - ElementType: tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, - }, []tftypes.Value{ - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "samevalue"), - "optional": tftypes.NewValue(tftypes.String, "newvalue"), - }), - }), - }), - }, - config: tfsdk.Config{ - Schema: blockSchema, - Raw: tftypes.NewValue(blockSchema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "block": tftypes.NewValue( - tftypes.List{ - ElementType: tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, - }, []tftypes.Value{ - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "samevalue"), - "optional": tftypes.NewValue(tftypes.String, "newvalue"), - }), - }), - }), - }, - path: path.Root("block"), - expectedPlan: types.ListValueMust( - types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "optional-computed": types.StringType, - "optional": types.StringType, - }, - }, - []attr.Value{ - types.ObjectValueMust( - map[string]attr.Type{ - "optional-computed": types.StringType, - "optional": types.StringType, - }, - map[string]attr.Value{ - "optional-computed": types.StringValue("samevalue"), - "optional": types.StringValue("newvalue"), - }, - ), - }, - ), - expectedRR: true, - }, - } - - for name, tc := range tests { - name, tc := name, tc - t.Run(name, func(t *testing.T) { - t.Parallel() - - var attrConfig, attrPlan, attrState attr.Value - - if !tc.config.Raw.IsNull() { - if diags := tc.config.GetAttribute(context.Background(), tc.path, &attrConfig); diags.HasError() { - t.Fatalf("Got unexpected diagnostics: %s", diags) - } - } - - if !tc.state.Raw.IsNull() { - if diags := tc.state.GetAttribute(context.Background(), tc.path, &attrState); diags.HasError() { - t.Fatalf("Got unexpected diagnostics: %s", diags) - } - } - - if !tc.plan.Raw.IsNull() { - if diags := tc.plan.GetAttribute(context.Background(), tc.path, &attrPlan); diags.HasError() { - t.Fatalf("Got unexpected diagnostics: %s", diags) - } - } - - req := tfsdk.ModifyAttributePlanRequest{ - AttributePath: tc.path, - Config: tc.config, - State: tc.state, - Plan: tc.plan, - AttributeConfig: attrConfig, - AttributeState: attrState, - AttributePlan: attrPlan, - ProviderMeta: tfsdk.Config{}, - } - resp := &tfsdk.ModifyAttributePlanResponse{ - AttributePlan: req.AttributePlan, - } - modifier := resource.RequiresReplace() - - modifier.Modify(context.Background(), req, resp) - if resp.Diagnostics.HasError() { - t.Fatalf("Unexpected diagnostics: %s", resp.Diagnostics) - } - if diff := cmp.Diff(tc.expectedPlan, resp.AttributePlan); diff != "" { - t.Fatalf("Unexpected diff in plan (-wanted, +got): %s", diff) - } - if diff := cmp.Diff(tc.expectedRR, resp.RequiresReplace); diff != "" { - t.Fatalf("Unexpected diff in RequiresReplace (-wanted, +got): %s", diff) - } - }) - } -} - -func TestRequiresReplaceIfModifier(t *testing.T) { - t.Parallel() - - type testCase struct { - state tfsdk.State - plan tfsdk.Plan - config tfsdk.Config - priorRR bool - path path.Path - ifReturn bool - expectedPlan attr.Value - expectedRR bool - } - - schema := tfsdk.Schema{ - Attributes: map[string]tfsdk.Attribute{ - "optional-computed": { - Type: types.StringType, - Optional: true, - Computed: true, - }, - "optional": { - Type: types.StringType, - Optional: true, - }, - }, - } - - blockSchema := tfsdk.Schema{ - Blocks: map[string]tfsdk.Block{ - "block": { - Attributes: map[string]tfsdk.Attribute{ - "optional-computed": { - Type: types.StringType, - Optional: true, - Computed: true, - }, - "optional": { - Type: types.StringType, - Optional: true, - }, - }, - NestingMode: tfsdk.BlockNestingModeList, - }, - }, - } - - tests := map[string]testCase{ - "null-state": { - // when we first create the resource, it shouldn't - // require replacing immediately - state: tfsdk.State{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), nil), - }, - plan: tfsdk.Plan{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - config: tfsdk.Config{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - priorRR: false, - path: path.Root("optional-computed"), - ifReturn: true, - expectedPlan: types.StringValue("foo"), - expectedRR: false, - }, - "null-plan": { - // when we destroy the resource, it shouldn't require - // replacing - // - // Terraform doesn't usually ask for provider input on - // the plan when destroying resources, but in case it - // does, let's make sure we handle it right - plan: tfsdk.Plan{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), nil), - }, - state: tfsdk.State{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - config: tfsdk.Config{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), nil), - }, - priorRR: false, - path: path.Root("optional-computed"), - ifReturn: true, - expectedPlan: nil, - expectedRR: false, - }, - "null-attribute-state": { - // make sure we're not confusing an attribute going - // from null to a value with the resource getting - // created - state: tfsdk.State{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, nil), - }), - }, - plan: tfsdk.Plan{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - config: tfsdk.Config{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - priorRR: false, - path: path.Root("optional"), - ifReturn: true, - expectedPlan: types.StringValue("bar"), - expectedRR: true, - }, - "null-attribute-plan": { - // make sure we're not confusing an attribute going - // from a value to null with the resource getting - // destroyed - state: tfsdk.State{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - plan: tfsdk.Plan{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, nil), - }), - }, - config: tfsdk.Config{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, nil), - }), - }, - priorRR: false, - ifReturn: true, - path: path.Root("optional"), - expectedPlan: types.StringNull(), - expectedRR: true, - }, - "known-state-change-true": { - // when updating the attribute, if it has changed and - // the function returns true, it should require - // replacing - state: tfsdk.State{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - plan: tfsdk.Plan{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "quux"), - }), - }, - config: tfsdk.Config{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "quux"), - }), - }, - priorRR: false, - path: path.Root("optional"), - ifReturn: true, - expectedPlan: types.StringValue("quux"), - expectedRR: true, - }, - "known-state-change-false": { - // when updating the attribute, if it has changed and - // the function returns false, it should not require - // replacing - state: tfsdk.State{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - plan: tfsdk.Plan{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "quux"), - }), - }, - config: tfsdk.Config{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "quux"), - }), - }, - priorRR: false, - path: path.Root("optional"), - ifReturn: false, - expectedPlan: types.StringValue("quux"), - expectedRR: false, - }, - "known-state-change-false-dont-override": { - // when updating the attribute, if it has changed and - // the function returns false, but a prior plan - // modifier already marked the resource as needing to - // be recreated, we shouldn't override that - state: tfsdk.State{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - plan: tfsdk.Plan{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "quux"), - }), - }, - config: tfsdk.Config{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "quux"), - }), - }, - priorRR: true, - path: path.Root("optional"), - ifReturn: false, - expectedPlan: types.StringValue("quux"), - expectedRR: true, - }, - "known-state-no-change": { - // when the attribute hasn't changed, it shouldn't - // require replacing - state: tfsdk.State{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - plan: tfsdk.Plan{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "quux"), - }), - }, - config: tfsdk.Config{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "quux"), - }), - }, - priorRR: false, - path: path.Root("optional-computed"), - ifReturn: true, - expectedPlan: types.StringValue("foo"), - expectedRR: false, - }, - "null-config-computed": { - // if the config is null for a computed attribute, we - // shouldn't require replacing, even if it's a change. - // - // this is sometimes unintuitive, if the practitioner - // is changing it on purpose. However, it's - // indistinguishable from the provider changing it, and - // practitioners pretty much never expect the resource - // to be recreated if the provider is the one changing - // the value. - state: tfsdk.State{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - plan: tfsdk.Plan{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, tftypes.UnknownValue), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - config: tfsdk.Config{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, nil), - "optional": tftypes.NewValue(tftypes.String, "quux"), - }), - }, - priorRR: false, - path: path.Root("optional-computed"), - ifReturn: true, - expectedPlan: types.StringUnknown(), - expectedRR: false, - }, - "null-config-not-computed": { - // if the config is null for a non-computed attribute, - // we should require replacing if it's a change. - // - // unlike computed attributes, this is always a - // practitioner making a change, and therefore the - // destroy/recreate cycle is likely expected. - // - // this test is technically covered by - // null-attribute-plan, but let's duplicate it just to - // be explicit about what each case is actually testing - state: tfsdk.State{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, "bar"), - }), - }, - plan: tfsdk.Plan{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, nil), - }), - }, - config: tfsdk.Config{ - Schema: schema, - Raw: tftypes.NewValue(schema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "foo"), - "optional": tftypes.NewValue(tftypes.String, nil), - }), - }, - priorRR: false, - path: path.Root("optional"), - ifReturn: true, - expectedPlan: types.StringNull(), - expectedRR: true, - }, - "block-no-change": { - state: tfsdk.State{ - Schema: blockSchema, - Raw: tftypes.NewValue(blockSchema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "block": tftypes.NewValue( - tftypes.List{ - ElementType: tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, - }, []tftypes.Value{ - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "samevalue"), - "optional": tftypes.NewValue(tftypes.String, "samevalue"), - }), - }), - }), - }, - plan: tfsdk.Plan{ - Schema: blockSchema, - Raw: tftypes.NewValue(blockSchema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "block": tftypes.NewValue( - tftypes.List{ - ElementType: tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, - }, []tftypes.Value{ - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "samevalue"), - "optional": tftypes.NewValue(tftypes.String, "samevalue"), - }), - }), - }), - }, - config: tfsdk.Config{ - Schema: blockSchema, - Raw: tftypes.NewValue(blockSchema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "block": tftypes.NewValue( - tftypes.List{ - ElementType: tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, - }, []tftypes.Value{ - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "samevalue"), - "optional": tftypes.NewValue(tftypes.String, "samevalue"), - }), - }), - }), - }, - path: path.Root("block"), - expectedPlan: types.ListValueMust( - types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "optional-computed": types.StringType, - "optional": types.StringType, - }, - }, - []attr.Value{ - types.ObjectValueMust( - map[string]attr.Type{ - "optional-computed": types.StringType, - "optional": types.StringType, - }, - map[string]attr.Value{ - "optional-computed": types.StringValue("samevalue"), - "optional": types.StringValue("samevalue"), - }, - ), - }, - ), - ifReturn: false, - expectedRR: false, - }, - "block-element-count-change": { - state: tfsdk.State{ - Schema: blockSchema, - Raw: tftypes.NewValue(blockSchema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "block": tftypes.NewValue( - tftypes.List{ - ElementType: tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, - }, []tftypes.Value{ - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "samevalue"), - "optional": tftypes.NewValue(tftypes.String, "samevalue"), - }), - }), - }), - }, - plan: tfsdk.Plan{ - Schema: blockSchema, - Raw: tftypes.NewValue(blockSchema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "block": tftypes.NewValue( - tftypes.List{ - ElementType: tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, - }, []tftypes.Value{ - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "samevalue"), - "optional": tftypes.NewValue(tftypes.String, "samevalue"), - }), - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "newvalue"), - "optional": tftypes.NewValue(tftypes.String, "newvalue"), - }), - }), - }), - }, - config: tfsdk.Config{ - Schema: blockSchema, - Raw: tftypes.NewValue(blockSchema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "block": tftypes.NewValue( - tftypes.List{ - ElementType: tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, - }, []tftypes.Value{ - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "samevalue"), - "optional": tftypes.NewValue(tftypes.String, "samevalue"), - }), - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "newvalue"), - "optional": tftypes.NewValue(tftypes.String, "newvalue"), - }), - }), - }), - }, - path: path.Root("block"), - expectedPlan: types.ListValueMust( - types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "optional-computed": types.StringType, - "optional": types.StringType, - }, - }, - []attr.Value{ - types.ObjectValueMust( - map[string]attr.Type{ - "optional-computed": types.StringType, - "optional": types.StringType, - }, - map[string]attr.Value{ - "optional-computed": types.StringValue("samevalue"), - "optional": types.StringValue("samevalue"), - }, - ), - types.ObjectValueMust( - map[string]attr.Type{ - "optional-computed": types.StringType, - "optional": types.StringType, - }, - map[string]attr.Value{ - "optional-computed": types.StringValue("newvalue"), - "optional": types.StringValue("newvalue"), - }, - ), - }, - ), - ifReturn: true, - expectedRR: true, - }, - "block-nested-attribute-change": { - state: tfsdk.State{ - Schema: blockSchema, - Raw: tftypes.NewValue(blockSchema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "block": tftypes.NewValue( - tftypes.List{ - ElementType: tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, - }, []tftypes.Value{ - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "samevalue"), - "optional": tftypes.NewValue(tftypes.String, "oldvalue"), - }), - }), - }), - }, - plan: tfsdk.Plan{ - Schema: blockSchema, - Raw: tftypes.NewValue(blockSchema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "block": tftypes.NewValue( - tftypes.List{ - ElementType: tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, - }, []tftypes.Value{ - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "samevalue"), - "optional": tftypes.NewValue(tftypes.String, "newvalue"), - }), - }), - }), - }, - config: tfsdk.Config{ - Schema: blockSchema, - Raw: tftypes.NewValue(blockSchema.Type().TerraformType(context.Background()), map[string]tftypes.Value{ - "block": tftypes.NewValue( - tftypes.List{ - ElementType: tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, - }, []tftypes.Value{ - tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "optional-computed": tftypes.String, - "optional": tftypes.String, - }, - }, map[string]tftypes.Value{ - "optional-computed": tftypes.NewValue(tftypes.String, "samevalue"), - "optional": tftypes.NewValue(tftypes.String, "newvalue"), - }), - }), - }), - }, - path: path.Root("block"), - expectedPlan: types.ListValueMust( - types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "optional-computed": types.StringType, - "optional": types.StringType, - }, - }, - []attr.Value{ - types.ObjectValueMust( - map[string]attr.Type{ - "optional-computed": types.StringType, - "optional": types.StringType, - }, - map[string]attr.Value{ - "optional-computed": types.StringValue("samevalue"), - "optional": types.StringValue("newvalue"), - }, - ), - }, - ), - ifReturn: true, - expectedRR: true, - }, - } - - for name, tc := range tests { - name, tc := name, tc - t.Run(name, func(t *testing.T) { - t.Parallel() - - var attrConfig, attrPlan, attrState attr.Value - - if !tc.config.Raw.IsNull() { - if diags := tc.config.GetAttribute(context.Background(), tc.path, &attrConfig); diags.HasError() { - t.Fatalf("Got unexpected diagnostics: %s", diags) - } - } - - if !tc.state.Raw.IsNull() { - if diags := tc.state.GetAttribute(context.Background(), tc.path, &attrState); diags.HasError() { - t.Fatalf("Got unexpected diagnostics: %s", diags) - } - } - - if !tc.plan.Raw.IsNull() { - if diags := tc.plan.GetAttribute(context.Background(), tc.path, &attrPlan); diags.HasError() { - t.Fatalf("Got unexpected diagnostics: %s", diags) - } - } - - req := tfsdk.ModifyAttributePlanRequest{ - AttributePath: tc.path, - Config: tc.config, - State: tc.state, - Plan: tc.plan, - AttributeConfig: attrConfig, - AttributeState: attrState, - AttributePlan: attrPlan, - ProviderMeta: tfsdk.Config{}, - } - resp := &tfsdk.ModifyAttributePlanResponse{ - AttributePlan: req.AttributePlan, - RequiresReplace: tc.priorRR, - } - modifier := resource.RequiresReplaceIf(func(ctx context.Context, state, config attr.Value, path path.Path) (bool, diag.Diagnostics) { - return tc.ifReturn, nil - }, "", "") - - modifier.Modify(context.Background(), req, resp) - if resp.Diagnostics.HasError() { - t.Fatalf("Unexpected diagnostics: %s", resp.Diagnostics) - } - if diff := cmp.Diff(tc.expectedPlan, resp.AttributePlan); diff != "" { - t.Fatalf("Unexpected diff in plan (-wanted, +got): %s", diff) - } - if diff := cmp.Diff(tc.expectedRR, resp.RequiresReplace); diff != "" { - t.Fatalf("Unexpected diff in RequiresReplace (-wanted, +got): %s", diff) - } - }) - } -} diff --git a/resource/resource.go b/resource/resource.go index e811da77c..9000fda5d 100644 --- a/resource/resource.go +++ b/resource/resource.go @@ -2,23 +2,18 @@ package resource import ( "context" - - "github.com/hashicorp/terraform-plugin-framework/diag" - "github.com/hashicorp/terraform-plugin-framework/tfsdk" ) // Resource represents an instance of a managed resource type. This is the core -// interface that all resources must implement. Resources must also -// implement the Schema method or the deprecated GetSchema method. The Schema -// method will be required in a future version. +// interface that all resources must implement. // // Resources can optionally implement these additional concepts: // // - Configure: Include provider-level data or clients. // - Import: ResourceWithImportState -// - Validation: Schema-based via tfsdk.Attribute or entire configuration +// - Validation: Schema-based or entire configuration // via ResourceWithConfigValidators or ResourceWithValidateConfig. -// - Plan Modification: Schema-based via tfsdk.Attribute or entire plan +// - Plan Modification: Schema-based or entire plan // via ResourceWithModifyPlan. // - State Upgrades: ResourceWithUpgradeState // @@ -29,6 +24,9 @@ type Resource interface { // examplecloud_thing. Metadata(context.Context, MetadataRequest, *MetadataResponse) + // Schema should return the schema for this resource. + Schema(context.Context, SchemaRequest, *SchemaResponse) + // Create is called when the provider must create a new resource. Config // and planned state values should be read from the // CreateRequest and new state values set on the CreateResponse. @@ -84,17 +82,6 @@ type ResourceWithConfigValidators interface { ConfigValidators(context.Context) []ConfigValidator } -// ResourceWithGetSchema is a temporary interface type that extends -// Resource to include the deprecated GetSchema method. -type ResourceWithGetSchema interface { - Resource - - // GetSchema returns the schema for this resource. - // - // Deprecated: Use Schema method instead. - GetSchema(context.Context) (tfsdk.Schema, diag.Diagnostics) -} - // Optional interface on top of Resource that enables provider control over // the ImportResourceState RPC. This RPC is called by Terraform when the // `terraform import` command is executed. Afterwards, the ReadResource RPC @@ -137,15 +124,6 @@ type ResourceWithModifyPlan interface { ModifyPlan(context.Context, ModifyPlanRequest, *ModifyPlanResponse) } -// ResourceWithSchema is a temporary interface type that extends -// Resource to include the new Schema method. -type ResourceWithSchema interface { - Resource - - // Schema should return the schema for this resource. - Schema(context.Context, SchemaRequest, *SchemaResponse) -} - // Optional interface on top of Resource that enables provider control over // the UpgradeResourceState RPC. This RPC is automatically called by Terraform // when the current Schema type Version field is greater than the stored state. diff --git a/tfsdk/attribute.go b/tfsdk/attribute.go deleted file mode 100644 index 464ccaceb..000000000 --- a/tfsdk/attribute.go +++ /dev/null @@ -1,271 +0,0 @@ -package tfsdk - -import ( - "errors" - - "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" - "github.com/hashicorp/terraform-plugin-go/tftypes" -) - -// Attribute must satify the fwschema.Attribute interface. It must also satisfy -// fwxschema.AttributeWithPlanModifiers and fwxschema.AttributeWithValidators -// interfaces, however we cannot check that here or it would introduce an -// import cycle. -var ( - _ fwschema.Attribute = Attribute{} - _ fwschema.NestedAttribute = Attribute{} -) - -// Attribute defines the constraints and behaviors of a single value field in a -// schema. Attributes are the fields that show up in Terraform state files and -// can be used in configuration files. -// -// Deprecated: Use datasource/schema.Attribute, provider/schema.Attribute, or -// resource/schema.Attribute instead. This can be switched by using the -// datasource/schema.Schema, provider/schema.Schema, or resource/schema.Schema -// types. -type Attribute struct { - // Type indicates what kind of attribute this is. You'll most likely - // want to use one of the types in the types package. - // - // If Type is set, Attributes cannot be. - Type attr.Type - - // Attributes can have their own, nested attributes. This nested map of - // attributes behaves exactly like the map of attributes on the Schema - // type. - // - // If Attributes is set, Type cannot be. - Attributes fwschema.NestedAttributes - - // Description is used in various tooling, like the language server, to - // give practitioners more information about what this attribute is, - // what it's for, and how it should be used. It should be written as - // plain text, with no special formatting. - Description string - - // MarkdownDescription is used in various tooling, like the - // documentation generator, to give practitioners more information - // about what this attribute is, what it's for, and how it should be - // used. It should be formatted using Markdown. - MarkdownDescription string - - // Required indicates whether the practitioner must enter a value for - // this attribute or not. Required and Optional cannot both be true, - // and Required and Computed cannot both be true. - Required bool - - // Optional indicates whether the practitioner can choose not to enter - // a value for this attribute or not. Optional and Required cannot both - // be true. - // - // When defining an attribute that has Optional set to true, - // and uses PlanModifiers to set a "default value" when none is provided, - // Computed must also be set to true. This is necessary because default - // values are, in effect, set by the provider (i.e. computed). - Optional bool - - // Computed indicates whether the provider may return its own value for - // this Attribute or not. Required and Computed cannot both be true. If - // Required and Optional are both false, Computed must be true, and the - // attribute will be considered "read only" for the practitioner, with - // only the provider able to set its value. - // - // When defining an Optional Attribute that has a "default value" - // plan modifier, Computed must also be set to true. Otherwise, - // Terraform will return an error like: - // - // planned value ... for a non-computed attribute - // - Computed bool - - // Sensitive indicates whether the value of this attribute should be - // considered sensitive data. Setting it to true will obscure the value - // in CLI output. Sensitive does not impact how values are stored, and - // practitioners are encouraged to store their state as if the entire - // file is sensitive. - Sensitive bool - - // DeprecationMessage defines warning diagnostic details to display when - // practitioner configurations use this Attribute. The warning diagnostic - // summary is automatically set to "Attribute Deprecated" along with - // configuration source file and line information. - // - // Set this field to a practitioner actionable message such as: - // - // - "Configure other_attribute instead. This attribute will be removed - // in the next major version of the provider." - // - "Remove this attribute's configuration as it no longer is used and - // the attribute will be removed in the next major version of the - // provider." - // - // In Terraform 1.2.7 and later, this warning diagnostic is displayed any - // time a practitioner attempts to configure a value for this attribute and - // certain scenarios where this attribute is referenced. - // - // In Terraform 1.2.6 and earlier, this warning diagnostic is only - // displayed when the Attribute is Required or Optional, and if the - // practitioner configuration sets the value to a known or unknown value - // (which may eventually be null). It has no effect when the Attribute is - // Computed-only (read-only; not Required or Optional). - // - // Across any Terraform version, there are no warnings raised for - // practitioner configuration values set directly to null, as there is no - // way for the framework to differentiate between an unset and null - // configuration due to how Terraform sends configuration information - // across the protocol. - // - // Additional information about deprecation enhancements for read-only - // attributes can be found in: - // - // - https://github.com/hashicorp/terraform/issues/7569 - // - DeprecationMessage string - - // Validators define value validation functionality for the attribute. All - // elements of the slice of AttributeValidator are run, regardless of any - // previous error diagnostics. - // - // Many common use case validators can be found in the - // github.com/hashicorp/terraform-plugin-framework-validators Go module. - // - // If the Type field points to a custom type that implements the - // xattr.TypeWithValidate interface, the validators defined in this field - // are run in addition to the validation defined by the type. - Validators []AttributeValidator - - // PlanModifiers defines a sequence of modifiers for this attribute at - // plan time. Attribute-level plan modifications occur before any - // resource-level plan modifications. - // - // Any errors will prevent further execution of this sequence - // of modifiers and modifiers associated with any nested Attribute, but - // will not prevent execution of PlanModifiers on any other Attribute or - // Block in the Schema. - // - // Plan modification only applies to resources, not data sources or - // providers. Setting PlanModifiers on a data source or provider attribute - // will have no effect. - // - // When providing PlanModifiers, it's necessary to set Computed to true. - PlanModifiers AttributePlanModifiers -} - -// ApplyTerraform5AttributePathStep transparently calls -// ApplyTerraform5AttributePathStep on a.Type or a.Attributes, whichever is -// non-nil. It allows Attributes to be walked using tftypes.Walk and -// tftypes.Transform. -func (a Attribute) ApplyTerraform5AttributePathStep(step tftypes.AttributePathStep) (interface{}, error) { - if a.Type != nil { - return a.Type.ApplyTerraform5AttributePathStep(step) - } - if a.Attributes != nil { - return a.Attributes.ApplyTerraform5AttributePathStep(step) - } - return nil, errors.New("Attribute has no type or nested attributes") -} - -// Equal returns true if `a` and `o` should be considered Equal. -func (a Attribute) Equal(o fwschema.Attribute) bool { - other, ok := o.(Attribute) - - if !ok { - return false - } - - if a.GetNestingMode() != other.GetNestingMode() { - return false - } - - if a.GetNestedObject() != nil && !a.GetNestedObject().Equal(other.GetNestedObject()) { - return false - } - - if other.GetNestedObject() != nil && !other.GetNestedObject().Equal(a.GetNestedObject()) { - return false - } - - return fwschema.AttributesEqual(a, o) -} - -// GetDeprecationMessage satisfies the fwschema.Attribute interface. -func (a Attribute) GetDeprecationMessage() string { - return a.DeprecationMessage -} - -// GetDescription satisfies the fwschema.Attribute interface. -func (a Attribute) GetDescription() string { - return a.Description -} - -// GetMarkdownDescription satisfies the fwschema.Attribute interface. -func (a Attribute) GetMarkdownDescription() string { - return a.MarkdownDescription -} - -// GetNestedObject returns a generated NestedAttributeObject if the -// Attribute represents nested attributes, otherwise nil. -func (a Attribute) GetNestedObject() fwschema.NestedAttributeObject { - if a.GetNestingMode() == fwschema.NestingModeUnknown { - return nil - } - - return nestedAttributeObject{ - Attributes: a.Attributes.GetAttributes(), - } -} - -// GetNestingMode returns the Attributes nesting mode, if set. Otherwise, -// returns NestingModeUnset. -func (a Attribute) GetNestingMode() fwschema.NestingMode { - if a.Type != nil { - return fwschema.NestingModeUnknown - } - - if a.Attributes != nil { - return a.Attributes.GetNestingMode() - } - - return fwschema.NestingModeUnknown -} - -// GetPlanModifiers satisfies the fwxschema.AttributeWithPlanModifiers -// interface. -func (a Attribute) GetPlanModifiers() AttributePlanModifiers { - return a.PlanModifiers -} - -// GetValidators satisfies the fwxschema.AttributeWithValidators interface. -func (a Attribute) GetValidators() []AttributeValidator { - return a.Validators -} - -// GetType satisfies the fwschema.Attribute interface. -func (a Attribute) GetType() attr.Type { - if a.Attributes != nil { - return a.Attributes.Type() - } - - return a.Type -} - -// IsComputed satisfies the fwschema.Attribute interface. -func (a Attribute) IsComputed() bool { - return a.Computed -} - -// IsOptional satisfies the fwschema.Attribute interface. -func (a Attribute) IsOptional() bool { - return a.Optional -} - -// IsRequired satisfies the fwschema.Attribute interface. -func (a Attribute) IsRequired() bool { - return a.Required -} - -// IsSensitive satisfies the fwschema.Attribute interface. -func (a Attribute) IsSensitive() bool { - return a.Sensitive -} diff --git a/tfsdk/attribute_plan_modification.go b/tfsdk/attribute_plan_modification.go deleted file mode 100644 index 5c462520d..000000000 --- a/tfsdk/attribute_plan_modification.go +++ /dev/null @@ -1,128 +0,0 @@ -package tfsdk - -import ( - "context" - - "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/diag" - "github.com/hashicorp/terraform-plugin-framework/internal/privatestate" - "github.com/hashicorp/terraform-plugin-framework/path" -) - -// AttributePlanModifier represents a modifier for an attribute at plan time. -// An AttributePlanModifier can only modify the planned value for the attribute -// on which it is defined. For plan-time modifications that modify the values of -// several attributes at once, please instead use the ResourceWithModifyPlan -// interface by defining a ModifyPlan function on the resource. -type AttributePlanModifier interface { - // Description is used in various tooling, like the language server, to - // give practitioners more information about what this modifier is, - // what it's for, and how it should be used. It should be written as - // plain text, with no special formatting. - Description(context.Context) string - - // MarkdownDescription is used in various tooling, like the - // documentation generator, to give practitioners more information - // about what this modifier is, what it's for, and how it should be - // used. It should be formatted using Markdown. - MarkdownDescription(context.Context) string - - // Modify is called when the provider has an opportunity to modify - // the plan: once during the plan phase when Terraform is determining - // the diff that should be shown to the user for approval, and once - // during the apply phase with any unknown values from configuration - // filled in with their final values. - // - // The Modify function has access to the config, state, and plan for - // both the attribute in question and the entire resource, but it can - // only modify the value of the one attribute. - // - // Any returned errors will stop further execution of plan modifications - // for this Attribute and any nested Attribute. Other Attribute at the same - // or higher levels of the Schema will still execute any plan modifications - // to ensure all warnings and errors across all root Attribute are - // captured. - // - // Please see the documentation for ResourceWithModifyPlan#ModifyPlan - // for further details. - Modify(context.Context, ModifyAttributePlanRequest, *ModifyAttributePlanResponse) -} - -// AttributePlanModifiers represents a sequence of AttributePlanModifiers, in -// order. -type AttributePlanModifiers []AttributePlanModifier - -// ModifyAttributePlanRequest represents a request for the provider to modify an -// attribute value, or mark it as requiring replacement, at plan time. An -// instance of this request struct is supplied as an argument to the Modify -// function of an attribute's plan modifier(s). -type ModifyAttributePlanRequest struct { - // AttributePath is the path of the attribute. Use this path for any - // response diagnostics. - AttributePath path.Path - - // AttributePathExpression is the expression matching the exact path of the - // attribute. - AttributePathExpression path.Expression - - // Config is the configuration the user supplied for the resource. - Config Config - - // State is the current state of the resource. - State State - - // Plan is the planned new state for the resource. - Plan Plan - - // AttributeConfig is the configuration the user supplied for the attribute. - AttributeConfig attr.Value - - // AttributeState is the current state of the attribute. - AttributeState attr.Value - - // AttributePlan is the planned new state for the attribute. - AttributePlan attr.Value - - // ProviderMeta is metadata from the provider_meta block of the module. - ProviderMeta Config - - // Private is provider-defined resource private state data which was previously - // stored with the resource state. This data is opaque to Terraform and does - // not affect plan output. Any existing data is copied to - // ModifyAttributePlanResponse.Private to prevent accidental private state data loss. - // - // The private state data is always the original data when the schema-based plan - // modification began or, is updated as the logic traverses deeper into underlying - // attributes. - // - // Use the GetKey method to read data. Use the SetKey method on - // ModifyAttributePlanResponse.Private to update or remove a value. - Private *privatestate.ProviderData -} - -// ModifyAttributePlanResponse represents a response to a -// ModifyAttributePlanRequest. An instance of this response struct is supplied -// as an argument to the Modify function of an attribute's plan modifier(s). -type ModifyAttributePlanResponse struct { - // AttributePlan is the planned new state for the attribute. - AttributePlan attr.Value - - // RequiresReplace indicates whether a change in the attribute - // requires replacement of the whole resource. - RequiresReplace bool - - // Private is the private state resource data following the ModifyAttributePlan operation. - // This field is pre-populated from ModifyAttributePlanRequest.Private and - // can be modified during the resource's ModifyAttributePlan operation. - // - // The private state data is always the original data when the schema-based plan - // modification began or, is updated as the logic traverses deeper into underlying - // attributes. - Private *privatestate.ProviderData - - // Diagnostics report errors or warnings related to determining the - // planned state of the requested resource. Returning an empty slice - // indicates a successful validation with no warnings or errors - // generated. - Diagnostics diag.Diagnostics -} diff --git a/tfsdk/attribute_test.go b/tfsdk/attribute_test.go deleted file mode 100644 index 87d54faa8..000000000 --- a/tfsdk/attribute_test.go +++ /dev/null @@ -1,241 +0,0 @@ -package tfsdk - -import ( - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" - "github.com/hashicorp/terraform-plugin-framework/types" -) - -func TestAttributeGetNestedMode(t *testing.T) { - t.Parallel() - - testCases := map[string]struct { - attribute Attribute - expected fwschema.NestingMode - }{ - "unset": { - attribute: Attribute{ - Type: types.StringType, - }, - expected: fwschema.NestingModeUnknown, - }, - "list": { - attribute: Attribute{ - Attributes: ListNestedAttributes(map[string]Attribute{}), - }, - expected: fwschema.NestingModeList, - }, - "map": { - attribute: Attribute{ - Attributes: MapNestedAttributes(map[string]Attribute{}), - }, - expected: fwschema.NestingModeMap, - }, - "set": { - attribute: Attribute{ - Attributes: SetNestedAttributes(map[string]Attribute{}), - }, - expected: fwschema.NestingModeSet, - }, - "single": { - attribute: Attribute{ - Attributes: SingleNestedAttributes(map[string]Attribute{}), - }, - expected: fwschema.NestingModeSingle, - }, - } - - for name, testCase := range testCases { - name, testCase := name, testCase - - t.Run(name, func(t *testing.T) { - t.Parallel() - - got := testCase.attribute.GetNestingMode() - - if diff := cmp.Diff(got, testCase.expected); diff != "" { - t.Errorf("unexpected difference: %s", diff) - } - }) - } -} - -func TestAttributeGetType(t *testing.T) { - t.Parallel() - - testCases := map[string]struct { - attribute Attribute - expected attr.Type - }{ - "Attributes-ListNestedAttributes": { - attribute: Attribute{ - Attributes: ListNestedAttributes(map[string]Attribute{ - "test_nested_attribute": { - Required: true, - Type: types.StringType, - }, - }), - Required: true, - }, - expected: types.ListType{ - ElemType: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "test_nested_attribute": types.StringType, - }, - }, - }, - }, - "Attributes-MapNestedAttributes": { - attribute: Attribute{ - Attributes: MapNestedAttributes(map[string]Attribute{ - "test_nested_attribute": { - Required: true, - Type: types.StringType, - }, - }), - Required: true, - }, - expected: types.MapType{ - ElemType: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "test_nested_attribute": types.StringType, - }, - }, - }, - }, - "Attributes-SetNestedAttributes": { - attribute: Attribute{ - Attributes: SetNestedAttributes(map[string]Attribute{ - "test_nested_attribute": { - Required: true, - Type: types.StringType, - }, - }), - Required: true, - }, - expected: types.SetType{ - ElemType: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "test_nested_attribute": types.StringType, - }, - }, - }, - }, - "Attributes-SingleNestedAttributes": { - attribute: Attribute{ - Attributes: SingleNestedAttributes(map[string]Attribute{ - "test_nested_attribute": { - Required: true, - Type: types.StringType, - }, - }), - Required: true, - }, - expected: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "test_nested_attribute": types.StringType, - }, - }, - }, - "Type-BoolType": { - attribute: Attribute{ - Required: true, - Type: types.BoolType, - }, - expected: types.BoolType, - }, - "Type-Float64Type": { - attribute: Attribute{ - Required: true, - Type: types.Float64Type, - }, - expected: types.Float64Type, - }, - "Type-Int64Type": { - attribute: Attribute{ - Required: true, - Type: types.Int64Type, - }, - expected: types.Int64Type, - }, - "Type-ListType": { - attribute: Attribute{ - Required: true, - Type: types.ListType{ - ElemType: types.StringType, - }, - }, - expected: types.ListType{ - ElemType: types.StringType, - }, - }, - "Type-MapType": { - attribute: Attribute{ - Required: true, - Type: types.MapType{ - ElemType: types.StringType, - }, - }, - expected: types.MapType{ - ElemType: types.StringType, - }, - }, - "Type-NumberType": { - attribute: Attribute{ - Required: true, - Type: types.NumberType, - }, - expected: types.NumberType, - }, - "Type-ObjectType": { - attribute: Attribute{ - Required: true, - Type: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "test_object_attribute": types.StringType, - }, - }, - }, - expected: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "test_object_attribute": types.StringType, - }, - }, - }, - "Type-SetType": { - attribute: Attribute{ - Required: true, - Type: types.SetType{ - ElemType: types.StringType, - }, - }, - expected: types.SetType{ - ElemType: types.StringType, - }, - }, - "Type-StringType": { - attribute: Attribute{ - Required: true, - Type: types.StringType, - }, - expected: types.StringType, - }, - } - - for name, testCase := range testCases { - name, testCase := name, testCase - - t.Run(name, func(t *testing.T) { - t.Parallel() - - got := testCase.attribute.GetType() - - if diff := cmp.Diff(got, testCase.expected); diff != "" { - t.Errorf("unexpected difference: %s", diff) - } - }) - } -} diff --git a/tfsdk/attribute_validation.go b/tfsdk/attribute_validation.go deleted file mode 100644 index c9a6a6167..000000000 --- a/tfsdk/attribute_validation.go +++ /dev/null @@ -1,54 +0,0 @@ -package tfsdk - -import ( - "context" - - "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/diag" - "github.com/hashicorp/terraform-plugin-framework/path" -) - -// AttributeValidator describes reusable Attribute validation functionality. -type AttributeValidator interface { - // Description describes the validation in plain text formatting. - // - // This information may be automatically added to schema plain text - // descriptions by external tooling. - Description(context.Context) string - - // MarkdownDescription describes the validation in Markdown formatting. - // - // This information may be automatically added to schema Markdown - // descriptions by external tooling. - MarkdownDescription(context.Context) string - - // Validate performs the validation. - Validate(context.Context, ValidateAttributeRequest, *ValidateAttributeResponse) -} - -// ValidateAttributeRequest repesents a request for attribute validation. -type ValidateAttributeRequest struct { - // AttributePath contains the path of the attribute. Use this path for any - // response diagnostics. - AttributePath path.Path - - // AttributePathExpression contains the expression matching the exact path - // of the attribute. - AttributePathExpression path.Expression - - // AttributeConfig contains the value of the attribute in the configuration. - AttributeConfig attr.Value - - // Config contains the entire configuration of the data source, provider, or resource. - Config Config -} - -// ValidateAttributeResponse represents a response to a -// ValidateAttributeRequest. An instance of this response struct is -// automatically passed through to each AttributeValidator. -type ValidateAttributeResponse struct { - // Diagnostics report errors or warnings related to validating the data - // source configuration. An empty slice indicates success, with no warnings - // or errors generated. - Diagnostics diag.Diagnostics -} diff --git a/tfsdk/block.go b/tfsdk/block.go deleted file mode 100644 index f169714df..000000000 --- a/tfsdk/block.go +++ /dev/null @@ -1,218 +0,0 @@ -package tfsdk - -import ( - "fmt" - - "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" - "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/hashicorp/terraform-plugin-go/tftypes" -) - -var _ tftypes.AttributePathStepper = Block{} - -// Block must satify the fwschema.Block interface. It must also satisfy -// fwxschema.BlockWithPlanModifiers and fwxschema.BlockWithValidators -// interfaces, however we cannot check that here or it would introduce an -// import cycle. -var _ fwschema.Block = Block{} - -// Block defines the constraints and behaviors of a single structural field in a -// schema. -// -// The NestingMode field must be set or a runtime error will be raised by the -// framework when fetching the schema. -// -// Deprecated: Use datasource/schema.Block, provider/schema.Block, or -// resource/schema.Block instead. This can be switched by using the -// datasource/schema.Schema, provider/schema.Schema, or resource/schema.Schema -// types. -type Block struct { - // Attributes are value fields inside the block. This map of attributes - // behaves exactly like the map of attributes on the Schema type. - Attributes map[string]Attribute - - // Blocks can have their own nested blocks. This nested map of blocks - // behaves exactly like the map of blocks on the Schema type. - Blocks map[string]Block - - // DeprecationMessage defines warning diagnostic details to display to - // practitioners configuring this Block. The warning diagnostic summary - // is automatically set to "Block Deprecated" along with configuration - // source file and line information. - // - // This warning diagnostic is only displayed during Terraform's validation - // phase when this field is a non-empty string and if the practitioner - // configuration attempts to set the block value to a known or unknown - // value (which may eventually be null). - // - // Set this field to a practitioner actionable message such as: - // - // - "Configure other_attribute instead. This block will be removed - // in the next major version of the provider." - // - "Remove this block's configuration as it no longer is used and - // the block will be removed in the next major version of the - // provider." - // - DeprecationMessage string - - // Description is used in various tooling, like the language server, to - // give practitioners more information about what this attribute is, - // what it's for, and how it should be used. It should be written as - // plain text, with no special formatting. - Description string - - // MarkdownDescription is used in various tooling, like the - // documentation generator, to give practitioners more information - // about what this attribute is, what it's for, and how it should be - // used. It should be formatted using Markdown. - MarkdownDescription string - - // MaxItems is the maximum number of blocks that can be present in a - // practitioner configuration. - MaxItems int64 - - // MinItems is the minimum number of blocks that must be present in a - // practitioner configuration. Setting to 1 or above effectively marks - // this configuration as required. - MinItems int64 - - // NestingMode indicates the block kind. This field must be set or a - // runtime error will be raised by the framework when fetching the schema. - NestingMode fwschema.BlockNestingMode - - // PlanModifiers defines a sequence of modifiers for this block at - // plan time. Block-level plan modifications occur before any - // resource-level plan modifications. - // - // Any errors will prevent further execution of this sequence - // of modifiers and modifiers associated with any nested Attribute or - // Block, but will not prevent execution of PlanModifiers on any - // other Attribute or Block in the Schema. - // - // Plan modification only applies to resources, not data sources or - // providers. Setting PlanModifiers on a data source or provider attribute - // will have no effect. - PlanModifiers AttributePlanModifiers - - // Validators defines validation functionality for the block. - Validators []AttributeValidator -} - -// ApplyTerraform5AttributePathStep allows Blocks to be walked using -// tftypes.Walk and tftypes.Transform. -func (b Block) ApplyTerraform5AttributePathStep(step tftypes.AttributePathStep) (interface{}, error) { - switch b.NestingMode { - case BlockNestingModeList: - _, ok := step.(tftypes.ElementKeyInt) - - if !ok { - return nil, fmt.Errorf("can't apply %T to block NestingModeList", step) - } - - return b.GetNestedObject(), nil - case BlockNestingModeSet: - _, ok := step.(tftypes.ElementKeyValue) - - if !ok { - return nil, fmt.Errorf("can't apply %T to block NestingModeSet", step) - } - - return b.GetNestedObject(), nil - case BlockNestingModeSingle: - _, ok := step.(tftypes.AttributeName) - - if !ok { - return nil, fmt.Errorf("can't apply %T to block NestingModeSingle", step) - } - - return b.GetNestedObject().ApplyTerraform5AttributePathStep(step) - default: - return nil, fmt.Errorf("unsupported block nesting mode: %v", b.NestingMode) - } -} - -// Equal returns true if `b` and `o` should be considered Equal. -func (b Block) Equal(o fwschema.Block) bool { - return fwschema.BlocksEqual(b, o) -} - -// GetDeprecationMessage satisfies the fwschema.Block interface. -func (b Block) GetDeprecationMessage() string { - return b.DeprecationMessage -} - -// GetDescription satisfies the fwschema.Block interface. -func (b Block) GetDescription() string { - return b.Description -} - -// GetMarkdownDescription satisfies the fwschema.Block interface. -func (b Block) GetMarkdownDescription() string { - return b.MarkdownDescription -} - -// GetMaxItems satisfies the fwschema.Block interface. -func (b Block) GetMaxItems() int64 { - return b.MaxItems -} - -// GetMinItems satisfies the fwschema.Block interface. -func (b Block) GetMinItems() int64 { - return b.MinItems -} - -// GetNestedObject returns a generated NestedBlockObject from the -// Attributes and Blocks field values. -func (b Block) GetNestedObject() fwschema.NestedBlockObject { - return nestedBlockObject{ - Attributes: b.Attributes, - Blocks: b.Blocks, - } -} - -// GetNestingMode satisfies the fwschema.Block interface. -func (b Block) GetNestingMode() fwschema.BlockNestingMode { - return b.NestingMode -} - -// GetPlanModifiers satisfies the fwxschema.BlockWithPlanModifiers -// interface. -func (b Block) GetPlanModifiers() AttributePlanModifiers { - return b.PlanModifiers -} - -// GetValidators satisfies the fwxschema.BlockWithValidators interface. -func (b Block) GetValidators() []AttributeValidator { - return b.Validators -} - -// attributeType returns an attr.Type corresponding to the block. -func (b Block) Type() attr.Type { - attrType := types.ObjectType{ - AttrTypes: map[string]attr.Type{}, - } - - for attrName, attr := range b.Attributes { - attrType.AttrTypes[attrName] = attr.GetType() - } - - for blockName, block := range b.Blocks { - attrType.AttrTypes[blockName] = block.Type() - } - - switch b.NestingMode { - case BlockNestingModeList: - return types.ListType{ - ElemType: attrType, - } - case BlockNestingModeSet: - return types.SetType{ - ElemType: attrType, - } - case BlockNestingModeSingle: - return attrType - default: - panic(fmt.Sprintf("unsupported block nesting mode: %v", b.NestingMode)) - } -} diff --git a/tfsdk/block_nested_mode.go b/tfsdk/block_nested_mode.go deleted file mode 100644 index ddbd681c2..000000000 --- a/tfsdk/block_nested_mode.go +++ /dev/null @@ -1,11 +0,0 @@ -package tfsdk - -import ( - "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" -) - -const ( - BlockNestingModeList = fwschema.BlockNestingModeList - BlockNestingModeSet = fwschema.BlockNestingModeSet - BlockNestingModeSingle = fwschema.BlockNestingModeSingle -) diff --git a/tfsdk/block_test.go b/tfsdk/block_test.go deleted file mode 100644 index 4da4814ce..000000000 --- a/tfsdk/block_test.go +++ /dev/null @@ -1,137 +0,0 @@ -package tfsdk - -import ( - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/types" -) - -func TestBlockType(t *testing.T) { - t.Parallel() - - testCases := map[string]struct { - block Block - expected attr.Type - }{ - "NestingMode-List": { - block: Block{ - Attributes: map[string]Attribute{ - "test_attribute": { - Required: true, - Type: types.StringType, - }, - }, - Blocks: map[string]Block{ - "test_block": { - Attributes: map[string]Attribute{ - "test_block_attribute": { - Required: true, - Type: types.StringType, - }, - }, - NestingMode: BlockNestingModeList, - }, - }, - NestingMode: BlockNestingModeList, - }, - expected: types.ListType{ - ElemType: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "test_attribute": types.StringType, - "test_block": types.ListType{ - ElemType: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "test_block_attribute": types.StringType, - }, - }, - }, - }, - }, - }, - }, - "NestingMode-Set": { - block: Block{ - Attributes: map[string]Attribute{ - "test_attribute": { - Required: true, - Type: types.StringType, - }, - }, - Blocks: map[string]Block{ - "test_block": { - Attributes: map[string]Attribute{ - "test_block_attribute": { - Required: true, - Type: types.StringType, - }, - }, - NestingMode: BlockNestingModeSet, - }, - }, - NestingMode: BlockNestingModeSet, - }, - expected: types.SetType{ - ElemType: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "test_attribute": types.StringType, - "test_block": types.SetType{ - ElemType: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "test_block_attribute": types.StringType, - }, - }, - }, - }, - }, - }, - }, - "NestingMode-Single": { - block: Block{ - Attributes: map[string]Attribute{ - "test_attribute": { - Required: true, - Type: types.StringType, - }, - }, - Blocks: map[string]Block{ - "test_block": { - Attributes: map[string]Attribute{ - "test_block_attribute": { - Required: true, - Type: types.StringType, - }, - }, - NestingMode: BlockNestingModeSingle, - }, - }, - NestingMode: BlockNestingModeSingle, - }, - expected: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "test_attribute": types.StringType, - "test_block": types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "test_block_attribute": types.StringType, - }, - }, - }, - }, - }, - } - - for name, testCase := range testCases { - name, testCase := name, testCase - - t.Run(name, func(t *testing.T) { - t.Parallel() - - got := testCase.block.Type() - - if diff := cmp.Diff(got, testCase.expected); diff != "" { - t.Errorf("unexpected difference: %s", diff) - } - }) - } -} diff --git a/tfsdk/config_test.go b/tfsdk/config_test.go index 402e009a7..82e0c4a65 100644 --- a/tfsdk/config_test.go +++ b/tfsdk/config_test.go @@ -1,4 +1,4 @@ -package tfsdk +package tfsdk_test import ( "context" @@ -7,9 +7,12 @@ import ( "github.com/google/go-cmp/cmp" "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" intreflect "github.com/hashicorp/terraform-plugin-framework/internal/reflect" + "github.com/hashicorp/terraform-plugin-framework/internal/testing/testschema" testtypes "github.com/hashicorp/terraform-plugin-framework/internal/testing/types" "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/tfsdk" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-go/tftypes" ) @@ -18,7 +21,7 @@ func TestConfigGet(t *testing.T) { t.Parallel() testCases := map[string]struct { - config Config + config tfsdk.Config target any expected any expectedDiags diag.Diagnostics @@ -27,7 +30,7 @@ func TestConfigGet(t *testing.T) { // These test cases are to ensure Plan schema and data values are // passed appropriately to the shared implementation. "valid": { - config: Config{ + config: tfsdk.Config{ Raw: tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ @@ -38,9 +41,9 @@ func TestConfigGet(t *testing.T) { "string": tftypes.NewValue(tftypes.String, "test"), }, ), - Schema: Schema{ - Attributes: map[string]Attribute{ - "string": { + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "string": testschema.Attribute{ Optional: true, Type: types.StringType, }, @@ -57,7 +60,7 @@ func TestConfigGet(t *testing.T) { }, }, "diagnostic": { - config: Config{ + config: tfsdk.Config{ Raw: tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ @@ -68,9 +71,9 @@ func TestConfigGet(t *testing.T) { "bool": tftypes.NewValue(tftypes.Bool, nil), }, ), - Schema: Schema{ - Attributes: map[string]Attribute{ - "bool": { + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "bool": testschema.Attribute{ Optional: true, Type: types.BoolType, }, @@ -121,7 +124,7 @@ func TestConfigGetAttribute(t *testing.T) { t.Parallel() type testCase struct { - config Config + config tfsdk.Config target interface{} expected interface{} expectedDiags diag.Diagnostics @@ -132,7 +135,7 @@ func TestConfigGetAttribute(t *testing.T) { // testing. These test cases are to ensure Plan schema and data values // are passed appropriately to the shared implementation. "valid": { - config: Config{ + config: tfsdk.Config{ Raw: tftypes.NewValue(tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ "name": tftypes.String, @@ -140,9 +143,9 @@ func TestConfigGetAttribute(t *testing.T) { }, map[string]tftypes.Value{ "name": tftypes.NewValue(tftypes.String, "namevalue"), }), - Schema: Schema{ - Attributes: map[string]Attribute{ - "name": { + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "name": testschema.Attribute{ Type: types.StringType, Required: true, }, @@ -150,10 +153,10 @@ func TestConfigGetAttribute(t *testing.T) { }, }, target: new(string), - expected: newStringPointer("namevalue"), + expected: pointer("namevalue"), }, "diagnostics": { - config: Config{ + config: tfsdk.Config{ Raw: tftypes.NewValue(tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ "name": tftypes.String, @@ -161,9 +164,9 @@ func TestConfigGetAttribute(t *testing.T) { }, map[string]tftypes.Value{ "name": tftypes.NewValue(tftypes.String, "namevalue"), }), - Schema: Schema{ - Attributes: map[string]Attribute{ - "name": { + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "name": testschema.Attribute{ Type: testtypes.StringTypeWithValidateWarning{}, Required: true, }, @@ -198,7 +201,7 @@ func TestConfigPathMatches(t *testing.T) { t.Parallel() testCases := map[string]struct { - config Config + config tfsdk.Config expression path.Expression expected path.Paths expectedDiags diag.Diagnostics @@ -207,10 +210,10 @@ func TestConfigPathMatches(t *testing.T) { // These test cases are to ensure Config schema and data values are // passed appropriately to the shared implementation. "AttributeNameExact-match": { - config: Config{ - Schema: Schema{ - Attributes: map[string]Attribute{ - "test": { + config: tfsdk.Config{ + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "test": testschema.Attribute{ Type: types.StringType, }, }, @@ -232,10 +235,10 @@ func TestConfigPathMatches(t *testing.T) { }, }, "AttributeNameExact-mismatch": { - config: Config{ - Schema: Schema{ - Attributes: map[string]Attribute{ - "test": { + config: tfsdk.Config{ + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "test": testschema.Attribute{ Type: types.StringType, }, }, diff --git a/tfsdk/nested_attribute_object.go b/tfsdk/nested_attribute_object.go deleted file mode 100644 index 60dadfea5..000000000 --- a/tfsdk/nested_attribute_object.go +++ /dev/null @@ -1,44 +0,0 @@ -package tfsdk - -import ( - "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" - "github.com/hashicorp/terraform-plugin-framework/types/basetypes" - "github.com/hashicorp/terraform-plugin-go/tftypes" -) - -// Ensure the implementation satisifies the desired interfaces. -var _ fwschema.NestedAttributeObject = nestedAttributeObject{} - -// nestedAttributeObject is the object containing the underlying attributes -// for an Attribute with nested attributes. This is a temporary type until -// Attribute is removed. -type nestedAttributeObject struct { - // Attributes is the mapping of underlying attribute names to attribute - // definitions. This field must be set. - Attributes map[string]fwschema.Attribute -} - -// ApplyTerraform5AttributePathStep performs an AttributeName step on the -// underlying attributes or returns an error. -func (o nestedAttributeObject) ApplyTerraform5AttributePathStep(step tftypes.AttributePathStep) (any, error) { - return fwschema.NestedAttributeObjectApplyTerraform5AttributePathStep(o, step) -} - -// Equal returns true if the given nestedAttributeObject is equivalent. -func (o nestedAttributeObject) Equal(other fwschema.NestedAttributeObject) bool { - if _, ok := other.(nestedAttributeObject); !ok { - return false - } - - return fwschema.NestedAttributeObjectEqual(o, other) -} - -// GetAttributes returns the Attributes field value. -func (o nestedAttributeObject) GetAttributes() fwschema.UnderlyingAttributes { - return o.Attributes -} - -// Type returns the framework type of the nestedAttributeObject. -func (o nestedAttributeObject) Type() basetypes.ObjectTypable { - return fwschema.NestedAttributeObjectType(o) -} diff --git a/tfsdk/nested_attributes.go b/tfsdk/nested_attributes.go deleted file mode 100644 index 4a79ca353..000000000 --- a/tfsdk/nested_attributes.go +++ /dev/null @@ -1,62 +0,0 @@ -package tfsdk - -import ( - "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" -) - -// ListNestedAttributes nests `attributes` under another attribute, allowing -// multiple instances of that group of attributes to appear in the -// configuration. -// -// Deprecated: Use datasource/schema.ListNestedAttribute, -// provider/schema.ListNestedAttribute, or resource/schema.ListNestedAttribute -// instead. This can be switched by using the datasource/schema.Schema, -// provider/schema.Schema, or resource/schema.Schema types. -func ListNestedAttributes(attributes map[string]Attribute) fwschema.NestedAttributes { - return fwschema.ListNestedAttributes{ - UnderlyingAttributes: schemaAttributes(attributes), - } -} - -// MapNestedAttributes nests `attributes` under another attribute, allowing -// multiple instances of that group of attributes to appear in the -// configuration. Each group will need to be associated with a unique string by -// the user. -// -// Deprecated: Use datasource/schema.MapNestedAttribute, -// provider/schema.MapNestedAttribute, or resource/schema.MapNestedAttribute -// instead. This can be switched by using the datasource/schema.Schema, -// provider/schema.Schema, or resource/schema.Schema types. -func MapNestedAttributes(attributes map[string]Attribute) fwschema.NestedAttributes { - return fwschema.MapNestedAttributes{ - UnderlyingAttributes: schemaAttributes(attributes), - } -} - -// SetNestedAttributes nests `attributes` under another attribute, allowing -// multiple instances of that group of attributes to appear in the -// configuration, while requiring each group of values be unique. -// -// Deprecated: Use datasource/schema.SetNestedAttribute, -// provider/schema.SetNestedAttribute, or resource/schema.SetNestedAttribute -// instead. This can be switched by using the datasource/schema.Schema, -// provider/schema.Schema, or resource/schema.Schema types. -func SetNestedAttributes(attributes map[string]Attribute) fwschema.NestedAttributes { - return fwschema.SetNestedAttributes{ - UnderlyingAttributes: schemaAttributes(attributes), - } -} - -// SingleNestedAttributes nests `attributes` under another attribute, only -// allowing one instance of that group of attributes to appear in the -// configuration. -// -// Deprecated: Use datasource/schema.SingleNestedAttribute, -// provider/schema.SingleNestedAttribute, or resource/schema.SingleNestedAttribute -// instead. This can be switched by using the datasource/schema.Schema, -// provider/schema.Schema, or resource/schema.Schema types. -func SingleNestedAttributes(attributes map[string]Attribute) fwschema.NestedAttributes { - return fwschema.SingleNestedAttributes{ - UnderlyingAttributes: schemaAttributes(attributes), - } -} diff --git a/tfsdk/nested_block_object.go b/tfsdk/nested_block_object.go deleted file mode 100644 index b7e6e763f..000000000 --- a/tfsdk/nested_block_object.go +++ /dev/null @@ -1,60 +0,0 @@ -package tfsdk - -import ( - "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" - "github.com/hashicorp/terraform-plugin-framework/types/basetypes" - "github.com/hashicorp/terraform-plugin-go/tftypes" -) - -var _ fwschema.NestedBlockObject = nestedBlockObject{} - -// nestedBlockObject is the object containing the underlying attributes and -// blocks for Block. It is a temporary type until Block is removed. -// -// This object enables customizing and simplifying details within its parent -// Block, therefore it cannot have Terraform schema fields such as Description, -// etc. -type nestedBlockObject struct { - // Attributes is the mapping of underlying attribute names to attribute - // definitions. - // - // Names must only contain lowercase letters, numbers, and underscores. - // Names must not collide with any Blocks names. - Attributes map[string]Attribute - - // Blocks is the mapping of underlying block names to block definitions. - // - // Names must only contain lowercase letters, numbers, and underscores. - // Names must not collide with any Attributes names. - Blocks map[string]Block -} - -// ApplyTerraform5AttributePathStep performs an AttributeName step on the -// underlying attributes or returns an error. -func (o nestedBlockObject) ApplyTerraform5AttributePathStep(step tftypes.AttributePathStep) (any, error) { - return fwschema.NestedBlockObjectApplyTerraform5AttributePathStep(o, step) -} - -// Equal returns true if the given nestedBlockObject is equivalent. -func (o nestedBlockObject) Equal(other fwschema.NestedBlockObject) bool { - if _, ok := other.(nestedBlockObject); !ok { - return false - } - - return fwschema.NestedBlockObjectEqual(o, other) -} - -// GetAttributes returns the Attributes field value. -func (o nestedBlockObject) GetAttributes() fwschema.UnderlyingAttributes { - return schemaAttributes(o.Attributes) -} - -// GetAttributes returns the Blocks field value. -func (o nestedBlockObject) GetBlocks() map[string]fwschema.Block { - return schemaBlocks(o.Blocks) -} - -// Type returns the framework type of the nestedBlockObject. -func (o nestedBlockObject) Type() basetypes.ObjectTypable { - return fwschema.NestedBlockObjectType(o) -} diff --git a/tfsdk/plan_test.go b/tfsdk/plan_test.go index dadec120d..dd05af45a 100644 --- a/tfsdk/plan_test.go +++ b/tfsdk/plan_test.go @@ -1,4 +1,4 @@ -package tfsdk +package tfsdk_test import ( "context" @@ -7,9 +7,12 @@ import ( "github.com/google/go-cmp/cmp" "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" intreflect "github.com/hashicorp/terraform-plugin-framework/internal/reflect" + "github.com/hashicorp/terraform-plugin-framework/internal/testing/testschema" testtypes "github.com/hashicorp/terraform-plugin-framework/internal/testing/types" "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/tfsdk" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-go/tftypes" ) @@ -18,7 +21,7 @@ func TestPlanGet(t *testing.T) { t.Parallel() testCases := map[string]struct { - plan Plan + plan tfsdk.Plan target any expected any expectedDiags diag.Diagnostics @@ -27,7 +30,7 @@ func TestPlanGet(t *testing.T) { // These test cases are to ensure Plan schema and data values are // passed appropriately to the shared implementation. "valid": { - plan: Plan{ + plan: tfsdk.Plan{ Raw: tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ @@ -38,9 +41,9 @@ func TestPlanGet(t *testing.T) { "string": tftypes.NewValue(tftypes.String, "test"), }, ), - Schema: Schema{ - Attributes: map[string]Attribute{ - "string": { + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "string": testschema.Attribute{ Optional: true, Type: types.StringType, }, @@ -57,7 +60,7 @@ func TestPlanGet(t *testing.T) { }, }, "diagnostic": { - plan: Plan{ + plan: tfsdk.Plan{ Raw: tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ @@ -68,9 +71,9 @@ func TestPlanGet(t *testing.T) { "bool": tftypes.NewValue(tftypes.Bool, nil), }, ), - Schema: Schema{ - Attributes: map[string]Attribute{ - "bool": { + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "bool": testschema.Attribute{ Optional: true, Type: types.BoolType, }, @@ -121,7 +124,7 @@ func TestPlanGetAttribute(t *testing.T) { t.Parallel() type testCase struct { - plan Plan + plan tfsdk.Plan target interface{} expected interface{} expectedDiags diag.Diagnostics @@ -132,7 +135,7 @@ func TestPlanGetAttribute(t *testing.T) { // testing. These test cases are to ensure Plan schema and data values // are passed appropriately to the shared implementation. "valid": { - plan: Plan{ + plan: tfsdk.Plan{ Raw: tftypes.NewValue(tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ "name": tftypes.String, @@ -140,9 +143,9 @@ func TestPlanGetAttribute(t *testing.T) { }, map[string]tftypes.Value{ "name": tftypes.NewValue(tftypes.String, "namevalue"), }), - Schema: Schema{ - Attributes: map[string]Attribute{ - "name": { + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "name": testschema.Attribute{ Type: types.StringType, Required: true, }, @@ -150,10 +153,10 @@ func TestPlanGetAttribute(t *testing.T) { }, }, target: new(string), - expected: newStringPointer("namevalue"), + expected: pointer("namevalue"), }, "diagnostics": { - plan: Plan{ + plan: tfsdk.Plan{ Raw: tftypes.NewValue(tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ "name": tftypes.String, @@ -161,9 +164,9 @@ func TestPlanGetAttribute(t *testing.T) { }, map[string]tftypes.Value{ "name": tftypes.NewValue(tftypes.String, "namevalue"), }), - Schema: Schema{ - Attributes: map[string]Attribute{ - "name": { + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "name": testschema.Attribute{ Type: testtypes.StringTypeWithValidateWarning{}, Required: true, }, @@ -198,7 +201,7 @@ func TestPlanPathMatches(t *testing.T) { t.Parallel() testCases := map[string]struct { - plan Plan + plan tfsdk.Plan expression path.Expression expected path.Paths expectedDiags diag.Diagnostics @@ -207,10 +210,10 @@ func TestPlanPathMatches(t *testing.T) { // These test cases are to ensure Plan schema and data values are // passed appropriately to the shared implementation. "AttributeNameExact-match": { - plan: Plan{ - Schema: Schema{ - Attributes: map[string]Attribute{ - "test": { + plan: tfsdk.Plan{ + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "test": testschema.Attribute{ Type: types.StringType, }, }, @@ -232,10 +235,10 @@ func TestPlanPathMatches(t *testing.T) { }, }, "AttributeNameExact-mismatch": { - plan: Plan{ - Schema: Schema{ - Attributes: map[string]Attribute{ - "test": { + plan: tfsdk.Plan{ + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "test": testschema.Attribute{ Type: types.StringType, }, }, @@ -288,7 +291,7 @@ func TestPlanSet(t *testing.T) { t.Parallel() type testCase struct { - plan Plan + plan tfsdk.Plan val interface{} expected tftypes.Value expectedDiags diag.Diagnostics @@ -299,7 +302,7 @@ func TestPlanSet(t *testing.T) { // These test cases are to ensure Plan schema and data values are // passed appropriately to the shared implementation. "valid": { - plan: Plan{ + plan: tfsdk.Plan{ Raw: tftypes.NewValue(tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ "name": tftypes.String, @@ -307,9 +310,9 @@ func TestPlanSet(t *testing.T) { }, map[string]tftypes.Value{ "name": tftypes.NewValue(tftypes.String, "oldvalue"), }), - Schema: Schema{ - Attributes: map[string]Attribute{ - "name": { + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "name": testschema.Attribute{ Type: types.StringType, Required: true, }, @@ -330,11 +333,11 @@ func TestPlanSet(t *testing.T) { }), }, "diagnostics": { - plan: Plan{ + plan: tfsdk.Plan{ Raw: tftypes.Value{}, - Schema: Schema{ - Attributes: map[string]Attribute{ - "name": { + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "name": testschema.Attribute{ Type: testtypes.StringTypeWithValidateWarning{}, Required: true, }, @@ -379,7 +382,7 @@ func TestPlanSetAttribute(t *testing.T) { t.Parallel() type testCase struct { - plan Plan + plan tfsdk.Plan path path.Path val interface{} expected tftypes.Value @@ -391,7 +394,7 @@ func TestPlanSetAttribute(t *testing.T) { // testing. These test cases are to ensure Plan schema and data values // are passed appropriately to the shared implementation. "valid": { - plan: Plan{ + plan: tfsdk.Plan{ Raw: tftypes.NewValue(tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ "test": tftypes.String, @@ -401,13 +404,13 @@ func TestPlanSetAttribute(t *testing.T) { "test": tftypes.NewValue(tftypes.String, "originalvalue"), "other": tftypes.NewValue(tftypes.String, "should be untouched"), }), - Schema: Schema{ - Attributes: map[string]Attribute{ - "test": { + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "test": testschema.Attribute{ Type: types.StringType, Required: true, }, - "other": { + "other": testschema.Attribute{ Type: types.StringType, Required: true, }, @@ -427,7 +430,7 @@ func TestPlanSetAttribute(t *testing.T) { }), }, "diagnostics": { - plan: Plan{ + plan: tfsdk.Plan{ Raw: tftypes.NewValue(tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ "name": tftypes.String, @@ -435,9 +438,9 @@ func TestPlanSetAttribute(t *testing.T) { }, map[string]tftypes.Value{ "name": tftypes.NewValue(tftypes.String, "originalname"), }), - Schema: Schema{ - Attributes: map[string]Attribute{ - "name": { + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "name": testschema.Attribute{ Type: testtypes.StringTypeWithValidateWarning{}, Required: true, }, diff --git a/tfsdk/pointer_test.go b/tfsdk/pointer_test.go new file mode 100644 index 000000000..275ed4cc7 --- /dev/null +++ b/tfsdk/pointer_test.go @@ -0,0 +1,5 @@ +package tfsdk_test + +func pointer[T any](value T) *T { + return &value +} diff --git a/tfsdk/schema.go b/tfsdk/schema.go deleted file mode 100644 index d11221da8..000000000 --- a/tfsdk/schema.go +++ /dev/null @@ -1,176 +0,0 @@ -package tfsdk - -import ( - "context" - - "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/diag" - "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" - "github.com/hashicorp/terraform-plugin-framework/path" - "github.com/hashicorp/terraform-plugin-go/tftypes" -) - -var ( - // ErrPathInsideAtomicAttribute is used with AttributeAtPath is called - // on a path that doesn't have a schema associated with it, because - // it's an element, attribute, or block of a complex type, not a nested - // attribute. - // - // Deprecated: This error value was intended for internal usage and will - // be removed in a future version. If you have a use case for this, - // please create a GitHub issue. - ErrPathInsideAtomicAttribute = fwschema.ErrPathInsideAtomicAttribute - - // ErrPathIsBlock is used with AttributeAtPath is called on a path is a - // block, not an attribute. Use blockAtPath on the path instead. - // - // Deprecated: This error value was intended for internal usage and will - // be removed in a future version. If you have a use case for this, - // please create a GitHub issue. - ErrPathIsBlock = fwschema.ErrPathIsBlock -) - -// Schema must satify the fwschema.Schema interface. -var _ fwschema.Schema = Schema{} - -// Schema is used to define the shape of practitioner-provider information, -// like resources, data sources, and providers. Think of it as a type -// definition, but for Terraform. -// -// Deprecated: Use datasource/schema.Schema, provider/schema.Schema, or -// resource/schema.Schema instead. This can be switched by using the -// datasource.DataSource, provider.Provider, or resource.Resource interface -// Schema method. -type Schema struct { - // Attributes are value fields inside the resource, provider, or data - // source that the schema is defining. The map key should be the name - // of the attribute, and the body defines how it behaves. Names must - // only contain lowercase letters, numbers, and underscores. Names must - // not collide with any Blocks names. - // - // In practitioner configurations, an equals sign (=) is required to set - // the value. See also: - // https://www.terraform.io/docs/language/syntax/configuration.html - // - // Attributes are strongly preferred over Blocks. - Attributes map[string]Attribute - - // Blocks are structural fields inside the resource, provider, or data - // source that the schema is defining. The map key should be the name - // of the block, and the body defines how it behaves. Names must - // only contain lowercase letters, numbers, and underscores. Names must - // not collide with any Attributes names. - // - // Blocks are by definition, structural, meaning they are implicitly - // required in values. - // - // In practitioner configurations, an equals sign (=) cannot be used to - // set the value. Blocks are instead repeated as necessary, or require - // the use of dynamic block expressions. See also: - // https://www.terraform.io/docs/language/syntax/configuration.html - // https://www.terraform.io/docs/language/expressions/dynamic-blocks.html - // - // Attributes are preferred over Blocks. Blocks should typically be used - // for configuration compatibility with previously existing schemas from - // an older Terraform Plugin SDK. Efforts should be made to convert from - // Blocks to Attributes as a breaking change for practitioners. - Blocks map[string]Block - - // Version indicates the current version of the schema. Schemas are - // versioned to help with automatic upgrade process. This is not - // typically required unless there is a change in the schema, such as - // changing an attribute type, that needs manual upgrade handling. - // Versions should only be incremented by one each release. - Version int64 - - DeprecationMessage string - Description string - MarkdownDescription string -} - -// ApplyTerraform5AttributePathStep applies the given AttributePathStep to the -// schema. -func (s Schema) ApplyTerraform5AttributePathStep(step tftypes.AttributePathStep) (interface{}, error) { - return fwschema.SchemaApplyTerraform5AttributePathStep(s, step) -} - -// TypeAtPath returns the framework type at the given schema path. -func (s Schema) TypeAtPath(ctx context.Context, p path.Path) (attr.Type, diag.Diagnostics) { - return fwschema.SchemaTypeAtPath(ctx, s, p) -} - -// TypeAtTerraformPath returns the framework type at the given tftypes path. -func (s Schema) TypeAtTerraformPath(ctx context.Context, p *tftypes.AttributePath) (attr.Type, error) { - return fwschema.SchemaTypeAtTerraformPath(ctx, s, p) -} - -// GetAttributes satisfies the fwschema.Schema interface. -func (s Schema) GetAttributes() map[string]fwschema.Attribute { - return schemaAttributes(s.Attributes) -} - -// GetBlocks satisfies the fwschema.Schema interface. -func (s Schema) GetBlocks() map[string]fwschema.Block { - return schemaBlocks(s.Blocks) -} - -// GetDeprecationMessage satisfies the fwschema.Schema interface. -func (s Schema) GetDeprecationMessage() string { - return s.DeprecationMessage -} - -// GetDescription satisfies the fwschema.Schema interface. -func (s Schema) GetDescription() string { - return s.Description -} - -// GetMarkdownDescription satisfies the fwschema.Schema interface. -func (s Schema) GetMarkdownDescription() string { - return s.MarkdownDescription -} - -// GetVersion satisfies the fwschema.Schema interface. -func (s Schema) GetVersion() int64 { - return s.Version -} - -// Type returns the framework type of the schema. -func (s Schema) Type() attr.Type { - return fwschema.SchemaType(s) -} - -// AttributeAtPath returns the Attribute at the passed path. If the path points -// to an element or attribute of a complex type, rather than to an Attribute, -// it will return an ErrPathInsideAtomicAttribute error. -func (s Schema) AttributeAtPath(ctx context.Context, p path.Path) (fwschema.Attribute, diag.Diagnostics) { - return fwschema.SchemaAttributeAtPath(ctx, s, p) -} - -// AttributeAtPath returns the Attribute at the passed path. If the path points -// to an element or attribute of a complex type, rather than to an Attribute, -// it will return an ErrPathInsideAtomicAttribute error. -func (s Schema) AttributeAtTerraformPath(ctx context.Context, p *tftypes.AttributePath) (fwschema.Attribute, error) { - return fwschema.SchemaAttributeAtTerraformPath(ctx, s, p) -} - -// schemaAttributes is a tfsdk to fwschema type conversion function. -func schemaAttributes(attributes map[string]Attribute) map[string]fwschema.Attribute { - result := make(map[string]fwschema.Attribute, len(attributes)) - - for name, attribute := range attributes { - result[name] = attribute - } - - return result -} - -// schemaBlocks is a tfsdk to fwschema type conversion function. -func schemaBlocks(blocks map[string]Block) map[string]fwschema.Block { - result := make(map[string]fwschema.Block, len(blocks)) - - for name, block := range blocks { - result[name] = block - } - - return result -} diff --git a/tfsdk/schema_test.go b/tfsdk/schema_test.go deleted file mode 100644 index 09f5fc784..000000000 --- a/tfsdk/schema_test.go +++ /dev/null @@ -1,3416 +0,0 @@ -package tfsdk - -import ( - "context" - "fmt" - "strings" - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/hashicorp/terraform-plugin-framework/attr" - "github.com/hashicorp/terraform-plugin-framework/diag" - "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" - "github.com/hashicorp/terraform-plugin-framework/path" - "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/hashicorp/terraform-plugin-go/tftypes" -) - -func TestSchemaAttributeAtPath(t *testing.T) { - t.Parallel() - - testCases := map[string]struct { - schema Schema - path path.Path - expected fwschema.Attribute - expectedDiags diag.Diagnostics - }{ - "empty-root": { - schema: Schema{}, - path: path.Empty(), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Empty(), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: \n"+ - "Original Error: got unexpected type tfsdk.Schema", - ), - }, - }, - "root": { - schema: Schema{ - Attributes: map[string]Attribute{ - "test": { - Type: types.StringType, - Required: true, - }, - }, - }, - path: path.Empty(), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Empty(), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: \n"+ - "Original Error: got unexpected type tfsdk.Schema", - ), - }, - }, - "WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Type: types.StringType, - Required: true, - }, - }, - }, - path: path.Root("test"), - expected: Attribute{ - Type: types.StringType, - Required: true, - }, - }, - "WithAttributeName-ListNestedAttributes-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: ListNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: path.Root("test").AtName("sub_test"), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtName("sub_test"), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test.sub_test\n"+ - "Original Error: AttributeName(\"sub_test\") still remains in the path: can't apply tftypes.AttributeName to ListNestedAttributes", - ), - }, - }, - "WithAttributeName-ListNestedAttributes-WithElementKeyInt": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: ListNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: path.Root("test").AtListIndex(0), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtListIndex(0), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[0]\n"+ - "Original Error: "+ErrPathInsideAtomicAttribute.Error(), - ), - }, - }, - "WithAttributeName-ListNestedAttributes-WithElementKeyInt-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: ListNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: path.Root("test").AtListIndex(0).AtName("sub_test"), - expected: Attribute{ - Type: types.StringType, - Required: true, - }, - }, - "WithAttributeName-ListNestedAttributes-WithElementKeyString": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: ListNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: path.Root("test").AtMapKey("sub_test"), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtMapKey("sub_test"), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[\"sub_test\"]\n"+ - "Original Error: ElementKeyString(\"sub_test\") still remains in the path: can't apply tftypes.ElementKeyString to ListNestedAttributes", - ), - }, - }, - "WithAttributeName-ListNestedAttributes-WithElementKeyValue": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: ListNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: path.Root("test").AtSetValue(types.StringValue("sub_test")), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtSetValue(types.StringValue("sub_test")), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[Value(\"sub_test\")]\n"+ - "Original Error: ElementKeyValue(tftypes.String<\"sub_test\">) still remains in the path: can't apply tftypes.ElementKeyValue to ListNestedAttributes", - ), - }, - }, - "WithAttributeName-ListNestedBlocks-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Optional: true, - }, - }, - NestingMode: BlockNestingModeList, - }, - "test": { - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeList, - }, - }, - }, - path: path.Root("test").AtName("sub_test"), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtName("sub_test"), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test.sub_test\n"+ - "Original Error: AttributeName(\"sub_test\") still remains in the path: can't apply tftypes.AttributeName to block NestingModeList", - ), - }, - }, - "WithAttributeName-ListNestedBlocks-WithElementKeyInt": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Optional: true, - }, - }, - NestingMode: BlockNestingModeList, - }, - "test": { - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeList, - }, - }, - }, - path: path.Root("test").AtListIndex(0), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtListIndex(0), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[0]\n"+ - "Original Error: "+ErrPathInsideAtomicAttribute.Error(), - ), - }, - }, - "WithAttributeName-ListNestedBlocks-WithElementKeyInt-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Optional: true, - }, - }, - NestingMode: BlockNestingModeList, - }, - "test": { - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeList, - }, - }, - }, - path: path.Root("test").AtListIndex(0).AtName("sub_test"), - expected: Attribute{ - Type: types.StringType, - Required: true, - }, - }, - "WithAttributeName-ListNestedBlocks-WithElementKeyString": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Optional: true, - }, - }, - NestingMode: BlockNestingModeList, - }, - "test": { - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeList, - }, - }, - }, - path: path.Root("test").AtMapKey("sub_test"), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtMapKey("sub_test"), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[\"sub_test\"]\n"+ - "Original Error: ElementKeyString(\"sub_test\") still remains in the path: can't apply tftypes.ElementKeyString to block NestingModeList", - ), - }, - }, - "WithAttributeName-ListNestedBlocks-WithElementKeyValue": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Optional: true, - }, - }, - NestingMode: BlockNestingModeList, - }, - "test": { - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeList, - }, - }, - }, - path: path.Root("test").AtSetValue(types.StringValue("sub_test")), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtSetValue(types.StringValue("sub_test")), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[Value(\"sub_test\")]\n"+ - "Original Error: ElementKeyValue(tftypes.String<\"sub_test\">) still remains in the path: can't apply tftypes.ElementKeyValue to block NestingModeList", - ), - }, - }, - "WithAttributeName-MapNestedAttributes-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: MapNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: path.Root("test").AtName("sub_test"), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtName("sub_test"), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test.sub_test\n"+ - "Original Error: AttributeName(\"sub_test\") still remains in the path: can't use tftypes.AttributeName on maps", - ), - }, - }, - "WithAttributeName-MapNestedAttributes-WithElementKeyInt": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: MapNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: path.Root("test").AtListIndex(0), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtListIndex(0), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[0]\n"+ - "Original Error: ElementKeyInt(0) still remains in the path: can't use tftypes.ElementKeyInt on maps", - ), - }, - }, - "WithAttributeName-MapNestedAttributes-WithElementKeyString": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: MapNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: path.Root("test").AtMapKey("sub_test"), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtMapKey("sub_test"), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[\"sub_test\"]\n"+ - "Original Error: "+ErrPathInsideAtomicAttribute.Error(), - ), - }, - }, - "WithAttributeName-MapNestedAttributes-WithElementKeyString-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: MapNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: path.Root("test").AtMapKey("element").AtName("sub_test"), - expected: Attribute{ - Type: types.StringType, - Required: true, - }, - }, - "WithAttributeName-MapNestedAttributes-WithElementKeyValue": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: MapNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: path.Root("test").AtSetValue(types.StringValue("sub_test")), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtSetValue(types.StringValue("sub_test")), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[Value(\"sub_test\")]\n"+ - "Original Error: ElementKeyValue(tftypes.String<\"sub_test\">) still remains in the path: can't use tftypes.ElementKeyValue on maps", - ), - }, - }, - "WithAttributeName-SetNestedAttributes-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: SetNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: path.Root("test").AtName("sub_test"), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtName("sub_test"), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test.sub_test\n"+ - "Original Error: AttributeName(\"sub_test\") still remains in the path: can't use tftypes.AttributeName on sets", - ), - }, - }, - "WithAttributeName-SetNestedAttributes-WithElementKeyInt": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: SetNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: path.Root("test").AtListIndex(0), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtListIndex(0), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[0]\n"+ - "Original Error: ElementKeyInt(0) still remains in the path: can't use tftypes.ElementKeyInt on sets", - ), - }, - }, - "WithAttributeName-SetNestedAttributes-WithElementKeyString": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: SetNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: path.Root("test").AtMapKey("sub_test"), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtMapKey("sub_test"), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[\"sub_test\"]\n"+ - "Original Error: ElementKeyString(\"sub_test\") still remains in the path: can't use tftypes.ElementKeyString on sets", - ), - }, - }, - "WithAttributeName-SetNestedAttributes-WithElementKeyValue": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: SetNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: path.Root("test").AtSetValue(types.StringValue("sub_test")), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtSetValue(types.StringValue("sub_test")), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[Value(\"sub_test\")]\n"+ - "Original Error: "+ErrPathInsideAtomicAttribute.Error(), - ), - }, - }, - "WithAttributeName-SetNestedAttributes-WithElementKeyValue-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: SetNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: path.Root("test").AtSetValue(types.StringValue("element")).AtName("sub_test"), - expected: Attribute{ - Type: types.StringType, - Required: true, - }, - }, - "WithAttributeName-SetNestedBlocks-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Optional: true, - }, - }, - NestingMode: BlockNestingModeSet, - }, - "test": { - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSet, - }, - }, - }, - path: path.Root("test").AtName("sub_test"), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtName("sub_test"), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test.sub_test\n"+ - "Original Error: AttributeName(\"sub_test\") still remains in the path: can't apply tftypes.AttributeName to block NestingModeSet", - ), - }, - }, - "WithAttributeName-SetNestedBlocks-WithElementKeyInt": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Optional: true, - }, - }, - NestingMode: BlockNestingModeSet, - }, - "test": { - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSet, - }, - }, - }, - path: path.Root("test").AtListIndex(0), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtListIndex(0), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[0]\n"+ - "Original Error: ElementKeyInt(0) still remains in the path: can't apply tftypes.ElementKeyInt to block NestingModeSet", - ), - }, - }, - "WithAttributeName-SetNestedBlocks-WithElementKeyString": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Optional: true, - }, - }, - NestingMode: BlockNestingModeSet, - }, - "test": { - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSet, - }, - }, - }, - path: path.Root("test").AtMapKey("sub_test"), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtMapKey("sub_test"), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[\"sub_test\"]\n"+ - "Original Error: ElementKeyString(\"sub_test\") still remains in the path: can't apply tftypes.ElementKeyString to block NestingModeSet", - ), - }, - }, - "WithAttributeName-SetNestedBlocks-WithElementKeyValue": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Optional: true, - }, - }, - NestingMode: BlockNestingModeSet, - }, - "test": { - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSet, - }, - }, - }, - path: path.Root("test").AtSetValue(types.StringValue("sub_test")), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtSetValue(types.StringValue("sub_test")), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[Value(\"sub_test\")]\n"+ - "Original Error: "+ErrPathInsideAtomicAttribute.Error(), - ), - }, - }, - "WithAttributeName-SetNestedBlocks-WithElementKeyValue-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Optional: true, - }, - }, - NestingMode: BlockNestingModeSet, - }, - "test": { - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSet, - }, - }, - }, - path: path.Root("test").AtSetValue(types.StringValue("element")).AtName("sub_test"), - expected: Attribute{ - Type: types.StringType, - Required: true, - }, - }, - "WithAttributeName-SingleNestedAttributes-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: SingleNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: path.Root("test").AtName("sub_test"), - expected: Attribute{ - Type: types.StringType, - Required: true, - }, - }, - "WithAttributeName-SingleNestedAttributes-WithElementKeyInt": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: SingleNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: path.Root("test").AtListIndex(0), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtListIndex(0), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[0]\n"+ - "Original Error: ElementKeyInt(0) still remains in the path: can't apply tftypes.ElementKeyInt to Attributes", - ), - }, - }, - "WithAttributeName-SingleNestedAttributes-WithElementKeyString": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: SingleNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: path.Root("test").AtMapKey("sub_test"), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtMapKey("sub_test"), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[\"sub_test\"]\n"+ - "Original Error: ElementKeyString(\"sub_test\") still remains in the path: can't apply tftypes.ElementKeyString to Attributes", - ), - }, - }, - "WithAttributeName-SingleNestedAttributes-WithElementKeyValue": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: SingleNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: path.Root("test").AtSetValue(types.StringValue("sub_test")), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtSetValue(types.StringValue("sub_test")), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[Value(\"sub_test\")]\n"+ - "Original Error: ElementKeyValue(tftypes.String<\"sub_test\">) still remains in the path: can't apply tftypes.ElementKeyValue to Attributes", - ), - }, - }, - "WithAttributeName-SingleBlock-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSingle, - }, - "test": { - Attributes: map[string]Attribute{ - "other_nested_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSingle, - }, - }, - }, - path: path.Root("test").AtName("sub_test"), - expected: Attribute{ - Type: types.StringType, - Required: true, - }, - }, - "WithAttributeName-SingleBlock-WithElementKeyInt": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSingle, - }, - "test": { - Attributes: map[string]Attribute{ - "other_nested_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSingle, - }, - }, - }, - path: path.Root("test").AtListIndex(0), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtListIndex(0), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[0]\n"+ - "Original Error: ElementKeyInt(0) still remains in the path: can't apply tftypes.ElementKeyInt to block NestingModeSingle", - ), - }, - }, - "WithAttributeName-SingleBlock-WithElementKeyString": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSingle, - }, - "test": { - Attributes: map[string]Attribute{ - "other_nested_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSingle, - }, - }, - }, - path: path.Root("test").AtMapKey("sub_test"), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtMapKey("sub_test"), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[\"sub_test\"]\n"+ - "Original Error: ElementKeyString(\"sub_test\") still remains in the path: can't apply tftypes.ElementKeyString to block NestingModeSingle", - ), - }, - }, - "WithAttributeName-SingleBlock-WithElementKeyValue": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSingle, - }, - "test": { - Attributes: map[string]Attribute{ - "other_nested_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSingle, - }, - }, - }, - path: path.Root("test").AtSetValue(types.StringValue("sub_test")), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtSetValue(types.StringValue("sub_test")), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[Value(\"sub_test\")]\n"+ - "Original Error: ElementKeyValue(tftypes.String<\"sub_test\">) still remains in the path: can't apply tftypes.ElementKeyValue to block NestingModeSingle", - ), - }, - }, - "WithAttributeName-Object-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Type: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "sub_test": types.StringType, - }, - }, - Required: true, - }, - }, - }, - path: path.Root("test").AtName("sub_test"), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtName("sub_test"), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test.sub_test\n"+ - "Original Error: "+ErrPathInsideAtomicAttribute.Error(), - ), - }, - }, - "WithAttributeName-WithElementKeyInt-invalid-parent": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Type: types.StringType, - Required: true, - }, - }, - }, - path: path.Root("test").AtListIndex(0), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtListIndex(0), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[0]\n"+ - "Original Error: ElementKeyInt(0) still remains in the path: cannot apply AttributePathStep tftypes.ElementKeyInt to basetypes.StringType", - ), - }, - }, - "WithAttributeName-WithElementKeyInt-valid-parent": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Type: types.ListType{ - ElemType: types.StringType, - }, - Required: true, - }, - }, - }, - path: path.Root("test").AtListIndex(0), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtListIndex(0), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[0]\n"+ - "Original Error: "+ErrPathInsideAtomicAttribute.Error(), - ), - }, - }, - "WithAttributeName-WithElementKeyString-invalid-parent": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Type: types.StringType, - Required: true, - }, - }, - }, - path: path.Root("test").AtMapKey("element"), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtMapKey("element"), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[\"element\"]\n"+ - "Original Error: ElementKeyString(\"element\") still remains in the path: cannot apply AttributePathStep tftypes.ElementKeyString to basetypes.StringType", - ), - }, - }, - "WithAttributeName-WithElementKeyString-valid-parent": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Type: types.MapType{ - ElemType: types.StringType, - }, - Required: true, - }, - }, - }, - path: path.Root("test").AtMapKey("element"), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtMapKey("element"), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[\"element\"]\n"+ - "Original Error: "+ErrPathInsideAtomicAttribute.Error(), - ), - }, - }, - "WithAttributeName-WithElementKeyValue-invalid-parent": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Type: types.StringType, - Required: true, - }, - }, - }, - path: path.Root("test").AtSetValue(types.StringValue("element")), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtSetValue(types.StringValue("element")), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[Value(\"element\")]\n"+ - "Original Error: ElementKeyValue(tftypes.String<\"element\">) still remains in the path: cannot apply AttributePathStep tftypes.ElementKeyValue to basetypes.StringType", - ), - }, - }, - "WithAttributeName-WithElementKeyValue-valid-parent": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Type: types.SetType{ - ElemType: types.StringType, - }, - Required: true, - }, - }, - }, - path: path.Root("test").AtSetValue(types.StringValue("element")), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("test").AtSetValue(types.StringValue("element")), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: test[Value(\"element\")]\n"+ - "Original Error: "+ErrPathInsideAtomicAttribute.Error(), - ), - }, - }, - "WithElementKeyInt": { - schema: Schema{ - Attributes: map[string]Attribute{ - "test": { - Type: types.StringType, - Required: true, - }, - }, - }, - path: path.Empty().AtListIndex(0), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Empty().AtListIndex(0), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: [0]\n"+ - "Original Error: ElementKeyInt(0) still remains in the path: cannot apply AttributePathStep tftypes.ElementKeyInt to schema", - ), - }, - }, - "WithElementKeyString": { - schema: Schema{ - Attributes: map[string]Attribute{ - "test": { - Type: types.StringType, - Required: true, - }, - }, - }, - path: path.Empty().AtMapKey("test"), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Empty().AtMapKey("test"), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: [\"test\"]\n"+ - "Original Error: ElementKeyString(\"test\") still remains in the path: cannot apply AttributePathStep tftypes.ElementKeyString to schema", - ), - }, - }, - "WithElementKeyValue": { - schema: Schema{ - Attributes: map[string]Attribute{ - "test": { - Type: types.StringType, - Required: true, - }, - }, - }, - path: path.Empty().AtSetValue(types.StringValue("test")), - expected: nil, - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Empty().AtSetValue(types.StringValue("test")), - "Invalid Schema Path", - "When attempting to get the framework attribute associated with a schema path, an unexpected error was returned. "+ - "This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: [Value(\"test\")]\n"+ - "Original Error: ElementKeyValue(tftypes.String<\"test\">) still remains in the path: cannot apply AttributePathStep tftypes.ElementKeyValue to schema", - ), - }, - }, - } - - for name, tc := range testCases { - name, tc := name, tc - - t.Run(name, func(t *testing.T) { - t.Parallel() - - got, diags := tc.schema.AttributeAtPath(context.Background(), tc.path) - - if diff := cmp.Diff(diags, tc.expectedDiags); diff != "" { - t.Errorf("Unexpected diagnostics (+wanted, -got): %s", diff) - } - - if diff := cmp.Diff(got, tc.expected); diff != "" { - t.Errorf("Unexpected result (+wanted, -got): %s", diff) - } - }) - } -} - -func TestSchemaAttributeAtTerraformPath(t *testing.T) { - t.Parallel() - - testCases := map[string]struct { - schema Schema - path *tftypes.AttributePath - expected Attribute - expectedErr string - }{ - "empty-root": { - schema: Schema{}, - path: tftypes.NewAttributePath(), - expected: Attribute{}, - expectedErr: "got unexpected type tfsdk.Schema", - }, - "empty-nil": { - schema: Schema{}, - path: nil, - expected: Attribute{}, - expectedErr: "got unexpected type tfsdk.Schema", - }, - "root": { - schema: Schema{ - Attributes: map[string]Attribute{ - "test": { - Type: types.StringType, - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath(), - expected: Attribute{}, - expectedErr: "got unexpected type tfsdk.Schema", - }, - "nil": { - schema: Schema{ - Attributes: map[string]Attribute{ - "test": { - Type: types.StringType, - Required: true, - }, - }, - }, - path: nil, - expected: Attribute{}, - expectedErr: "got unexpected type tfsdk.Schema", - }, - "WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Type: types.StringType, - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test"), - expected: Attribute{ - Type: types.StringType, - Required: true, - }, - }, - "WithAttributeName-ListNestedAttributes-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: ListNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithAttributeName("sub_test"), - expected: Attribute{}, - expectedErr: "AttributeName(\"sub_test\") still remains in the path: can't apply tftypes.AttributeName to ListNestedAttributes", - }, - "WithAttributeName-ListNestedAttributes-WithElementKeyInt": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: ListNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyInt(0), - expected: Attribute{}, - expectedErr: ErrPathInsideAtomicAttribute.Error(), - }, - "WithAttributeName-ListNestedAttributes-WithElementKeyInt-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: ListNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyInt(0).WithAttributeName("sub_test"), - expected: Attribute{ - Type: types.StringType, - Required: true, - }, - }, - "WithAttributeName-ListNestedAttributes-WithElementKeyString": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: ListNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyString("sub_test"), - expected: Attribute{}, - expectedErr: "ElementKeyString(\"sub_test\") still remains in the path: can't apply tftypes.ElementKeyString to ListNestedAttributes", - }, - "WithAttributeName-ListNestedAttributes-WithElementKeyValue": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: ListNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyValue(tftypes.NewValue(tftypes.String, "sub_test")), - expected: Attribute{}, - expectedErr: "ElementKeyValue(tftypes.String<\"sub_test\">) still remains in the path: can't apply tftypes.ElementKeyValue to ListNestedAttributes", - }, - "WithAttributeName-ListNestedBlocks-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Optional: true, - }, - }, - NestingMode: BlockNestingModeList, - }, - "test": { - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeList, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithAttributeName("sub_test"), - expected: Attribute{}, - expectedErr: "AttributeName(\"sub_test\") still remains in the path: can't apply tftypes.AttributeName to block NestingModeList", - }, - "WithAttributeName-ListNestedBlocks-WithElementKeyInt": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Optional: true, - }, - }, - NestingMode: BlockNestingModeList, - }, - "test": { - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeList, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyInt(0), - expected: Attribute{}, - expectedErr: ErrPathInsideAtomicAttribute.Error(), - }, - "WithAttributeName-ListNestedBlocks-WithElementKeyInt-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Optional: true, - }, - }, - NestingMode: BlockNestingModeList, - }, - "test": { - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeList, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyInt(0).WithAttributeName("sub_test"), - expected: Attribute{ - Type: types.StringType, - Required: true, - }, - }, - "WithAttributeName-ListNestedBlocks-WithElementKeyString": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Optional: true, - }, - }, - NestingMode: BlockNestingModeList, - }, - "test": { - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeList, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyString("sub_test"), - expected: Attribute{}, - expectedErr: "ElementKeyString(\"sub_test\") still remains in the path: can't apply tftypes.ElementKeyString to block NestingModeList", - }, - "WithAttributeName-ListNestedBlocks-WithElementKeyValue": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Optional: true, - }, - }, - NestingMode: BlockNestingModeList, - }, - "test": { - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeList, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyValue(tftypes.NewValue(tftypes.String, "sub_test")), - expected: Attribute{}, - expectedErr: "ElementKeyValue(tftypes.String<\"sub_test\">) still remains in the path: can't apply tftypes.ElementKeyValue to block NestingModeList", - }, - "WithAttributeName-MapNestedAttributes-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: MapNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithAttributeName("sub_test"), - expected: Attribute{}, - expectedErr: "AttributeName(\"sub_test\") still remains in the path: can't use tftypes.AttributeName on maps", - }, - "WithAttributeName-MapNestedAttributes-WithElementKeyInt": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: MapNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyInt(0), - expected: Attribute{}, - expectedErr: "ElementKeyInt(0) still remains in the path: can't use tftypes.ElementKeyInt on maps", - }, - "WithAttributeName-MapNestedAttributes-WithElementKeyString": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: MapNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyString("sub_test"), - expected: Attribute{}, - expectedErr: ErrPathInsideAtomicAttribute.Error(), - }, - "WithAttributeName-MapNestedAttributes-WithElementKeyString-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: MapNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyString("element").WithAttributeName("sub_test"), - expected: Attribute{ - Type: types.StringType, - Required: true, - }, - }, - "WithAttributeName-MapNestedAttributes-WithElementKeyValue": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: MapNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyValue(tftypes.NewValue(tftypes.String, "sub_test")), - expected: Attribute{}, - expectedErr: "ElementKeyValue(tftypes.String<\"sub_test\">) still remains in the path: can't use tftypes.ElementKeyValue on maps", - }, - "WithAttributeName-SetNestedAttributes-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: SetNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithAttributeName("sub_test"), - expected: Attribute{}, - expectedErr: "AttributeName(\"sub_test\") still remains in the path: can't use tftypes.AttributeName on sets", - }, - "WithAttributeName-SetNestedAttributes-WithElementKeyInt": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: SetNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyInt(0), - expected: Attribute{}, - expectedErr: "ElementKeyInt(0) still remains in the path: can't use tftypes.ElementKeyInt on sets", - }, - "WithAttributeName-SetNestedAttributes-WithElementKeyString": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: SetNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyString("sub_test"), - expected: Attribute{}, - expectedErr: "ElementKeyString(\"sub_test\") still remains in the path: can't use tftypes.ElementKeyString on sets", - }, - "WithAttributeName-SetNestedAttributes-WithElementKeyValue": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: SetNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyValue(tftypes.NewValue(tftypes.String, "sub_test")), - expected: Attribute{}, - expectedErr: ErrPathInsideAtomicAttribute.Error(), - }, - "WithAttributeName-SetNestedAttributes-WithElementKeyValue-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: SetNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyValue(tftypes.NewValue(tftypes.String, "element")).WithAttributeName("sub_test"), - expected: Attribute{ - Type: types.StringType, - Required: true, - }, - }, - "WithAttributeName-SetNestedBlocks-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Optional: true, - }, - }, - NestingMode: BlockNestingModeSet, - }, - "test": { - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSet, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithAttributeName("sub_test"), - expected: Attribute{}, - expectedErr: "AttributeName(\"sub_test\") still remains in the path: can't apply tftypes.AttributeName to block NestingModeSet", - }, - "WithAttributeName-SetNestedBlocks-WithElementKeyInt": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Optional: true, - }, - }, - NestingMode: BlockNestingModeSet, - }, - "test": { - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSet, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyInt(0), - expected: Attribute{}, - expectedErr: "ElementKeyInt(0) still remains in the path: can't apply tftypes.ElementKeyInt to block NestingModeSet", - }, - "WithAttributeName-SetNestedBlocks-WithElementKeyString": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Optional: true, - }, - }, - NestingMode: BlockNestingModeSet, - }, - "test": { - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSet, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyString("sub_test"), - expected: Attribute{}, - expectedErr: "ElementKeyString(\"sub_test\") still remains in the path: can't apply tftypes.ElementKeyString to block NestingModeSet", - }, - "WithAttributeName-SetNestedBlocks-WithElementKeyValue": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Optional: true, - }, - }, - NestingMode: BlockNestingModeSet, - }, - "test": { - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSet, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyValue(tftypes.NewValue(tftypes.String, "sub_test")), - expected: Attribute{}, - expectedErr: ErrPathInsideAtomicAttribute.Error(), - }, - "WithAttributeName-SetNestedBlocks-WithElementKeyValue-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Optional: true, - }, - }, - NestingMode: BlockNestingModeSet, - }, - "test": { - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSet, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyValue(tftypes.NewValue(tftypes.String, "element")).WithAttributeName("sub_test"), - expected: Attribute{ - Type: types.StringType, - Required: true, - }, - }, - "WithAttributeName-SingleNestedAttributes-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: SingleNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithAttributeName("sub_test"), - expected: Attribute{ - Type: types.StringType, - Required: true, - }, - }, - "WithAttributeName-SingleNestedAttributes-WithElementKeyInt": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: SingleNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyInt(0), - expected: Attribute{}, - expectedErr: "ElementKeyInt(0) still remains in the path: can't apply tftypes.ElementKeyInt to Attributes", - }, - "WithAttributeName-SingleNestedAttributes-WithElementKeyString": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: SingleNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyString("sub_test"), - expected: Attribute{}, - expectedErr: "ElementKeyString(\"sub_test\") still remains in the path: can't apply tftypes.ElementKeyString to Attributes", - }, - "WithAttributeName-SingleNestedAttributes-WithElementKeyValue": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Attributes: SingleNestedAttributes(map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }), - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyValue(tftypes.NewValue(tftypes.String, "sub_test")), - expected: Attribute{}, - expectedErr: "ElementKeyValue(tftypes.String<\"sub_test\">) still remains in the path: can't apply tftypes.ElementKeyValue to Attributes", - }, - "WithAttributeName-SingleBlock-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSingle, - }, - "test": { - Attributes: map[string]Attribute{ - "other_nested_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSingle, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithAttributeName("sub_test"), - expected: Attribute{ - Type: types.StringType, - Required: true, - }, - }, - "WithAttributeName-SingleBlock-WithElementKeyInt": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSingle, - }, - "test": { - Attributes: map[string]Attribute{ - "other_nested_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSingle, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyInt(0), - expected: Attribute{}, - expectedErr: "ElementKeyInt(0) still remains in the path: can't apply tftypes.ElementKeyInt to block NestingModeSingle", - }, - "WithAttributeName-SingleBlock-WithElementKeyString": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSingle, - }, - "test": { - Attributes: map[string]Attribute{ - "other_nested_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSingle, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyString("sub_test"), - expected: Attribute{}, - expectedErr: "ElementKeyString(\"sub_test\") still remains in the path: can't apply tftypes.ElementKeyString to block NestingModeSingle", - }, - "WithAttributeName-SingleBlock-WithElementKeyValue": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other_attr": { - Type: types.BoolType, - Optional: true, - }, - }, - Blocks: map[string]Block{ - "other_block": { - Attributes: map[string]Attribute{ - "sub_test": { - Type: types.BoolType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSingle, - }, - "test": { - Attributes: map[string]Attribute{ - "other_nested_attr": { - Type: types.BoolType, - Optional: true, - }, - "sub_test": { - Type: types.StringType, - Required: true, - }, - }, - NestingMode: BlockNestingModeSingle, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyValue(tftypes.NewValue(tftypes.String, "sub_test")), - expected: Attribute{}, - expectedErr: "ElementKeyValue(tftypes.String<\"sub_test\">) still remains in the path: can't apply tftypes.ElementKeyValue to block NestingModeSingle", - }, - "WithAttributeName-Object-WithAttributeName": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Type: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "sub_test": types.StringType, - }, - }, - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithAttributeName("sub_test"), - expected: Attribute{}, - expectedErr: ErrPathInsideAtomicAttribute.Error(), - }, - "WithAttributeName-WithElementKeyInt-invalid-parent": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Type: types.StringType, - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyInt(0), - expected: Attribute{}, - expectedErr: "ElementKeyInt(0) still remains in the path: cannot apply AttributePathStep tftypes.ElementKeyInt to basetypes.StringType", - }, - "WithAttributeName-WithElementKeyInt-valid-parent": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Type: types.ListType{ - ElemType: types.StringType, - }, - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyInt(0), - expected: Attribute{}, - expectedErr: ErrPathInsideAtomicAttribute.Error(), - }, - "WithAttributeName-WithElementKeyString-invalid-parent": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Type: types.StringType, - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyString("element"), - expected: Attribute{}, - expectedErr: "ElementKeyString(\"element\") still remains in the path: cannot apply AttributePathStep tftypes.ElementKeyString to basetypes.StringType", - }, - "WithAttributeName-WithElementKeyString-valid-parent": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Type: types.MapType{ - ElemType: types.StringType, - }, - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyString("element"), - expected: Attribute{}, - expectedErr: ErrPathInsideAtomicAttribute.Error(), - }, - "WithAttributeName-WithElementKeyValue-invalid-parent": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Type: types.StringType, - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyValue(tftypes.NewValue(tftypes.String, "element")), - expected: Attribute{}, - expectedErr: "ElementKeyValue(tftypes.String<\"element\">) still remains in the path: cannot apply AttributePathStep tftypes.ElementKeyValue to basetypes.StringType", - }, - "WithAttributeName-WithElementKeyValue-valid-parent": { - schema: Schema{ - Attributes: map[string]Attribute{ - "other": { - Type: types.BoolType, - Optional: true, - }, - "test": { - Type: types.SetType{ - ElemType: types.StringType, - }, - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("test").WithElementKeyValue(tftypes.NewValue(tftypes.String, "element")), - expected: Attribute{}, - expectedErr: ErrPathInsideAtomicAttribute.Error(), - }, - "WithElementKeyInt": { - schema: Schema{ - Attributes: map[string]Attribute{ - "test": { - Type: types.StringType, - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithElementKeyInt(0), - expected: Attribute{}, - expectedErr: "ElementKeyInt(0) still remains in the path: cannot apply AttributePathStep tftypes.ElementKeyInt to schema", - }, - "WithElementKeyString": { - schema: Schema{ - Attributes: map[string]Attribute{ - "test": { - Type: types.StringType, - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithElementKeyString("test"), - expected: Attribute{}, - expectedErr: "ElementKeyString(\"test\") still remains in the path: cannot apply AttributePathStep tftypes.ElementKeyString to schema", - }, - "WithElementKeyValue": { - schema: Schema{ - Attributes: map[string]Attribute{ - "test": { - Type: types.StringType, - Required: true, - }, - }, - }, - path: tftypes.NewAttributePath().WithElementKeyValue(tftypes.NewValue(tftypes.String, "test")), - expected: Attribute{}, - expectedErr: "ElementKeyValue(tftypes.String<\"test\">) still remains in the path: cannot apply AttributePathStep tftypes.ElementKeyValue to schema", - }, - } - - for name, tc := range testCases { - name, tc := name, tc - - t.Run(name, func(t *testing.T) { - t.Parallel() - - got, err := tc.schema.AttributeAtTerraformPath(context.Background(), tc.path) - - if err != nil { - if tc.expectedErr == "" { - t.Errorf("Unexpected error: %s", err) - return - } - if err.Error() != tc.expectedErr { - t.Errorf("Expected error to be %q, got %q", tc.expectedErr, err.Error()) - return - } - // got expected error - return - } - - if err == nil && tc.expectedErr != "" { - t.Errorf("Expected error to be %q, got nil", tc.expectedErr) - return - } - - if diff := cmp.Diff(got, tc.expected); diff != "" { - t.Errorf("Unexpected result (+wanted, -got): %s", diff) - } - }) - } -} - -func TestSchemaType(t *testing.T) { - testSchema := Schema{ - Attributes: map[string]Attribute{ - "foo": { - Type: types.StringType, - Required: true, - }, - "bar": { - Type: types.ListType{ - ElemType: types.StringType, - }, - Required: true, - }, - "disks": { - Attributes: ListNestedAttributes(map[string]Attribute{ - "id": { - Type: types.StringType, - Required: true, - }, - "delete_with_instance": { - Type: types.BoolType, - Optional: true, - }, - }), - Optional: true, - Computed: true, - }, - "boot_disk": { - Attributes: SingleNestedAttributes(map[string]Attribute{ - "id": { - Type: types.StringType, - Required: true, - }, - "delete_with_instance": { - Type: types.BoolType, - }, - }), - }, - }, - Blocks: map[string]Block{ - "list_nested_blocks": { - Attributes: map[string]Attribute{ - "string": { - Type: types.StringType, - Required: true, - }, - "number": { - Type: types.NumberType, - Optional: true, - }, - "bool": { - Type: types.BoolType, - Computed: true, - }, - "list": { - Type: types.ListType{ElemType: types.StringType}, - Computed: true, - Optional: true, - }, - }, - NestingMode: BlockNestingModeList, - }, - "set_nested_blocks": { - Attributes: map[string]Attribute{ - "string": { - Type: types.StringType, - Required: true, - }, - "number": { - Type: types.NumberType, - Optional: true, - }, - "bool": { - Type: types.BoolType, - Computed: true, - }, - "list": { - Type: types.ListType{ElemType: types.StringType}, - Computed: true, - Optional: true, - }, - }, - NestingMode: BlockNestingModeSet, - }, - "single_nested_block": { - Attributes: map[string]Attribute{ - "string": { - Type: types.StringType, - Required: true, - }, - "number": { - Type: types.NumberType, - Optional: true, - }, - "bool": { - Type: types.BoolType, - Computed: true, - }, - "list": { - Type: types.ListType{ElemType: types.StringType}, - Computed: true, - Optional: true, - }, - }, - NestingMode: BlockNestingModeSingle, - }, - }, - } - - expectedType := types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "foo": types.StringType, - "bar": types.ListType{ - ElemType: types.StringType, - }, - "disks": types.ListType{ - ElemType: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "id": types.StringType, - "delete_with_instance": types.BoolType, - }, - }, - }, - "boot_disk": types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "id": types.StringType, - "delete_with_instance": types.BoolType, - }, - }, - "list_nested_blocks": types.ListType{ - ElemType: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "string": types.StringType, - "number": types.NumberType, - "bool": types.BoolType, - "list": types.ListType{ElemType: types.StringType}, - }, - }, - }, - "set_nested_blocks": types.SetType{ - ElemType: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "string": types.StringType, - "number": types.NumberType, - "bool": types.BoolType, - "list": types.ListType{ElemType: types.StringType}, - }, - }, - }, - "single_nested_block": types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "string": types.StringType, - "number": types.NumberType, - "bool": types.BoolType, - "list": types.ListType{ElemType: types.StringType}, - }, - }, - }, - } - - actualType := testSchema.Type() - - if !expectedType.Equal(actualType) { - t.Fatalf("types not equal (+wanted, -got): %s", cmp.Diff(expectedType, actualType)) - } -} - -func TestSchemaTypeAtPath(t *testing.T) { - t.Parallel() - - testCases := map[string]struct { - schema Schema - path path.Path - expected attr.Type - expectedDiags diag.Diagnostics - }{ - "empty-schema-empty-path": { - schema: Schema{}, - path: path.Empty(), - expected: types.ObjectType{}, - }, - "empty-path": { - schema: Schema{ - Attributes: map[string]Attribute{ - "bool": { - Required: true, - Type: types.BoolType, - }, - "string": { - Required: true, - Type: types.StringType, - }, - }, - }, - path: path.Empty(), - expected: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "bool": types.BoolType, - "string": types.StringType, - }, - }, - }, - "AttributeName-Attribute": { - schema: Schema{ - Attributes: map[string]Attribute{ - "bool": { - Required: true, - Type: types.BoolType, - }, - "string": { - Required: true, - Type: types.StringType, - }, - }, - }, - path: path.Root("string"), - expected: types.StringType, - }, - "AttributeName-Block": { - schema: Schema{ - Blocks: map[string]Block{ - "list_block": { - Attributes: map[string]Attribute{ - "list_block_nested": { - Required: true, - Type: types.StringType, - }, - }, - NestingMode: BlockNestingModeList, - }, - "set_block": { - Attributes: map[string]Attribute{ - "set_block_nested": { - Required: true, - Type: types.StringType, - }, - }, - NestingMode: BlockNestingModeSet, - }, - "single_block": { - Attributes: map[string]Attribute{ - "single_block_nested": { - Required: true, - Type: types.StringType, - }, - }, - NestingMode: BlockNestingModeSingle, - }, - }, - }, - path: path.Root("list_block"), - expected: types.ListType{ - ElemType: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "list_block_nested": types.StringType, - }, - }, - }, - }, - "AttributeName-non-existent": { - schema: Schema{}, - path: path.Root("non-existent"), - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Root("non-existent"), - "Invalid Schema Path", - "When attempting to get the framework type associated with a schema path, an unexpected error was returned. This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: non-existent\n"+ - "Original Error: AttributeName(\"non-existent\") still remains in the path: could not find attribute or block \"non-existent\" in schema", - ), - }, - }, - "ElementKeyInt": { - schema: Schema{}, - path: path.Empty().AtListIndex(0), - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Empty().AtListIndex(0), - "Invalid Schema Path", - "When attempting to get the framework type associated with a schema path, an unexpected error was returned. This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: [0]\n"+ - "Original Error: ElementKeyInt(0) still remains in the path: cannot apply AttributePathStep tftypes.ElementKeyInt to schema", - ), - }, - }, - "ElementKeyString": { - schema: Schema{}, - path: path.Empty().AtMapKey("invalid"), - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Empty().AtMapKey("invalid"), - "Invalid Schema Path", - "When attempting to get the framework type associated with a schema path, an unexpected error was returned. This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: [\"invalid\"]\n"+ - "Original Error: ElementKeyString(\"invalid\") still remains in the path: cannot apply AttributePathStep tftypes.ElementKeyString to schema", - ), - }, - }, - "ElementKeyValue": { - schema: Schema{}, - path: path.Empty().AtSetValue(types.StringNull()), - expectedDiags: diag.Diagnostics{ - diag.NewAttributeErrorDiagnostic( - path.Empty().AtSetValue(types.StringNull()), - "Invalid Schema Path", - "When attempting to get the framework type associated with a schema path, an unexpected error was returned. This is always an issue with the provider. Please report this to the provider developers.\n\n"+ - "Path: [Value()]\n"+ - "Original Error: ElementKeyValue(tftypes.String) still remains in the path: cannot apply AttributePathStep tftypes.ElementKeyValue to schema", - ), - }, - }, - } - - for name, testCase := range testCases { - name, testCase := name, testCase - - t.Run(name, func(t *testing.T) { - t.Parallel() - - got, diags := testCase.schema.TypeAtPath(context.Background(), testCase.path) - - if diff := cmp.Diff(diags, testCase.expectedDiags); diff != "" { - t.Errorf("unexpected diagnostics difference: %s", diff) - } - - if diff := cmp.Diff(got, testCase.expected); diff != "" { - t.Errorf("unexpected difference: %s", diff) - } - }) - } -} - -func TestSchemaTypeAtTerraformPath(t *testing.T) { - t.Parallel() - - testCases := map[string]struct { - schema Schema - path *tftypes.AttributePath - expected attr.Type - expectedError error - }{ - "empty-schema-nil-path": { - schema: Schema{}, - path: nil, - expected: types.ObjectType{}, - }, - "empty-schema-empty-path": { - schema: Schema{}, - path: tftypes.NewAttributePath(), - expected: types.ObjectType{}, - }, - "nil-path": { - schema: Schema{ - Attributes: map[string]Attribute{ - "bool": { - Required: true, - Type: types.BoolType, - }, - "string": { - Required: true, - Type: types.StringType, - }, - }, - }, - path: nil, - expected: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "bool": types.BoolType, - "string": types.StringType, - }, - }, - }, - "empty-path": { - schema: Schema{ - Attributes: map[string]Attribute{ - "bool": { - Required: true, - Type: types.BoolType, - }, - "string": { - Required: true, - Type: types.StringType, - }, - }, - }, - path: tftypes.NewAttributePath(), - expected: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "bool": types.BoolType, - "string": types.StringType, - }, - }, - }, - "AttributeName-Attribute": { - schema: Schema{ - Attributes: map[string]Attribute{ - "bool": { - Required: true, - Type: types.BoolType, - }, - "string": { - Required: true, - Type: types.StringType, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("string"), - expected: types.StringType, - }, - "AttributeName-Block": { - schema: Schema{ - Blocks: map[string]Block{ - "list_block": { - Attributes: map[string]Attribute{ - "list_block_nested": { - Required: true, - Type: types.StringType, - }, - }, - NestingMode: BlockNestingModeList, - }, - "set_block": { - Attributes: map[string]Attribute{ - "set_block_nested": { - Required: true, - Type: types.StringType, - }, - }, - NestingMode: BlockNestingModeSet, - }, - "single_block": { - Attributes: map[string]Attribute{ - "single_block_nested": { - Required: true, - Type: types.StringType, - }, - }, - NestingMode: BlockNestingModeSingle, - }, - }, - }, - path: tftypes.NewAttributePath().WithAttributeName("list_block"), - expected: types.ListType{ - ElemType: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "list_block_nested": types.StringType, - }, - }, - }, - }, - "AttributeName-non-existent": { - schema: Schema{}, - path: tftypes.NewAttributePath().WithAttributeName("non-existent"), - expectedError: fmt.Errorf("AttributeName(\"non-existent\") still remains in the path: could not find attribute or block \"non-existent\" in schema"), - }, - "ElementKeyInt": { - schema: Schema{}, - path: tftypes.NewAttributePath().WithElementKeyInt(0), - expectedError: fmt.Errorf("ElementKeyInt(0) still remains in the path: cannot apply AttributePathStep tftypes.ElementKeyInt to schema"), - }, - "ElementKeyString": { - schema: Schema{}, - path: tftypes.NewAttributePath().WithElementKeyString("invalid"), - expectedError: fmt.Errorf("ElementKeyString(\"invalid\") still remains in the path: cannot apply AttributePathStep tftypes.ElementKeyString to schema"), - }, - "ElementKeyValue": { - schema: Schema{}, - path: tftypes.NewAttributePath().WithElementKeyValue(tftypes.NewValue(tftypes.String, nil)), - expectedError: fmt.Errorf("ElementKeyValue(tftypes.String) still remains in the path: cannot apply AttributePathStep tftypes.ElementKeyValue to schema"), - }, - } - - for name, testCase := range testCases { - name, testCase := name, testCase - - t.Run(name, func(t *testing.T) { - t.Parallel() - - got, err := testCase.schema.TypeAtTerraformPath(context.Background(), testCase.path) - - if err != nil { - if testCase.expectedError == nil { - t.Fatalf("expected no error, got: %s", err) - } - - if !strings.Contains(err.Error(), testCase.expectedError.Error()) { - t.Fatalf("expected error %q, got: %s", testCase.expectedError, err) - } - } - - if err == nil && testCase.expectedError != nil { - t.Fatalf("got no error, expected: %s", testCase.expectedError) - } - - if diff := cmp.Diff(got, testCase.expected); diff != "" { - t.Errorf("unexpected difference: %s", diff) - } - }) - } -} diff --git a/tfsdk/state_test.go b/tfsdk/state_test.go index 23ab826a0..c06d81865 100644 --- a/tfsdk/state_test.go +++ b/tfsdk/state_test.go @@ -1,4 +1,4 @@ -package tfsdk +package tfsdk_test import ( "context" @@ -7,9 +7,12 @@ import ( "github.com/google/go-cmp/cmp" "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/internal/fwschema" intreflect "github.com/hashicorp/terraform-plugin-framework/internal/reflect" + "github.com/hashicorp/terraform-plugin-framework/internal/testing/testschema" testtypes "github.com/hashicorp/terraform-plugin-framework/internal/testing/types" "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/tfsdk" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-go/tftypes" ) @@ -18,7 +21,7 @@ func TestStateGet(t *testing.T) { t.Parallel() testCases := map[string]struct { - state State + state tfsdk.State target any expected any expectedDiags diag.Diagnostics @@ -27,7 +30,7 @@ func TestStateGet(t *testing.T) { // These test cases are to ensure Plan schema and data values are // passed appropriately to the shared implementation. "valid": { - state: State{ + state: tfsdk.State{ Raw: tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ @@ -38,9 +41,9 @@ func TestStateGet(t *testing.T) { "string": tftypes.NewValue(tftypes.String, "test"), }, ), - Schema: Schema{ - Attributes: map[string]Attribute{ - "string": { + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "string": testschema.Attribute{ Optional: true, Type: types.StringType, }, @@ -57,7 +60,7 @@ func TestStateGet(t *testing.T) { }, }, "diagnostic": { - state: State{ + state: tfsdk.State{ Raw: tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ @@ -68,9 +71,9 @@ func TestStateGet(t *testing.T) { "bool": tftypes.NewValue(tftypes.Bool, nil), }, ), - Schema: Schema{ - Attributes: map[string]Attribute{ - "bool": { + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "bool": testschema.Attribute{ Optional: true, Type: types.BoolType, }, @@ -121,7 +124,7 @@ func TestStateGetAttribute(t *testing.T) { t.Parallel() type testCase struct { - state State + state tfsdk.State target interface{} expected interface{} expectedDiags diag.Diagnostics @@ -132,7 +135,7 @@ func TestStateGetAttribute(t *testing.T) { // testing. These test cases are to ensure Plan schema and data values // are passed appropriately to the shared implementation. "valid": { - state: State{ + state: tfsdk.State{ Raw: tftypes.NewValue(tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ "name": tftypes.String, @@ -140,9 +143,9 @@ func TestStateGetAttribute(t *testing.T) { }, map[string]tftypes.Value{ "name": tftypes.NewValue(tftypes.String, "namevalue"), }), - Schema: Schema{ - Attributes: map[string]Attribute{ - "name": { + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "name": testschema.Attribute{ Type: types.StringType, Required: true, }, @@ -150,10 +153,10 @@ func TestStateGetAttribute(t *testing.T) { }, }, target: new(string), - expected: newStringPointer("namevalue"), + expected: pointer("namevalue"), }, "diagnostics": { - state: State{ + state: tfsdk.State{ Raw: tftypes.NewValue(tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ "name": tftypes.String, @@ -161,9 +164,9 @@ func TestStateGetAttribute(t *testing.T) { }, map[string]tftypes.Value{ "name": tftypes.NewValue(tftypes.String, "namevalue"), }), - Schema: Schema{ - Attributes: map[string]Attribute{ - "name": { + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "name": testschema.Attribute{ Type: testtypes.StringTypeWithValidateWarning{}, Required: true, }, @@ -198,7 +201,7 @@ func TestStateSet(t *testing.T) { t.Parallel() type testCase struct { - state State + state tfsdk.State val interface{} expected tftypes.Value expectedDiags diag.Diagnostics @@ -209,7 +212,7 @@ func TestStateSet(t *testing.T) { // These test cases are to ensure State schema and data values are // passed appropriately to the shared implementation. "valid": { - state: State{ + state: tfsdk.State{ Raw: tftypes.NewValue(tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ "name": tftypes.String, @@ -217,9 +220,9 @@ func TestStateSet(t *testing.T) { }, map[string]tftypes.Value{ "name": tftypes.NewValue(tftypes.String, "oldvalue"), }), - Schema: Schema{ - Attributes: map[string]Attribute{ - "name": { + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "name": testschema.Attribute{ Type: types.StringType, Required: true, }, @@ -240,11 +243,11 @@ func TestStateSet(t *testing.T) { }), }, "diagnostics": { - state: State{ + state: tfsdk.State{ Raw: tftypes.Value{}, - Schema: Schema{ - Attributes: map[string]Attribute{ - "name": { + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "name": testschema.Attribute{ Type: testtypes.StringTypeWithValidateWarning{}, Required: true, }, @@ -289,7 +292,7 @@ func TestStateSetAttribute(t *testing.T) { t.Parallel() type testCase struct { - state State + state tfsdk.State path path.Path val interface{} expected tftypes.Value @@ -301,7 +304,7 @@ func TestStateSetAttribute(t *testing.T) { // testing. These test cases are to ensure State schema and data values // are passed appropriately to the shared implementation. "valid": { - state: State{ + state: tfsdk.State{ Raw: tftypes.NewValue(tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ "test": tftypes.String, @@ -311,13 +314,13 @@ func TestStateSetAttribute(t *testing.T) { "test": tftypes.NewValue(tftypes.String, "originalvalue"), "other": tftypes.NewValue(tftypes.String, "should be untouched"), }), - Schema: Schema{ - Attributes: map[string]Attribute{ - "test": { + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "test": testschema.Attribute{ Type: types.StringType, Required: true, }, - "other": { + "other": testschema.Attribute{ Type: types.StringType, Required: true, }, @@ -337,7 +340,7 @@ func TestStateSetAttribute(t *testing.T) { }), }, "diagnostics": { - state: State{ + state: tfsdk.State{ Raw: tftypes.NewValue(tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ "name": tftypes.String, @@ -345,9 +348,9 @@ func TestStateSetAttribute(t *testing.T) { }, map[string]tftypes.Value{ "name": tftypes.NewValue(tftypes.String, "originalname"), }), - Schema: Schema{ - Attributes: map[string]Attribute{ - "name": { + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "name": testschema.Attribute{ Type: testtypes.StringTypeWithValidateWarning{}, Required: true, },