mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-13 00:46:16 -06:00
helper/schema: only mark "ForceNew" on resources that cause the ForceNew
Fixes #2748 This changes the diff to only mark "forces new resource" on the fields that actually caused the new resource, not every field that changed. This makes diffs much more accurate. I'd like to request a review but I'm going to defer merging until Terraform 0.8. Changes like this are very possible to cause "diffs didn't match" errors and I want some real world testing in a beta before we hit prod with this.
This commit is contained in:
parent
645d3271f6
commit
e45debe0e5
@ -288,9 +288,21 @@ func (s *Schema) finalizeDiff(
|
|||||||
d.New = normalizeBoolString(d.New)
|
d.New = normalizeBoolString(d.New)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.Computed && !d.NewRemoved && d.New == "" {
|
||||||
|
// Computed attribute without a new value set
|
||||||
|
d.NewComputed = true
|
||||||
|
}
|
||||||
|
|
||||||
if s.ForceNew {
|
if s.ForceNew {
|
||||||
// Force new, set it to true in the diff
|
// ForceNew, mark that this field is requiring new under the
|
||||||
d.RequiresNew = true
|
// following conditions, explained below:
|
||||||
|
//
|
||||||
|
// * Old != New - There is a change in value. This field
|
||||||
|
// is therefore causing a new resource.
|
||||||
|
//
|
||||||
|
// * NewComputed - This field is being computed, hence a
|
||||||
|
// potential change in value, mark as causing a new resource.
|
||||||
|
d.RequiresNew = d.Old != d.New || d.NewComputed
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.NewRemoved {
|
if d.NewRemoved {
|
||||||
|
@ -2341,9 +2341,8 @@ func TestSchemaMap_Diff(t *testing.T) {
|
|||||||
RequiresNew: true,
|
RequiresNew: true,
|
||||||
},
|
},
|
||||||
"instances.3": &terraform.ResourceAttrDiff{
|
"instances.3": &terraform.ResourceAttrDiff{
|
||||||
Old: "333",
|
Old: "333",
|
||||||
New: "333",
|
New: "333",
|
||||||
RequiresNew: true,
|
|
||||||
},
|
},
|
||||||
"instances.4": &terraform.ResourceAttrDiff{
|
"instances.4": &terraform.ResourceAttrDiff{
|
||||||
Old: "",
|
Old: "",
|
||||||
@ -2426,6 +2425,61 @@ func TestSchemaMap_Diff(t *testing.T) {
|
|||||||
Err: false,
|
Err: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"Set ForceNew only marks the changing element as ForceNew": {
|
||||||
|
Schema: map[string]*Schema{
|
||||||
|
"ports": &Schema{
|
||||||
|
Type: TypeSet,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
Elem: &Schema{Type: TypeInt},
|
||||||
|
Set: func(a interface{}) int {
|
||||||
|
return a.(int)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
State: &terraform.InstanceState{
|
||||||
|
Attributes: map[string]string{
|
||||||
|
"ports.#": "3",
|
||||||
|
"ports.1": "1",
|
||||||
|
"ports.2": "2",
|
||||||
|
"ports.4": "4",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
Config: map[string]interface{}{
|
||||||
|
"ports": []interface{}{5, 2, 1},
|
||||||
|
},
|
||||||
|
|
||||||
|
Diff: &terraform.InstanceDiff{
|
||||||
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
||||||
|
"ports.#": &terraform.ResourceAttrDiff{
|
||||||
|
Old: "3",
|
||||||
|
New: "3",
|
||||||
|
},
|
||||||
|
"ports.1": &terraform.ResourceAttrDiff{
|
||||||
|
Old: "1",
|
||||||
|
New: "1",
|
||||||
|
},
|
||||||
|
"ports.2": &terraform.ResourceAttrDiff{
|
||||||
|
Old: "2",
|
||||||
|
New: "2",
|
||||||
|
},
|
||||||
|
"ports.5": &terraform.ResourceAttrDiff{
|
||||||
|
Old: "",
|
||||||
|
New: "5",
|
||||||
|
RequiresNew: true,
|
||||||
|
},
|
||||||
|
"ports.4": &terraform.ResourceAttrDiff{
|
||||||
|
Old: "4",
|
||||||
|
New: "0",
|
||||||
|
NewRemoved: true,
|
||||||
|
RequiresNew: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
"removed optional items should trigger ForceNew": {
|
"removed optional items should trigger ForceNew": {
|
||||||
Schema: map[string]*Schema{
|
Schema: map[string]*Schema{
|
||||||
"description": &Schema{
|
"description": &Schema{
|
||||||
@ -2495,26 +2549,28 @@ func TestSchemaMap_Diff(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for tn, tc := range cases {
|
for tn, tc := range cases {
|
||||||
c, err := config.NewRawConfig(tc.Config)
|
t.Run(tn, func(t *testing.T) {
|
||||||
if err != nil {
|
c, err := config.NewRawConfig(tc.Config)
|
||||||
t.Fatalf("#%q err: %s", tn, err)
|
if err != nil {
|
||||||
}
|
|
||||||
|
|
||||||
if len(tc.ConfigVariables) > 0 {
|
|
||||||
if err := c.Interpolate(tc.ConfigVariables); err != nil {
|
|
||||||
t.Fatalf("#%q err: %s", tn, err)
|
t.Fatalf("#%q err: %s", tn, err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
d, err := schemaMap(tc.Schema).Diff(
|
if len(tc.ConfigVariables) > 0 {
|
||||||
tc.State, terraform.NewResourceConfig(c))
|
if err := c.Interpolate(tc.ConfigVariables); err != nil {
|
||||||
if err != nil != tc.Err {
|
t.Fatalf("#%q err: %s", tn, err)
|
||||||
t.Fatalf("#%q err: %s", tn, err)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(tc.Diff, d) {
|
d, err := schemaMap(tc.Schema).Diff(
|
||||||
t.Fatalf("#%q:\n\nexpected:\n%#v\n\ngot:\n%#v", tn, tc.Diff, d)
|
tc.State, terraform.NewResourceConfig(c))
|
||||||
}
|
if err != nil != tc.Err {
|
||||||
|
t.Fatalf("#%q err: %s", tn, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(tc.Diff, d) {
|
||||||
|
t.Fatalf("#%q:\n\nexpected:\n%#v\n\ngot:\n%#v", tn, tc.Diff, d)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user