terraform-plugin-framework icon indicating copy to clipboard operation
terraform-plugin-framework copied to clipboard

Multiple computed BoolAttributes with defaults in SetNestedAttribute cause flip-flopping plan on every apply

Open henryrecker-pingidentity opened this issue 1 year ago • 2 comments

Module version

1.4.2

Relevant provider source code

func (r *setNestedExampleResource) 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{
						"name": schema.StringAttribute{
							Required: true,
						},
						"bool_one": schema.BoolAttribute{
							Optional: true,
							Computed: true,
							Default:  booldefault.StaticBool(false),
						},
						"bool_two": schema.BoolAttribute{
							Optional: true,
							Computed: true,
							Default:  booldefault.StaticBool(false),
						},
					},
				},
			},
		},
	}
}

func (r *setNestedExampleResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
	resp.State.Raw = req.Plan.Raw
}

func (r *setNestedExampleResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
	resp.State.Raw = req.State.Raw
}

func (r *setNestedExampleResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
	resp.State.Raw = req.Plan.Raw
}

Terraform Configuration Files

resource "example_set_nested_example" "myExample" {
  set = [
    {
      name = "test2"
      bool_two = true
    }
  ]
}

Debug Output

Expected Behavior

The provider would not produce any plan after the first apply.

Actual Behavior

The first apply succeeds, and everything looks right in the state. On every subsequent apply, the generated plan flips the bool_two value to its opposite value.

First plan for example:

# example_set_nested_example.myExample will be created
  + resource "example_set_nested_example" "myExample" {
      + set = [
          + {
              + bool_one = false
              + bool_two = true
              + name     = "test2"
            },
        ]
    }

Second plan with no changes to HCL:

# example_set_nested_example.myExample will be updated in-place
  ~ resource "example_set_nested_example" "myExample" {
      ~ set = [
          - {
              - bool_one = false -> null
              - bool_two = true -> null
              - name     = "test2" -> null
            },
          + {
              + bool_one = false
              + bool_two = false
              + name     = "test2"
            },
        ]
    }

Third plan:

# example_set_nested_example.myExample will be updated in-place
  ~ resource "example_set_nested_example" "myExample" {
      ~ set = [
          - {
              - bool_one = false -> null
              - bool_two = false -> null
              - name     = "test2" -> null
            },
          + {
              + bool_one = false
              + bool_two = true
              + name     = "test2"
            },
        ]
    }

The plans will continue to cycle between setting bool_two to true and to false.

Steps to Reproduce

Apply the provided HCL multiple times

I believe this bug report is a different result of a similar root cause from #783 and #709, a known issue with Set identity and plan modification (default values).

austinvalle avatar Oct 30 '23 14:10 austinvalle

I have been bitten by this. My workaround was to re-implement the defaults using a custom plan modifier on the set. I'll subscribe to this in hopes of removing that horrible cludge.

See https://github.com/thiagoarrais/terraform-provider-twoflag-issue-example/commit/adacdb6daedd397115128741321fe7eec0937fea

thiagoarrais avatar Nov 16 '23 20:11 thiagoarrais