github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/lang/globalref/analyzer_meta_references_shortcuts.go (about) 1 package globalref 2 3 import ( 4 "fmt" 5 6 "github.com/hashicorp/terraform/internal/addrs" 7 "github.com/hashicorp/terraform/internal/lang" 8 ) 9 10 // ReferencesFromOutputValue returns all of the direct references from the 11 // value expression of the given output value. It doesn't include any indirect 12 // references. 13 func (a *Analyzer) ReferencesFromOutputValue(addr addrs.AbsOutputValue) []Reference { 14 mc := a.ModuleConfig(addr.Module) 15 if mc == nil { 16 return nil 17 } 18 oc := mc.Outputs[addr.OutputValue.Name] 19 if oc == nil { 20 return nil 21 } 22 refs, _ := lang.ReferencesInExpr(oc.Expr) 23 return absoluteRefs(addr.Module, refs) 24 } 25 26 // ReferencesFromResourceInstance returns all of the direct references from the 27 // definition of the resource instance at the given address. It doesn't include 28 // any indirect references. 29 // 30 // The result doesn't directly include references from a "count" or "for_each" 31 // expression belonging to the associated resource, but it will include any 32 // references to count.index, each.key, or each.value that appear in the 33 // expressions which you can then, if you wish, resolve indirectly using 34 // Analyzer.MetaReferences. Alternatively, you can use 35 // Analyzer.ReferencesFromResourceRepetition to get that same result directly. 36 func (a *Analyzer) ReferencesFromResourceInstance(addr addrs.AbsResourceInstance) []Reference { 37 // Using MetaReferences for this is kinda overkill, since 38 // lang.ReferencesInBlock would be sufficient really, but 39 // this ensures we keep consistent in how we build the 40 // resulting absolute references and otherwise aside from 41 // some extra overhead this call boils down to a call to 42 // lang.ReferencesInBlock anyway. 43 fakeRef := Reference{ 44 ContainerAddr: addr.Module, 45 LocalRef: &addrs.Reference{ 46 Subject: addr.Resource, 47 }, 48 } 49 return a.MetaReferences(fakeRef) 50 } 51 52 // ReferencesFromResourceRepetition returns the references from the given 53 // resource's for_each or count expression, or an empty set if the resource 54 // doesn't use repetition. 55 // 56 // This is a special-case sort of helper for use in situations where an 57 // expression might refer to count.index, each.key, or each.value, and thus 58 // we say that it depends indirectly on the repetition expression. 59 func (a *Analyzer) ReferencesFromResourceRepetition(addr addrs.AbsResource) []Reference { 60 modCfg := a.ModuleConfig(addr.Module) 61 if modCfg == nil { 62 return nil 63 } 64 rc := modCfg.ResourceByAddr(addr.Resource) 65 if rc == nil { 66 return nil 67 } 68 69 // We're assuming here that resources can either have count or for_each, 70 // but never both, because that's a requirement enforced by the language 71 // decoder. But we'll assert it just to make sure we catch it if that 72 // changes for some reason. 73 if rc.ForEach != nil && rc.Count != nil { 74 panic(fmt.Sprintf("%s has both for_each and count", addr)) 75 } 76 77 switch { 78 case rc.ForEach != nil: 79 refs, _ := lang.ReferencesInExpr(rc.ForEach) 80 return absoluteRefs(addr.Module, refs) 81 case rc.Count != nil: 82 refs, _ := lang.ReferencesInExpr(rc.Count) 83 return absoluteRefs(addr.Module, refs) 84 default: 85 return nil 86 } 87 }