69 lines
2.9 KiB
Go
69 lines
2.9 KiB
Go
|
package globalref
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
|
||
|
"github.com/hashicorp/terraform/internal/addrs"
|
||
|
"github.com/hashicorp/terraform/internal/configs"
|
||
|
"github.com/hashicorp/terraform/internal/providers"
|
||
|
)
|
||
|
|
||
|
// 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.
|
||
|
type Analyzer struct {
|
||
|
cfg *configs.Config
|
||
|
providerSchemas map[addrs.Provider]*providers.Schemas
|
||
|
}
|
||
|
|
||
|
// 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 NewAnalyzer(cfg *configs.Config, providerSchemas map[addrs.Provider]*providers.Schemas) *Analyzer {
|
||
|
if !cfg.Path.IsRoot() {
|
||
|
panic(fmt.Sprintf("constructing an Analyzer with non-root module %s", cfg.Path))
|
||
|
}
|
||
|
|
||
|
ret := &Analyzer{
|
||
|
cfg: cfg,
|
||
|
providerSchemas: providerSchemas,
|
||
|
}
|
||
|
return ret
|
||
|
}
|
||
|
|
||
|
// ModuleConfig retrieves a module configuration from the configuration the
|
||
|
// analyzer belongs to, or nil if there is no module with the given address.
|
||
|
func (a *Analyzer) ModuleConfig(addr addrs.ModuleInstance) *configs.Module {
|
||
|
modCfg := a.cfg.DescendentForInstance(addr)
|
||
|
if modCfg == nil {
|
||
|
return nil
|
||
|
}
|
||
|
return modCfg.Module
|
||
|
}
|