-
Notifications
You must be signed in to change notification settings - Fork 9.5k
/
marks.go
151 lines (132 loc) · 5.07 KB
/
marks.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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
}