88 lines
3.0 KiB
Go
88 lines
3.0 KiB
Go
package globalref
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/terraform/internal/addrs"
|
|
"github.com/hashicorp/terraform/internal/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)
|
|
}
|
|
|
|
// ReferencesFromResource 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
|
|
}
|
|
}
|