152 lines
5.1 KiB
Go
152 lines
5.1 KiB
Go
package configschema
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/terraform/internal/lang/marks"
|
|
"github.com/zclconf/go-cty/cty"
|
|
)
|
|
|
|
// ValueMarks returns a set of path value marks for a given value and path,
|
|
// based on the sensitive flag for each attribute within the schema. Nested
|
|
// blocks are descended (if present in the given value).
|
|
func (b *Block) ValueMarks(val cty.Value, path cty.Path) []cty.PathValueMarks {
|
|
var pvm []cty.PathValueMarks
|
|
|
|
// We can mark attributes as sensitive even if the value is null
|
|
for name, attrS := range b.Attributes {
|
|
if attrS.Sensitive {
|
|
// Create a copy of the path, with this step added, to add to our PathValueMarks slice
|
|
attrPath := make(cty.Path, len(path), len(path)+1)
|
|
copy(attrPath, path)
|
|
attrPath = append(path, cty.GetAttrStep{Name: name})
|
|
pvm = append(pvm, cty.PathValueMarks{
|
|
Path: attrPath,
|
|
Marks: cty.NewValueMarks(marks.Sensitive),
|
|
})
|
|
}
|
|
}
|
|
|
|
// If the value is null, no other marks are possible
|
|
if val.IsNull() {
|
|
return pvm
|
|
}
|
|
|
|
// Extract marks for nested attribute type values
|
|
for name, attrS := range b.Attributes {
|
|
// If the attribute has no nested type, or the nested type doesn't
|
|
// contain any sensitive attributes, skip inspecting it
|
|
if attrS.NestedType == nil || !attrS.NestedType.ContainsSensitive() {
|
|
continue
|
|
}
|
|
|
|
// Create a copy of the path, with this step added, to add to our PathValueMarks slice
|
|
attrPath := make(cty.Path, len(path), len(path)+1)
|
|
copy(attrPath, path)
|
|
attrPath = append(path, cty.GetAttrStep{Name: name})
|
|
|
|
pvm = append(pvm, attrS.NestedType.ValueMarks(val.GetAttr(name), attrPath)...)
|
|
}
|
|
|
|
// Extract marks for nested blocks
|
|
for name, blockS := range b.BlockTypes {
|
|
// If our block doesn't contain any sensitive attributes, skip inspecting it
|
|
if !blockS.Block.ContainsSensitive() {
|
|
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
|
|
blockPath := make(cty.Path, len(path), len(path)+1)
|
|
copy(blockPath, path)
|
|
blockPath = append(path, cty.GetAttrStep{Name: name})
|
|
|
|
switch blockS.Nesting {
|
|
case NestingSingle, NestingGroup:
|
|
pvm = append(pvm, blockS.Block.ValueMarks(blockV, blockPath)...)
|
|
case NestingList, NestingMap, NestingSet:
|
|
for it := blockV.ElementIterator(); it.Next(); {
|
|
idx, blockEV := it.Element()
|
|
morePaths := blockS.Block.ValueMarks(blockEV, append(blockPath, cty.IndexStep{Key: idx}))
|
|
pvm = append(pvm, morePaths...)
|
|
}
|
|
default:
|
|
panic(fmt.Sprintf("unsupported nesting mode %s", blockS.Nesting))
|
|
}
|
|
}
|
|
return pvm
|
|
}
|
|
|
|
// ValueMarks returns a set of path value marks for a given value and path,
|
|
// based on the sensitive flag for each attribute within the nested attribute.
|
|
// Attributes with nested types are descended (if present in the given value).
|
|
func (o *Object) ValueMarks(val cty.Value, path cty.Path) []cty.PathValueMarks {
|
|
var pvm []cty.PathValueMarks
|
|
|
|
if val.IsNull() || !val.IsKnown() {
|
|
return pvm
|
|
}
|
|
|
|
for name, attrS := range o.Attributes {
|
|
// Skip attributes which can never produce sensitive path value marks
|
|
if !attrS.Sensitive && (attrS.NestedType == nil || !attrS.NestedType.ContainsSensitive()) {
|
|
continue
|
|
}
|
|
|
|
switch o.Nesting {
|
|
case NestingSingle, NestingGroup:
|
|
// Create a path to this attribute
|
|
attrPath := make(cty.Path, len(path), len(path)+1)
|
|
copy(attrPath, path)
|
|
attrPath = append(path, cty.GetAttrStep{Name: name})
|
|
|
|
if attrS.Sensitive {
|
|
// If the entire attribute is sensitive, mark it so
|
|
pvm = append(pvm, cty.PathValueMarks{
|
|
Path: attrPath,
|
|
Marks: cty.NewValueMarks(marks.Sensitive),
|
|
})
|
|
} else {
|
|
// The attribute has a nested type which contains sensitive
|
|
// attributes, so recurse
|
|
pvm = append(pvm, attrS.NestedType.ValueMarks(val.GetAttr(name), attrPath)...)
|
|
}
|
|
case NestingList, NestingMap, NestingSet:
|
|
// For nested attribute types which have a non-single nesting mode,
|
|
// we add path value marks for each element of the collection
|
|
for it := val.ElementIterator(); it.Next(); {
|
|
idx, attrEV := it.Element()
|
|
attrV := attrEV.GetAttr(name)
|
|
|
|
// Create a path to this element of the attribute's collection. Note
|
|
// that the path is extended in opposite order to the iteration order
|
|
// of the loops: index into the collection, then the contained
|
|
// attribute name. This is because we have one type
|
|
// representing multiple collection elements.
|
|
attrPath := make(cty.Path, len(path), len(path)+2)
|
|
copy(attrPath, path)
|
|
attrPath = append(path, cty.IndexStep{Key: idx}, cty.GetAttrStep{Name: name})
|
|
|
|
if attrS.Sensitive {
|
|
// If the entire attribute is sensitive, mark it so
|
|
pvm = append(pvm, cty.PathValueMarks{
|
|
Path: attrPath,
|
|
Marks: cty.NewValueMarks(marks.Sensitive),
|
|
})
|
|
} else {
|
|
// The attribute has a nested type which contains sensitive
|
|
// attributes, so recurse
|
|
pvm = append(pvm, attrS.NestedType.ValueMarks(attrV, attrPath)...)
|
|
}
|
|
}
|
|
default:
|
|
panic(fmt.Sprintf("unsupported nesting mode %s", attrS.NestedType.Nesting))
|
|
}
|
|
}
|
|
return pvm
|
|
}
|