check for unknowns when marking resource values

When we map schema sensitivity to resource values, there may be unknowns
when dealing with planned objects. Check for unknowns before iterating
over block values.
This commit is contained in:
James Bardin 2021-03-23 17:06:18 -04:00
parent 841cced6c9
commit 8cba2bfc39
2 changed files with 99 additions and 1 deletions

View File

@ -979,12 +979,17 @@ func getValMarks(schema *configschema.Block, val cty.Value, path cty.Path) []cty
if !blockS.Block.ContainsSensitive() { if !blockS.Block.ContainsSensitive() {
continue continue
} }
blockV := val.GetAttr(name)
if blockV.IsNull() || !blockV.IsKnown() {
continue
}
// Create a copy of the path, with this step added, to add to our PathValueMarks slice // Create a copy of the path, with this step added, to add to our PathValueMarks slice
blockPath := make(cty.Path, len(path), len(path)+1) blockPath := make(cty.Path, len(path), len(path)+1)
copy(blockPath, path) copy(blockPath, path)
blockPath = append(path, cty.GetAttrStep{Name: name}) blockPath = append(path, cty.GetAttrStep{Name: name})
blockV := val.GetAttr(name)
switch blockS.Nesting { switch blockS.Nesting {
case configschema.NestingSingle, configschema.NestingGroup: case configschema.NestingSingle, configschema.NestingGroup:
pvm = append(pvm, getValMarks(&blockS.Block, blockV, blockPath)...) pvm = append(pvm, getValMarks(&blockS.Block, blockV, blockPath)...)

View File

@ -1,6 +1,7 @@
package terraform package terraform
import ( import (
"fmt"
"sync" "sync"
"testing" "testing"
@ -550,3 +551,95 @@ func evaluatorForModule(stateSync *states.SyncState, changesSync *plans.ChangesS
Changes: changesSync, Changes: changesSync,
} }
} }
func TestMarkProviderSensitive(t *testing.T) {
schema := &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"unsensitive": {
Type: cty.String,
Optional: true,
},
"sensitive": {
Type: cty.String,
Sensitive: true,
},
},
BlockTypes: map[string]*configschema.NestedBlock{
"list": &configschema.NestedBlock{
Nesting: configschema.NestingList,
Block: configschema.Block{
Attributes: map[string]*configschema.Attribute{
"unsensitive": {
Type: cty.String,
Optional: true,
},
"sensitive": {
Type: cty.String,
Sensitive: true,
},
},
},
},
},
}
for _, tc := range []struct {
given cty.Value
expect cty.Value
}{
{
cty.UnknownVal(schema.ImpliedType()),
cty.UnknownVal(schema.ImpliedType()),
},
{
cty.ObjectVal(map[string]cty.Value{
"sensitive": cty.UnknownVal(cty.String),
"unsensitive": cty.UnknownVal(cty.String),
"list": cty.UnknownVal(schema.BlockTypes["list"].ImpliedType()),
}),
cty.ObjectVal(map[string]cty.Value{
"sensitive": cty.UnknownVal(cty.String).Mark("sensitive"),
"unsensitive": cty.UnknownVal(cty.String),
"list": cty.UnknownVal(schema.BlockTypes["list"].ImpliedType()),
}),
},
{
cty.ObjectVal(map[string]cty.Value{
"sensitive": cty.NullVal(cty.String),
"unsensitive": cty.UnknownVal(cty.String),
"list": cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"sensitive": cty.UnknownVal(cty.String),
"unsensitive": cty.UnknownVal(cty.String),
}),
cty.ObjectVal(map[string]cty.Value{
"sensitive": cty.NullVal(cty.String),
"unsensitive": cty.NullVal(cty.String),
}),
}),
}),
cty.ObjectVal(map[string]cty.Value{
"sensitive": cty.NullVal(cty.String).Mark("sensitive"),
"unsensitive": cty.UnknownVal(cty.String),
"list": cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"sensitive": cty.UnknownVal(cty.String).Mark("sensitive"),
"unsensitive": cty.UnknownVal(cty.String),
}),
cty.ObjectVal(map[string]cty.Value{
"sensitive": cty.NullVal(cty.String).Mark("sensitive"),
"unsensitive": cty.NullVal(cty.String),
}),
}),
}),
},
} {
t.Run(fmt.Sprintf("%#v", tc.given), func(t *testing.T) {
got := markProviderSensitiveAttributes(schema, tc.given)
if !got.RawEquals(tc.expect) {
t.Fatalf("\nexpected: %#v\ngot: %#v\n", tc.expect, got)
}
})
}
}