Skip to content

Cannot write state to interface in generic func #1035

@JacobPotter

Description

@JacobPotter

Module version

github.com/hashicorp/terraform-plugin-framework v1.11.0

Relevant provider source code

SEE ACTUAL BEHAVIOR FOR EXAMPLES

Terraform Configuration Files

...

Debug Output

Expected Behavior

Actual Behavior

We are using an interface for our resource models that stores the state of a provider resource. This interface defines methods for converting data from API to TF and vice versa. For example:

We have an interface here:

type ResourceTransform[M any] interface {
	GetApiModelFromTfModel(context.Context) (M, diag.Diagnostics)
	GetTfModelFromApiModel(context.Context, M) diag.Diagnostics
}
type ResourceTransformWithID[M any] interface {
	GetID() int64
	ResourceTransform[M]
}

Which is implemented by the model below

type DynamicContentVariantModel struct {
	ID       types.Int64  `tfsdk:"id"`
	Content  types.String `tfsdk:"content"`
	LocaleID types.Int64  `tfsdk:"locale_id"`
	Active   types.Bool   `tfsdk:"active"`
	Default  types.Bool   `tfsdk:"default"`
}

type DynamicContentItemResourceModel struct {
	ID              types.Int64                  `tfsdk:"id"`
	Name            types.String                 `tfsdk:"name"`
	Placeholder     types.String                 `tfsdk:"placeholder"`
	DefaultLocaleID types.Int64                  `tfsdk:"default_locale_id"`
	Variants        []DynamicContentVariantModel `tfsdk:"variants"`
}

func (d *DynamicContentItemResourceModel) GetID() int64 {
	...
}

func (d *DynamicContentItemResourceModel) GetApiModelFromTfModel(_ context.Context) (dci zendesk.DynamicContentItem, diags diag.Diagnostics) {
      ...
}

func (d *DynamicContentItemResourceModel) GetTfModelFromApiModel(_ context.Context, dci zendesk.DynamicContentItem) (diags diag.Diagnostics) {
	...
}

If I try to use a generic function like this:

func CreateResource[M any](ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse, resourceModel ResourceTransformWithID[M], createFunc func(ctx context.Context, newResource M) (M, error)) {
	response.Diagnostics.Append(request.Plan.Get(ctx, &resourceModel)...)

	if response.Diagnostics.HasError() {
		return
	}
	newResource, diags := resourceModel.GetApiModelFromTfModel(ctx)

	response.Diagnostics.Append(diags...)

	if response.Diagnostics.HasError() {
		return
	}

	resp, err := createFunc(ctx, newResource)

	if err != nil {
		response.Diagnostics.AddError("Error creating resource", fmt.Sprintf("Error: %s", err))
		return
	}

	response.Diagnostics.Append(resourceModel.GetTfModelFromApiModel(ctx, resp)...)

	if response.Diagnostics.HasError() {
		return
	}

	response.Diagnostics.Append(response.State.Set(ctx, resourceModel)...)
}

I get the following error when trying to apply:

 Error: Value Conversion Error
        
          with zendesk_dynamic_content.test,
        An unexpected error was encountered trying to build a value. This is always
        an error in the provider. Please report the following to the provider
        developer:
        
        don't know how to reflect tftypes.Object["default_locale_id":tftypes.Number,
        "id":tftypes.Number, "name":tftypes.String, "placeholder":tftypes.String,
        "variants":tftypes.List[tftypes.Object["active":tftypes.Bool,
        "content":tftypes.String, "default":tftypes.Bool, "id":tftypes.Number,
        "locale_id":tftypes.Number]]] into
        models.ResourceTransformWithID[github.com/JacobPotter/go-zendesk/zendesk.DynamicContentItem]

It looks like request.Plan.Get is having an issue writing the state data into the model when using an interface.

Steps to Reproduce

  1. Write terraform plan/state data into model via interface

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions