Skip to content

Commit

Permalink
Add reflection tests for object models with tfsdk tags in framework…
Browse files Browse the repository at this point in the history
… providers
  • Loading branch information
austinvalle committed Jul 23, 2024
1 parent a9ea115 commit 6d5f218
Show file tree
Hide file tree
Showing 8 changed files with 1,156 additions and 3 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ toolchain go1.21.6
require (
github.com/hashicorp/go-memdb v1.3.4
github.com/hashicorp/terraform-json v0.22.1
github.com/hashicorp/terraform-plugin-framework v1.10.0
github.com/hashicorp/terraform-plugin-framework v1.10.1-0.20240723171809-2ccf8f265f8d
github.com/hashicorp/terraform-plugin-framework-timeouts v0.4.1
github.com/hashicorp/terraform-plugin-framework-timetypes v0.4.0
github.com/hashicorp/terraform-plugin-go v0.23.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ github.com/hashicorp/terraform-exec v0.21.0 h1:uNkLAe95ey5Uux6KJdua6+cv8asgILFVW
github.com/hashicorp/terraform-exec v0.21.0/go.mod h1:1PPeMYou+KDUSSeRE9szMZ/oHf4fYUmB923Wzbq1ICg=
github.com/hashicorp/terraform-json v0.22.1 h1:xft84GZR0QzjPVWs4lRUwvTcPnegqlyS7orfb5Ltvec=
github.com/hashicorp/terraform-json v0.22.1/go.mod h1:JbWSQCLFSXFFhg42T7l9iJwdGXBYV8fmmD6o/ML4p3A=
github.com/hashicorp/terraform-plugin-framework v1.10.0 h1:xXhICE2Fns1RYZxEQebwkB2+kXouLC932Li9qelozrc=
github.com/hashicorp/terraform-plugin-framework v1.10.0/go.mod h1:qBXLDn69kM97NNVi/MQ9qgd1uWWsVftGSnygYG1tImM=
github.com/hashicorp/terraform-plugin-framework v1.10.1-0.20240723171809-2ccf8f265f8d h1:3QAP7iiGP+dr1z6kcZg08Z2wAZKN3CqJIHryCROqw1s=
github.com/hashicorp/terraform-plugin-framework v1.10.1-0.20240723171809-2ccf8f265f8d/go.mod h1:qBXLDn69kM97NNVi/MQ9qgd1uWWsVftGSnygYG1tImM=
github.com/hashicorp/terraform-plugin-framework-timeouts v0.4.1 h1:gm5b1kHgFFhaKFhm4h2TgvMUlNzFAtUqlcOWnWPm+9E=
github.com/hashicorp/terraform-plugin-framework-timeouts v0.4.1/go.mod h1:MsjL1sQ9L7wGwzJ5RjcI6FzEMdyoBnw+XK8ZnOvQOLY=
github.com/hashicorp/terraform-plugin-framework-timetypes v0.4.0 h1:XLI93Oqw2/KTzYjgCXrUnm8LBkGAiHC/mDQg5g5Vob4=
Expand Down
1 change: 1 addition & 0 deletions internal/framework5provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ func (p *testProvider) Resources(_ context.Context) []func() resource.Resource {
NewUserResource,
NewFloat32PrecisionResource,
NewFloat64PrecisionResource,
NewTFSDKReflectionResource,
}
}

Expand Down
324 changes: 324 additions & 0 deletions internal/framework5provider/tfsdk_reflection_resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,324 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package framework

import (
"context"

"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/dynamicplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/float64planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/listplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/mapplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/types"
)

var _ resource.Resource = TFSDKReflectionResource{}

func NewTFSDKReflectionResource() resource.Resource {
return &TFSDKReflectionResource{}
}

// TFSDKReflectionResource is a smoke test for reflection logic on objects using the `tfsdk` field tags.
type TFSDKReflectionResource struct{}

func (r TFSDKReflectionResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_tfsdk_reflection"
}

var nestedObjType = types.ObjectType{
AttrTypes: map[string]attr.Type{
"nested_string": types.StringType,
},
}

func (r TFSDKReflectionResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"config_bool": schema.BoolAttribute{
Required: true,
},
"computed_bool": schema.BoolAttribute{
Computed: true,
PlanModifiers: []planmodifier.Bool{
boolplanmodifier.UseStateForUnknown(),
},
},
"config_dynamic": schema.DynamicAttribute{
Required: true,
},
"computed_dynamic": schema.DynamicAttribute{
Computed: true,
PlanModifiers: []planmodifier.Dynamic{
dynamicplanmodifier.UseStateForUnknown(),
},
},
"config_float64": schema.Float64Attribute{
Required: true,
},
"computed_float64": schema.Float64Attribute{
Computed: true,
PlanModifiers: []planmodifier.Float64{
float64planmodifier.UseStateForUnknown(),
},
},
"config_int64": schema.Int64Attribute{
Required: true,
},
"computed_int64": schema.Int64Attribute{
Computed: true,
PlanModifiers: []planmodifier.Int64{
int64planmodifier.UseStateForUnknown(),
},
},
"config_list": schema.ListAttribute{
ElementType: types.StringType,
Required: true,
},
"computed_list": schema.ListAttribute{
ElementType: types.StringType,
Computed: true,
PlanModifiers: []planmodifier.List{
listplanmodifier.UseStateForUnknown(),
},
},
"config_map": schema.MapAttribute{
ElementType: types.StringType,
Required: true,
},
"computed_map": schema.MapAttribute{
ElementType: types.StringType,
Computed: true,
PlanModifiers: []planmodifier.Map{
mapplanmodifier.UseStateForUnknown(),
},
},
"config_object": schema.ObjectAttribute{
AttributeTypes: map[string]attr.Type{
"nested_string": types.StringType,
},
Required: true,
},
"computed_object": schema.ObjectAttribute{
AttributeTypes: map[string]attr.Type{
"nested_string": types.StringType,
},
Computed: true,
PlanModifiers: []planmodifier.Object{
objectplanmodifier.UseStateForUnknown(),
},
},
"config_string": schema.StringAttribute{
Required: true,
},
"computed_string": schema.StringAttribute{
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
},
Blocks: map[string]schema.Block{
"config_set_nested_block": schema.SetNestedBlock{
NestedObject: schema.NestedBlockObject{
Attributes: map[string]schema.Attribute{
"nested_string": schema.StringAttribute{
Required: true,
},
},
},
},
"computed_list_nested_block": schema.ListNestedBlock{
NestedObject: schema.NestedBlockObject{
Attributes: map[string]schema.Attribute{
"nested_string": schema.StringAttribute{
Computed: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.UseStateForUnknown(),
},
},
},
},
},
},
}
}

