hashicorp / hashicorp/terraform-plugin-sdk

CustomizeDiff using ForceNewIfChange on TypeSet Configuration Block Reporting Inconsistent Plan

Open
#151 7 comments 0 reactions 0 assignees View on GitHub
bug subsystem/types
Dominant language
Go
Stars
485
Forks
244
Avg merge
19h 57m
Merged PRs (30d)
4

Description

### Terraform Version

```
# go.mod
github.com/hashicorp/terraform v0.12.0-beta2
```

### Terraform Resource Files

In the Terraform AWS Provider:

```go
# aws/resource_aws_route53_zone.go (inside &schema.Resource)

CustomizeDiff: customdiff.All(
customdiff.ForceNewIfChange("vpc", func(old, new, meta interface{}) bool {
// "vpc" can only be in-place updated if already specified
return old.(*schema.Set).Len() == 0 || new.(*schema.Set).Len() == 0
}),
),

# aws/resource_aws_route53_zone_test.go

// Reference: https://github.com/terraform-providers/terraform-provider-aws/issues/7614
func TestAccAWSRoute53Zone_VPC_ForceNewIfChange(t *testing.T) {
var zone1, zone2, zone3 route53.GetHostedZoneOutput

rName := acctest.RandomWithPrefix("tf-acc-test")
resourceName := "aws_route53_zone.test"
vpcResourceName := "aws_vpc.test1"
zoneName := fmt.Sprintf("%s.terraformtest.com", rName)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckRoute53ZoneDestroy,
Steps: []resource.TestStep{
{
Config: testAccRoute53ZoneConfig(zoneName),
Check: resource.ComposeTestCheckFunc(
testAccCheckRoute53ZoneExists(resourceName, &zone1),
resource.TestCheckResourceAttr(resourceName, "vpc.#", "0"),
),
},
{
Config: testAccRoute53ZoneConfigVPCSingle(rName, zoneName),
Check: resource.ComposeTestCheckFunc(
testAccCheckRoute53ZoneExists(resourceName, &zone2),
resource.TestCheckResourceAttr(resourceName, "vpc.#", "1"),
testAccCheckRoute53ZoneAssociatesWithVpc(vpcResourceName, &zone2),
),
},
{
Config: testAccRoute53ZoneConfig(zoneName),
Check: resource.ComposeTestCheckFunc(
testAccCheckRoute53ZoneExists(resourceName, &zone3),
resource.TestCheckResourceAttr(resourceName, "vpc.#", "0"),
),
},
},
})
}

```

### Expected Behavior

Terraform Provider SDK marks resource for recreation when going from 0 `vpc` configuration blocks to greater than 0 configuration blocks or vice versa.

### Actual Behavior

```
--- FAIL: TestAccAWSRoute53Zone_VPC_ForceNewIfChange (55.58s)
testing.go:568: Step 1 error: errors during apply:

Error: Provider produced inconsistent final plan

When expanding the plan for aws_route53_zone.test to include new values
learned so far during apply, provider "aws" produced an invalid new value for
.vpc: planned set element cty.Value{ty:
cty.Object(map[string]cty.Type{"vpc_id":cty.String, "vpc_region":cty.String}),
v: map[string]interface {}{"vpc_id":"", "vpc_region":cty.unknown}} does not
correlate with any element in actual.

This is a bug in the provider, which should be reported in the provider's own
issue tracker.
```

### Steps to Reproduce

1. `TF_ACC=1 go test ./aws -v -timeout 120m -run='TestAccAWSRoute53Zone_VPC_ForceNewIfChange'`

### Additional Context

This was originally tried with the Terraform 0.11 Provider SDK a few months back, which yielded the previous iteration of this error:

```
--- FAIL: TestAccAWSRoute53Zone_VPC_ForceNewIfChange (52.34s)
testing.go:538: Step 1 error: Error applying: 1 error occurred:
* aws_route53_zone.test: aws_route53_zone.test: diffs didn't match during apply. This is a bug with Terraform and should be reported as a GitHub Issue.

Please include the following information in your report:

Terraform Version: 0.11.9
Resource ID: aws_route53_zone.test
Mismatch reason: attribute mismatch: vpc.2118463170.vpc_id
Diff One (usually from plan): *terraform.InstanceDiff{mu:sync.Mutex{state:0, sema:0x0}, Attributes:map[string]*terraform.ResourceAttrDiff{"name_servers.#":*terraform.ResourceAttrDiff{Old:"4", New:"", NewComputed:true, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}, "vpc.~2118463170.vpc_region":*terraform.ResourceAttrDiff{Old:"", New:"", NewComputed:true, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}, "vpc.2118463170.vpc_id":*terraform.ResourceAttrDiff{Old:"", New:"", NewComputed:false, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}, "vpc.2118463170.vpc_region":*terraform.ResourceAttrDiff{Old:"", New:"", NewComputed:true, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}, "force_destroy":*terraform.ResourceAttrDiff{Old:"false", New:"false", NewComputed:false, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}, "name":*terraform.ResourceAttrDiff{Old:"tf-acc-test-6356618791358131134.terraformtest.com.", New:"tf-acc-test-6356618791358131134.terraformtest.com.", NewComputed:false, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}, "comment":*terraform.ResourceAttrDiff{Old:"Managed by Terraform", New:"Managed by Terraform", NewComputed:false, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}, "vpc.#":*terraform.ResourceAttrDiff{Old:"0", New:"1", NewComputed:false, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:true, Sensitive:false, Type:0x0}, "vpc.~2118463170.vpc_id":*terraform.ResourceAttrDiff{Old:"", New:"${aws_vpc.test1.id}", NewComputed:true, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}, "zone_id":*terraform.ResourceAttrDiff{Old:"Z1AT08GB5RV06G", New:"", NewComputed:true, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}}, Destroy:false, DestroyDeposed:false, DestroyTainted:false, Meta:map[string]interface {}(nil)}
Diff Two (usually from apply): *terraform.InstanceDiff{mu:sync.Mutex{state:0, sema:0x0}, Attributes:map[string]*terraform.ResourceAttrDiff{"vpc.#":*terraform.ResourceAttrDiff{Old:"", New:"1", NewComputed:false, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:true, Sensitive:false, Type:0x0}, "zone_id":*terraform.ResourceAttrDiff{Old:"", New:"", NewComputed:true, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}, "name":*terraform.ResourceAttrDiff{Old:"", New:"tf-acc-test-6356618791358131134.terraformtest.com.", NewComputed:false, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:true, Sensitive:false, Type:0x0}, "comment":*terraform.ResourceAttrDiff{Old:"", New:"Managed by Terraform", NewComputed:false, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}, "vpc.3803688031.vpc_region":*terraform.ResourceAttrDiff{Old:"", New:"", NewComputed:true, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}, "vpc.3803688031.vpc_id":*terraform.ResourceAttrDiff{Old:"", New:"vpc-0406819a6dadcf2a0", NewComputed:false, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}, "name_servers.#":*terraform.ResourceAttrDiff{Old:"", New:"", NewComputed:true, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}, "force_destroy":*terraform.ResourceAttrDiff{Old:"", New:"false", NewComputed:false, NewRemoved:false, NewExtra:interface {}(nil), RequiresNew:false, Sensitive:false, Type:0x0}}, Destroy:false, DestroyDeposed:false, DestroyTainted:false, Meta:map[string]interface {}(nil)}

Also include as much context as you can about your config, state, and the steps you performed to trigger this error.
```

### References

- https://github.com/terraform-providers/terraform-provider-aws/issues/7614

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.