-
Notifications
You must be signed in to change notification settings - Fork 99
Open
Labels
bugSomething isn't workingSomething isn't working
Description
Module version
v1.3.1
Relevant provider source code
This is the entire source code of a single .go file provider that demonstrates the issues:
package main
import (
"context"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/provider"
"github.com/hashicorp/terraform-plugin-framework/providerserver"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
)
func main() {
err := providerserver.Serve(
context.Background(),
func() provider.Provider {
return new(bugProvider)
},
providerserver.ServeOpts{
Address: "bug/bug/bug",
},
)
if err != nil {
panic(err)
}
}
type bugProvider struct{}
func (p *bugProvider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) {
resp.TypeName = "bug"
}
func (p *bugProvider) Schema(ctx context.Context, req provider.SchemaRequest, resp *provider.SchemaResponse) {
}
func (p *bugProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
}
func (p *bugProvider) DataSources(ctx context.Context) []func() datasource.DataSource {
return nil
}
func (p *bugProvider) Resources(ctx context.Context) []func() resource.Resource {
return []func() resource.Resource{
func() resource.Resource {
return new(bugResource)
},
}
}
type bugResource struct{}
func (r bugResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_bug"
}
func (r bugResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"set": schema.SetNestedAttribute{
Required: true,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"fruit": schema.StringAttribute{
Optional: true,
Computed: true,
Default: stringdefault.StaticString("orange"),
},
"other": schema.StringAttribute{
Optional: true,
Computed: true,
Default: stringdefault.StaticString("other"),
},
},
},
},
},
}
}
func (r bugResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
}
func (r bugResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
resp.State.Raw = req.Plan.Raw
}
func (r bugResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
resp.State.Raw = req.Plan.Raw
}
func (r bugResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
}Terraform Configuration Files
terraform {
required_providers {
bug = {
source = "bug/bug/bug"
}
}
}
resource "bug_bug" "this" {
set = [
{ fruit = "apple" },
{ fruit = "banana" },
{ fruit = "kumquat" },
]
}Debug Output
https://gist.github.com/maxb/f0b606530531a1f7e89c1ac122f141da
Steps to Reproduce
- Copy the included provider source code to a file, add a
go.modincluding the latest version of terraform-plugin-framework (no other dependencies needed), build the provider. - Set up
dev_overridesso you can test the provider. - Copy the included Terraform configuration to a file
- Run
terraform apply -auto-approve(no initial state is needed) - Run
terraform apply -auto-approveagain ... the provider panics/crashes
Secondary related bug:
- Remove any
terraform.tfstatefrom the above reproduction - Reduce the number of items in the set in the Terraform configuration from 3 to 1
- Repeatedly run
terraform apply -auto-approve... observe that provider repeatedly changes the value back and forth on each run, oscillating between the value actually written in the configuration, and the value set as a default in the code.
Partial diagnosis
The terraform-plugin-framework appears to use a bafflingly complex algorithm to apply defaults, involving correlating the state and the configuration.
This is a victim of its own complexity when dealing with sets of objects, as the identity of an object within a set incorporates its own value ... a value that may itself have defaults. This means the identity of a set member in the config may omit unspecified attributes, whilst the identity of the same set member in the state will include unspecified attributes, now set to their default values.
austinvalle, henryrecker-pingidentity and azrod
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working