mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-29 10:21:01 -06:00
9d19086c8e
Add a test to ensure ignore_changes does not change null maps to empty maps. Fix when a marked map revers the changes ignored within that map.
444 lines
12 KiB
Go
444 lines
12 KiB
Go
package terraform
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/hashicorp/hcl/v2"
|
|
"github.com/hashicorp/hcl/v2/hclsyntax"
|
|
"github.com/zclconf/go-cty/cty"
|
|
)
|
|
|
|
func TestProcessIgnoreChangesIndividual(t *testing.T) {
|
|
tests := map[string]struct {
|
|
Old, New cty.Value
|
|
Ignore []string
|
|
Want cty.Value
|
|
}{
|
|
"string": {
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.StringVal("a value"),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.StringVal("new a value"),
|
|
"b": cty.StringVal("new b value"),
|
|
}),
|
|
[]string{"a"},
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.StringVal("a value"),
|
|
"b": cty.StringVal("new b value"),
|
|
}),
|
|
},
|
|
"changed type": {
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.StringVal("a value"),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.NumberIntVal(1),
|
|
"b": cty.StringVal("new b value"),
|
|
}),
|
|
[]string{"a"},
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.StringVal("a value"),
|
|
"b": cty.StringVal("new b value"),
|
|
}),
|
|
},
|
|
"list": {
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.ListVal([]cty.Value{
|
|
cty.StringVal("a0 value"),
|
|
cty.StringVal("a1 value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.ListVal([]cty.Value{
|
|
cty.StringVal("new a0 value"),
|
|
cty.StringVal("new a1 value"),
|
|
}),
|
|
"b": cty.StringVal("new b value"),
|
|
}),
|
|
[]string{"a"},
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.ListVal([]cty.Value{
|
|
cty.StringVal("a0 value"),
|
|
cty.StringVal("a1 value"),
|
|
}),
|
|
"b": cty.StringVal("new b value"),
|
|
}),
|
|
},
|
|
"list_index": {
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.ListVal([]cty.Value{
|
|
cty.StringVal("a0 value"),
|
|
cty.StringVal("a1 value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.ListVal([]cty.Value{
|
|
cty.StringVal("new a0 value"),
|
|
cty.StringVal("new a1 value"),
|
|
}),
|
|
"b": cty.StringVal("new b value"),
|
|
}),
|
|
[]string{"a[1]"},
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.ListVal([]cty.Value{
|
|
cty.StringVal("new a0 value"),
|
|
cty.StringVal("a1 value"),
|
|
}),
|
|
"b": cty.StringVal("new b value"),
|
|
}),
|
|
},
|
|
"map": {
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a0": cty.StringVal("a0 value"),
|
|
"a1": cty.StringVal("a1 value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a0": cty.StringVal("new a0 value"),
|
|
"a1": cty.UnknownVal(cty.String),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
[]string{`a`},
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a0": cty.StringVal("a0 value"),
|
|
"a1": cty.StringVal("a1 value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
},
|
|
"map_index": {
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a0": cty.StringVal("a0 value"),
|
|
"a1": cty.StringVal("a1 value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a0": cty.StringVal("new a0 value"),
|
|
"a1": cty.StringVal("new a1 value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
[]string{`a["a1"]`},
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a0": cty.StringVal("new a0 value"),
|
|
"a1": cty.StringVal("a1 value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
},
|
|
"map_index_no_config": {
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a0": cty.StringVal("a0 value"),
|
|
"a1": cty.StringVal("a1 value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.NullVal(cty.Map(cty.String)),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
[]string{`a["a1"]`},
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a1": cty.StringVal("a1 value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
},
|
|
"map_index_unknown_value": {
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a0": cty.StringVal("a0 value"),
|
|
"a1": cty.StringVal("a1 value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a0": cty.StringVal("a0 value"),
|
|
"a1": cty.UnknownVal(cty.String),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
[]string{`a["a1"]`},
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a0": cty.StringVal("a0 value"),
|
|
"a1": cty.StringVal("a1 value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
},
|
|
"map_index_multiple_keys": {
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a0": cty.StringVal("a0 value"),
|
|
"a1": cty.StringVal("a1 value"),
|
|
"a2": cty.StringVal("a2 value"),
|
|
"a3": cty.StringVal("a3 value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.NullVal(cty.Map(cty.String)),
|
|
"b": cty.StringVal("new b value"),
|
|
}),
|
|
[]string{`a["a1"]`, `a["a2"]`, `a["a3"]`, `b`},
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a1": cty.StringVal("a1 value"),
|
|
"a2": cty.StringVal("a2 value"),
|
|
"a3": cty.StringVal("a3 value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
},
|
|
"map_index_redundant": {
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a0": cty.StringVal("a0 value"),
|
|
"a1": cty.StringVal("a1 value"),
|
|
"a2": cty.StringVal("a2 value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.NullVal(cty.Map(cty.String)),
|
|
"b": cty.StringVal("new b value"),
|
|
}),
|
|
[]string{`a["a1"]`, `a`, `b`},
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a0": cty.StringVal("a0 value"),
|
|
"a1": cty.StringVal("a1 value"),
|
|
"a2": cty.StringVal("a2 value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
},
|
|
"missing_map_index": {
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a0": cty.StringVal("a0 value"),
|
|
"a1": cty.StringVal("a1 value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapValEmpty(cty.String),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
[]string{`a["a1"]`},
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a1": cty.StringVal("a1 value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
},
|
|
"missing_map_index_empty": {
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapValEmpty(cty.String),
|
|
}),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a": cty.StringVal("a0 value"),
|
|
}),
|
|
}),
|
|
[]string{`a["a"]`},
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapValEmpty(cty.String),
|
|
}),
|
|
},
|
|
"missing_map_index_to_object": {
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a": cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.StringVal("aa0"),
|
|
"b": cty.StringVal("ab0"),
|
|
}),
|
|
"b": cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.StringVal("ba0"),
|
|
"b": cty.StringVal("bb0"),
|
|
}),
|
|
}),
|
|
}),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapValEmpty(
|
|
cty.Object(map[string]cty.Type{
|
|
"a": cty.String,
|
|
"b": cty.String,
|
|
}),
|
|
),
|
|
}),
|
|
// we expect the config to be used here, as the ignore changes was
|
|
// `a["a"].b`, but the change was larger than that removing
|
|
// `a["a"]` entirely.
|
|
[]string{`a["a"].b`},
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapValEmpty(
|
|
cty.Object(map[string]cty.Type{
|
|
"a": cty.String,
|
|
"b": cty.String,
|
|
}),
|
|
),
|
|
}),
|
|
},
|
|
"missing_prior_map_index": {
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a0": cty.StringVal("a0 value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a0": cty.StringVal("a0 value"),
|
|
"a1": cty.StringVal("new a1 value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
[]string{`a["a1"]`},
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.MapVal(map[string]cty.Value{
|
|
"a0": cty.StringVal("a0 value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
},
|
|
"object attribute": {
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.ObjectVal(map[string]cty.Value{
|
|
"foo": cty.StringVal("a.foo value"),
|
|
"bar": cty.StringVal("a.bar value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.ObjectVal(map[string]cty.Value{
|
|
"foo": cty.StringVal("new a.foo value"),
|
|
"bar": cty.StringVal("new a.bar value"),
|
|
}),
|
|
"b": cty.StringVal("new b value"),
|
|
}),
|
|
[]string{"a.bar"},
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.ObjectVal(map[string]cty.Value{
|
|
"foo": cty.StringVal("new a.foo value"),
|
|
"bar": cty.StringVal("a.bar value"),
|
|
}),
|
|
"b": cty.StringVal("new b value"),
|
|
}),
|
|
},
|
|
"unknown_object_attribute": {
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.ObjectVal(map[string]cty.Value{
|
|
"foo": cty.StringVal("a.foo value"),
|
|
"bar": cty.StringVal("a.bar value"),
|
|
}),
|
|
"b": cty.StringVal("b value"),
|
|
}),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.ObjectVal(map[string]cty.Value{
|
|
"foo": cty.StringVal("new a.foo value"),
|
|
"bar": cty.UnknownVal(cty.String),
|
|
}),
|
|
"b": cty.StringVal("new b value"),
|
|
}),
|
|
[]string{"a.bar"},
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.ObjectVal(map[string]cty.Value{
|
|
"foo": cty.StringVal("new a.foo value"),
|
|
"bar": cty.StringVal("a.bar value"),
|
|
}),
|
|
"b": cty.StringVal("new b value"),
|
|
}),
|
|
},
|
|
"null_map": {
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.StringVal("ok"),
|
|
"list": cty.ListVal([]cty.Value{
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"s": cty.StringVal("ok"),
|
|
"map": cty.NullVal(cty.Map(cty.String)),
|
|
}),
|
|
}),
|
|
}),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.NullVal(cty.String),
|
|
"list": cty.ListVal([]cty.Value{
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"s": cty.StringVal("ok"),
|
|
"map": cty.NullVal(cty.Map(cty.String)),
|
|
}),
|
|
}),
|
|
}),
|
|
[]string{"a"},
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"a": cty.StringVal("ok"),
|
|
"list": cty.ListVal([]cty.Value{
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"s": cty.StringVal("ok"),
|
|
"map": cty.NullVal(cty.Map(cty.String)),
|
|
}),
|
|
}),
|
|
}),
|
|
},
|
|
"marked_map": {
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"map": cty.MapVal(map[string]cty.Value{
|
|
"key": cty.StringVal("val"),
|
|
}).Mark("marked"),
|
|
}),
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"map": cty.MapVal(map[string]cty.Value{
|
|
"key": cty.StringVal("new val"),
|
|
}).Mark("marked"),
|
|
}),
|
|
[]string{`map["key"]`},
|
|
cty.ObjectVal(map[string]cty.Value{
|
|
"map": cty.MapVal(map[string]cty.Value{
|
|
"key": cty.StringVal("val"),
|
|
}).Mark("marked"),
|
|
}),
|
|
},
|
|
}
|
|
|
|
for name, test := range tests {
|
|
t.Run(name, func(t *testing.T) {
|
|
ignore := make([]hcl.Traversal, len(test.Ignore))
|
|
for i, ignoreStr := range test.Ignore {
|
|
trav, diags := hclsyntax.ParseTraversalAbs([]byte(ignoreStr), "", hcl.Pos{Line: 1, Column: 1})
|
|
if diags.HasErrors() {
|
|
t.Fatalf("failed to parse %q: %s", ignoreStr, diags.Error())
|
|
}
|
|
ignore[i] = trav
|
|
}
|
|
|
|
ret, diags := processIgnoreChangesIndividual(test.Old, test.New, traversalsToPaths(ignore))
|
|
if diags.HasErrors() {
|
|
t.Fatal(diags.Err())
|
|
}
|
|
|
|
if got, want := ret, test.Want; !want.RawEquals(got) {
|
|
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, want)
|
|
}
|
|
})
|
|
}
|
|
}
|