func (r TFSDKReflectionResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var data TFSDKReflectionResourceModel

resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

data.ComputedBool = types.BoolValue(true)
data.ComputedDynamic = types.DynamicValue(types.StringValue("dynamic string"))
data.ComputedFloat64 = types.Float64Value(1.2)
data.ComputedInt64 = types.Int64Value(100)
data.ComputedString = types.StringValue("computed string")

data.ComputedList = types.ListValueMust(
types.StringType,
[]attr.Value{
types.StringValue("computed"),
types.StringValue("list"),
},
)
data.ComputedMap = types.MapValueMust(
types.StringType,
map[string]attr.Value{
"key6": types.StringValue("val6"),
"key7": types.StringValue("val7"),
},
)

data.ComputedObject = types.ObjectValueMust(
nestedObjType.AttrTypes,
map[string]attr.Value{
"nested_string": types.StringValue("computed string"),
},
)

data.ComputedListNestedBlock = types.ListValueMust(
nestedObjType,
[]attr.Value{
types.ObjectValueMust(
nestedObjType.AttrTypes,
map[string]attr.Value{
"nested_string": types.StringValue("computed string one"),
},
),
types.ObjectValueMust(
nestedObjType.AttrTypes,
map[string]attr.Value{
"nested_string": types.StringValue("computed string two"),
},
),
},
)

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r TFSDKReflectionResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var data TFSDKReflectionResourceModel

resp.Diagnostics.Append(req.State.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r TFSDKReflectionResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var data TFSDKReflectionResourceModel

resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)

if resp.Diagnostics.HasError() {
return
}

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

func (r TFSDKReflectionResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
}

type TFSDKReflectionResourceModel struct {
ConfigDynamic types.Dynamic `tfsdk:"config_dynamic"`
ComputedDynamic types.Dynamic `tfsdk:"computed_dynamic"`

primitiveAttrs
CollectionAttrs
objectAttrs
CollectionBlocks

ExplicitIgnore string `tfsdk:"-"`
implicitIgnore string //nolint
*EmbedIgnore `tfsdk:"-"`
embedIgnore `tfsdk:"-"`
}

type embedIgnore struct {
Field1 string
}

type EmbedIgnore struct {
Field2 string
}

type primitiveAttrs struct {
ConfigBool *bool `tfsdk:"config_bool"`
ComputedBool types.Bool `tfsdk:"computed_bool"`

ConfigFloat64 *float64 `tfsdk:"config_float64"`
ComputedFloat64 types.Float64 `tfsdk:"computed_float64"`

ConfigInt64 *int64 `tfsdk:"config_int64"`
ComputedInt64 types.Int64 `tfsdk:"computed_int64"`

ConfigString *string `tfsdk:"config_string"`
ComputedString types.String `tfsdk:"computed_string"`

ExplicitIgnore string `tfsdk:"-"`
implicitIgnore string //nolint
}

type CollectionAttrs struct {
ConfigList []string `tfsdk:"config_list"`
ComputedList types.List `tfsdk:"computed_list"`

MapAttrs

ExplicitIgnore string `tfsdk:"-"`
implicitIgnore string //nolint
}

type MapAttrs struct {
ConfigMap map[string]string `tfsdk:"config_map"`
ComputedMap types.Map `tfsdk:"computed_map"`

ExplicitIgnore string `tfsdk:"-"`
implicitIgnore string //nolint
}

type objectAttrs struct {
ConfigObject types.Object `tfsdk:"config_object"`
ComputedObject types.Object `tfsdk:"computed_object"`

ExplicitIgnore string `tfsdk:"-"`
implicitIgnore string //nolint
}

type CollectionBlocks struct {
setBlock
listBlock

ExplicitIgnore string `tfsdk:"-"`
implicitIgnore string //nolint
}

type setBlock struct {
ConfigSetNestedBlock types.Set `tfsdk:"config_set_nested_block"`

ExplicitIgnore string `tfsdk:"-"`
implicitIgnore string //nolint
}
type listBlock struct {
ComputedListNestedBlock types.List `tfsdk:"computed_list_nested_block"`

ExplicitIgnore string `tfsdk:"-"`
implicitIgnore string //nolint
}
Loading

0 comments on commit 6d5f218

Please sign in to comment.