Skip to content

Commit 95d37ea

Browse files
committed
helper/schema,terraform: handle computed primtives in diffs
Fixes hashicorp#3309 There are two primary changes, one to how helper/schema creates diffs and one to how Terraform compares diffs. Both require careful understanding. == 1. helper/schema Changes helper/schema, given any primitive field (string, int, bool, etc.) _used to_ create a basic diff when given a computed new value (i.e. from an unkown interpolation). This would put in the plan that the old value is whatever the old value was, and the new value was the actual interpolation. For example, from hashicorp#3309, the diff showed the following: ``` ~ module.test.aws_eip.test-instance.0 instance: "<INSTANCE ID>" => "${element(aws_instance.test-instance.*.id, count.index)}" ``` Then, when running `apply`, the diff would be realized and you would get a diff mismatch error because it would realize the final value is the same and remove it from the diff. **The change:** `helper/schema` now marks unknown primitive values with `NewComputed` set to true. Semantically this is correct for the diff to have this information. == 2. Terraform Diff.Same Changes Next, the way Terraform compares diffs needed to be updated Specifically, the case where the diff from the plan had a NewComputed primitive and the diff from the apply _no longer has that value_. This is possible if the computed value ended up being the same as the old value. This is allowed to pass through. Together, these fix hashicorp#3309.
1 parent 836d171 commit 95d37ea

4 files changed

Lines changed: 61 additions & 10 deletions

File tree

‎helper/schema/schema.go‎

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -995,7 +995,7 @@ func (m schemaMap) diffString(
995995
all bool) error {
996996
var originalN interface{}
997997
var os, ns string
998-
o, n, _, _ := d.diffChange(k)
998+
o, n, _, computed := d.diffChange(k)
999999
if schema.StateFunc != nil && n != nil {
10001000
originalN = n
10011001
n = schema.StateFunc(n)
@@ -1019,7 +1019,7 @@ func (m schemaMap) diffString(
10191019
}
10201020

10211021
// Otherwise, only continue if we're computed
1022-
if !schema.Computed {
1022+
if !schema.Computed && !computed {
10231023
return nil
10241024
}
10251025
}
@@ -1033,10 +1033,11 @@ func (m schemaMap) diffString(
10331033
}
10341034

10351035
diff.Attributes[k] = schema.finalizeDiff(&terraform.ResourceAttrDiff{
1036-
Old: os,
1037-
New: ns,
1038-
NewExtra: originalN,
1039-
NewRemoved: removed,
1036+
Old: os,
1037+
New: ns,
1038+
NewExtra: originalN,
1039+
NewRemoved: removed,
1040+
NewComputed: computed,
10401041
})
10411042

10421043
return nil

‎helper/schema/schema_test.go‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -439,8 +439,9 @@ func TestSchemaMap_Diff(t *testing.T) {
439439
Diff: &terraform.InstanceDiff{
440440
Attributes: map[string]*terraform.ResourceAttrDiff{
441441
"availability_zone": &terraform.ResourceAttrDiff{
442-
Old: "",
443-
New: "${var.foo}",
442+
Old: "",
443+
New: "${var.foo}",
444+
NewComputed: true,
444445
},
445446
},
446447
},
@@ -1675,8 +1676,9 @@ func TestSchemaMap_Diff(t *testing.T) {
16751676
New: "1",
16761677
},
16771678
"route.~1.gateway": &terraform.ResourceAttrDiff{
1678-
Old: "",
1679-
New: "${var.foo}",
1679+
Old: "",
1680+
New: "${var.foo}",
1681+
NewComputed: true,
16801682
},
16811683
},
16821684
},

‎terraform/diff.go‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,13 @@ func (d *InstanceDiff) Same(d2 *InstanceDiff) (bool, string) {
603603
continue
604604
}
605605

606+
// If the last diff was a computed value then the absense of
607+
// that value is allowed since it may mean the value ended up
608+
// being the same.
609+
if diffOld.NewComputed {
610+
continue
611+
}
612+
606613
// No exact match, but maybe this is a set containing computed
607614
// values. So check if there is an approximate hash in the key
608615
// and if so, try to match the key.

‎terraform/diff_test.go‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,47 @@ func TestInstanceDiffSame(t *testing.T) {
553553
"diff RequiresNew; old: true, new: false",
554554
},
555555

556+
// NewComputed on primitive
557+
{
558+
&InstanceDiff{
559+
Attributes: map[string]*ResourceAttrDiff{
560+
"foo": &ResourceAttrDiff{
561+
Old: "",
562+
New: "${var.foo}",
563+
NewComputed: true,
564+
},
565+
},
566+
},
567+
&InstanceDiff{
568+
Attributes: map[string]*ResourceAttrDiff{
569+
"foo": &ResourceAttrDiff{
570+
Old: "0",
571+
New: "1",
572+
},
573+
},
574+
},
575+
true,
576+
"",
577+
},
578+
579+
// NewComputed on primitive, removed
580+
{
581+
&InstanceDiff{
582+
Attributes: map[string]*ResourceAttrDiff{
583+
"foo": &ResourceAttrDiff{
584+
Old: "",
585+
New: "${var.foo}",
586+
NewComputed: true,
587+
},
588+
},
589+
},
590+
&InstanceDiff{
591+
Attributes: map[string]*ResourceAttrDiff{},
592+
},
593+
true,
594+
"",
595+
},
596+
556597
{
557598
&InstanceDiff{
558599
Attributes: map[string]*ResourceAttrDiff{

0 commit comments

Comments
 (0)