Documentation ¶
Overview ¶
Package globalref is home to some analysis algorithms that aim to answer questions about references between objects and object attributes across an entire configuration.
This is a different problem than references within a single module, which we handle using some relatively simpler functions in the "lang" package in the parent directory. The globalref algorithms are often implemented in terms of those module-local reference-checking functions.
Index ¶
- type Analyzer
- func (a *Analyzer) ContributingResourceReferences(refs ...Reference) []Reference
- func (a *Analyzer) ContributingResources(refs ...Reference) []addrs.AbsResource
- func (a *Analyzer) MetaReferences(ref Reference) []Reference
- func (a *Analyzer) ModuleConfig(addr addrs.ModuleInstance) *configs.Module
- func (a *Analyzer) ReferencesFromOutputValue(addr addrs.AbsOutputValue) []Reference
- func (a *Analyzer) ReferencesFromResourceInstance(addr addrs.AbsResourceInstance) []Reference
- func (a *Analyzer) ReferencesFromResourceRepetition(addr addrs.AbsResource) []Reference
- type Reference
- type ResourceAttr
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Analyzer ¶
type Analyzer struct {
// contains filtered or unexported fields
}
Analyzer is the main component of this package, serving as a container for various state that the analysis algorithms depend on either for their core functionality or for producing results more quickly.
Global reference analysis is currently intended only for "best effort" use-cases related to giving hints to the user or tailoring UI output. Avoid using it for anything that would cause changes to the analyzer being considered a breaking change under the v1 compatibility promises, because we expect to continue to refine and evolve these rules over time in ways that may cause us to detect either more or fewer references than today. Typically we will conservatively return more references than would be necessary dynamically, but that isn't guaranteed for all situations.
In particular, we currently typically don't distinguish between multiple instances of the same module, and so we overgeneralize references from one instance of a module as references from the same location in all instances of that module. We may make this more precise in future, which would then remove various detected references from the analysis results.
Each Analyzer works with a particular configs.Config object which it assumes represents the root module of a configuration. Config objects are typically immutable by convention anyway, but it's particularly important not to modify a configuration while it's attached to a live Analyzer, because the Analyzer contains caches derived from data in the configuration tree.
func NewAnalyzer ¶
func NewAnalyzer(cfg *configs.Config, providerSchemas map[addrs.Provider]providers.ProviderSchema) *Analyzer
NewAnalyzer constructs a new analyzer bound to the given configuration and provider schemas.
The given object must represent a root module, or this function will panic.
The given provider schemas must cover at least all of the providers used in the given configuration. If not then analysis results will be silently incomplete for any decision that requires checking schema.
func (*Analyzer) ContributingResourceReferences ¶
ContributingResourceReferences analyzes all of the given references and for each one tries to walk backwards through any named values to find all references to resource attributes that contributed either directly or indirectly to any of them.
This is a global operation that can be potentially quite expensive for complex configurations.
func (*Analyzer) ContributingResources ¶
func (a *Analyzer) ContributingResources(refs ...Reference) []addrs.AbsResource
ContributingResources analyzes all of the given references and for each one tries to walk backwards through any named values to find all resources whose values contributed either directly or indirectly to any of them.
This is a wrapper around ContributingResourceReferences which simplifies the result to only include distinct resource addresses, not full references. If the configuration includes several different references to different parts of a resource, ContributingResources will not preserve that detail.
func (*Analyzer) MetaReferences ¶
MetaReferences inspects the configuration to find the references contained within the most specific object that the given address refers to.
This finds only the direct references in that object, not any indirect references from those. This is a building block for some other Analyzer functions that can walk through multiple levels of reference.
If the given reference refers to something that doesn't exist in the configuration we're analyzing then MetaReferences will return no meta-references at all, which is indistinguishable from an existing object that doesn't refer to anything.
func (*Analyzer) ModuleConfig ¶
func (a *Analyzer) ModuleConfig(addr addrs.ModuleInstance) *configs.Module
ModuleConfig retrieves a module configuration from the configuration the analyzer belongs to, or nil if there is no module with the given address.
func (*Analyzer) ReferencesFromOutputValue ¶
func (a *Analyzer) ReferencesFromOutputValue(addr addrs.AbsOutputValue) []Reference
ReferencesFromOutputValue returns all of the direct references from the value expression of the given output value. It doesn't include any indirect references.
func (*Analyzer) ReferencesFromResourceInstance ¶
func (a *Analyzer) ReferencesFromResourceInstance(addr addrs.AbsResourceInstance) []Reference
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 (*Analyzer) ReferencesFromResourceRepetition ¶
func (a *Analyzer) ReferencesFromResourceRepetition(addr addrs.AbsResource) []Reference
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.
type Reference ¶
type Reference struct { // ContainerAddr is always either addrs.ModuleInstance or // addrs.AbsResourceInstance. The latter is required if LocalRef's // subject is either an addrs.CountAddr or addrs.ForEachAddr, so // we can know which resource's repetition expression it's // referring to. ContainerAddr addrs.Targetable // LocalRef is a reference that would be resolved in the context // of the module instance or resource instance given in ContainerAddr. LocalRef *addrs.Reference }
Reference combines an addrs.Reference with the address of the module instance or resource instance where it was found.
Because of the design of the OpenTofu language, our main model of references only captures the module-local part of the reference and assumes that it's always clear from context which module a reference belongs to. That's not true for globalref because our whole purpose is to work across module boundaries, and so this package in particular has its own representation of references.
func (Reference) DebugString ¶
DebugString returns an internal (but still somewhat OpenTofu-language-like) compact string representation of the reciever, which isn't an address that any of our usual address parsers could accept but still captures the essence of what the reference represents.
The DebugString result is not suitable for end-user-oriented messages.
DebugString is also not suitable for use as a unique key for a reference, because it's ambiguous (between a no-key resource instance and a resource) and because it discards the source location information in the LocalRef.
func (Reference) ModuleAddr ¶
func (r Reference) ModuleAddr() addrs.ModuleInstance
ModuleAddr returns the address of the module where the reference would be resolved.
This is either ContainerAddr directly if it's already just a module instance, or the module instance part of it if it's a resource instance.
func (Reference) ResourceAttr ¶
func (r Reference) ResourceAttr() (ResourceAttr, bool)
ResourceAttr converts the Reference value to a more specific ResourceAttr value.
Because not all references belong to resources, the extra boolean return value indicates whether the returned address is valid.
func (Reference) ResourceInstance ¶
func (r Reference) ResourceInstance() (addrs.AbsResourceInstance, bool)
ResourceInstance returns the address of the resource where the reference would be resolved, if there is one.
Because not all references belong to resources, the extra boolean return value indicates whether the returned address is valid.
type ResourceAttr ¶
type ResourceAttr struct { Resource addrs.AbsResourceInstance Attr cty.Path }
ResourceAttr represents a global resource and attribute reference. This is a more specific form of the Reference type since it can only refer to a specific AbsResource and one of its attributes.
func (ResourceAttr) DebugString ¶
func (r ResourceAttr) DebugString() string