lang/marks: MarkPaths helper function

This helper is a slightly more convenient wrapper around cty's own
"MarkWithPaths" function that applies a single given mark at zero or more
paths in a given value.

In several parts of Terraform we preserve sensitive marks in particular
for serialization and cannot preserve anything else, and so this helper
is useful for reapplying the saved sensitive paths back to the stored
value during decoding.
testing-renovate
Martin Atkins 2 years ago
parent 2334fc867c
commit b5a4860a36

@ -36,3 +36,27 @@ func PathsWithMark(pvms []cty.PathValueMarks, wantMark any) (withWanted []cty.Pa
return withWanted, withOthers
}
// MarkPaths transforms the given value by marking each of the given paths
// with the given mark value.
func MarkPaths(val cty.Value, mark any, paths []cty.Path) cty.Value {
if len(paths) == 0 {
// No-allocations path for the common case where there are no marked paths at all.
return val
}
// For now we'll use cty's slightly lower-level function to achieve this
// result. This is a little inefficient due to an additional dynamic
// allocation for the intermediate data structure, so if that becomes
// a problem in practice then we may wish to write a more direct
// implementation here.
markses := make([]cty.PathValueMarks, len(paths))
marks := cty.NewValueMarks(mark)
for i, path := range paths {
markses[i] = cty.PathValueMarks{
Path: path,
Marks: marks,
}
}
return val.MarkWithPaths(markses)
}

@ -56,3 +56,55 @@ func TestPathsWithMark(t *testing.T) {
t.Errorf("wrong set of entries with other marks\n%s", diff)
}
}
func TestMarkPaths(t *testing.T) {
value := cty.ObjectVal(map[string]cty.Value{
"s": cty.StringVal(".s"),
"l": cty.ListVal([]cty.Value{
cty.StringVal(".l[0]"),
cty.StringVal(".l[1]"),
}),
"m": cty.MapVal(map[string]cty.Value{
"a": cty.StringVal(`.m["a"]`),
"b": cty.StringVal(`.m["b"]`),
}),
"o": cty.ObjectVal(map[string]cty.Value{
"a": cty.StringVal(".o.a"),
"b": cty.StringVal(".o.b"),
}),
"t": cty.TupleVal([]cty.Value{
cty.StringVal(`.t[0]`),
cty.StringVal(`.t[1]`),
}),
})
sensitivePaths := []cty.Path{
cty.GetAttrPath("s"),
cty.GetAttrPath("l").IndexInt(1),
cty.GetAttrPath("m").IndexString("a"),
cty.GetAttrPath("o").GetAttr("b"),
cty.GetAttrPath("t").IndexInt(0),
}
got := MarkPaths(value, Sensitive, sensitivePaths)
want := cty.ObjectVal(map[string]cty.Value{
"s": cty.StringVal(".s").Mark(Sensitive),
"l": cty.ListVal([]cty.Value{
cty.StringVal(".l[0]"),
cty.StringVal(".l[1]").Mark(Sensitive),
}),
"m": cty.MapVal(map[string]cty.Value{
"a": cty.StringVal(`.m["a"]`).Mark(Sensitive),
"b": cty.StringVal(`.m["b"]`),
}),
"o": cty.ObjectVal(map[string]cty.Value{
"a": cty.StringVal(".o.a"),
"b": cty.StringVal(".o.b").Mark(Sensitive),
}),
"t": cty.TupleVal([]cty.Value{
cty.StringVal(`.t[0]`).Mark(Sensitive),
cty.StringVal(`.t[1]`),
}),
})
if diff := cmp.Diff(want, got, ctydebug.CmpOptions); diff != "" {
t.Errorf("wrong result\n%s", diff)
}
}

Loading…
Cancel
Save