/
analyzer_meta_references_shortcuts.go
87 lines (80 loc) · 3.04 KB
/
analyzer_meta_references_shortcuts.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
package globalref
import (
"fmt"
"github.com/khulnasoft/policy-engine/pkg/internal/terraform/addrs"
"github.com/khulnasoft/policy-engine/pkg/internal/terraform/lang"
)
// ReferencesFromOutputValue returns all of the direct references from the
// value expression of the given output value. It doesn't include any indirect
// references.
func (a *Analyzer) ReferencesFromOutputValue(addr addrs.AbsOutputValue) []Reference {
mc := a.ModuleConfig(addr.Module)
if mc == nil {
return nil
}
oc := mc.Outputs[addr.OutputValue.Name]
if oc == nil {
return nil
}
refs, _ := lang.ReferencesInExpr(oc.Expr)
return absoluteRefs(addr.Module, refs)
}
// ReferencesFromResourceInstance returns all of the direct references from the
// definition of the resource instance at the given address. It doesn't include
// any indirect references.
//
// The result doesn't directly include references from a "count" or "for_each"
// expression belonging to the associated resource, but it will include any
// references to count.index, each.key, or each.value that appear in the
// expressions which you can then, if you wish, resolve indirectly using
// Analyzer.MetaReferences. Alternatively, you can use
// Analyzer.ReferencesFromResourceRepetition to get that same result directly.
func (a *Analyzer) ReferencesFromResourceInstance(addr addrs.AbsResourceInstance) []Reference {
// Using MetaReferences for this is kinda overkill, since
// lang.ReferencesInBlock would be sufficient really, but
// this ensures we keep consistent in how we build the
// resulting absolute references and otherwise aside from
// some extra overhead this call boils down to a call to
// lang.ReferencesInBlock anyway.
fakeRef := Reference{
ContainerAddr: addr.Module,
LocalRef: &addrs.Reference{
Subject: addr.Resource,
},
}
return a.MetaReferences(fakeRef)
}
// ReferencesFromResourceRepetition returns the references from the given
// resource's for_each or count expression, or an empty set if the resource
// doesn't use repetition.
//
// This is a special-case sort of helper for use in situations where an
// expression might refer to count.index, each.key, or each.value, and thus
// we say that it depends indirectly on the repetition expression.
func (a *Analyzer) ReferencesFromResourceRepetition(addr addrs.AbsResource) []Reference {
modCfg := a.ModuleConfig(addr.Module)
if modCfg == nil {
return nil
}
rc := modCfg.ResourceByAddr(addr.Resource)
if rc == nil {
return nil
}
// We're assuming here that resources can either have count or for_each,
// but never both, because that's a requirement enforced by the language
// decoder. But we'll assert it just to make sure we catch it if that
// changes for some reason.
if rc.ForEach != nil && rc.Count != nil {
panic(fmt.Sprintf("%s has both for_each and count", addr))
}
switch {
case rc.ForEach != nil:
refs, _ := lang.ReferencesInExpr(rc.ForEach)
return absoluteRefs(addr.Module, refs)
case rc.Count != nil:
refs, _ := lang.ReferencesInExpr(rc.Count)
return absoluteRefs(addr.Module, refs)
default:
return nil
}
}