6 version "github.com/hashicorp/go-version"
7 "github.com/hashicorp/hcl2/hcl"
8 "github.com/hashicorp/terraform/addrs"
11 // A Config is a node in the tree of modules within a configuration.
13 // The module tree is constructed by following ModuleCall instances recursively
14 // through the root module transitively into descendent modules.
16 // A module tree described in *this* package represents the static tree
17 // represented by configuration. During evaluation a static ModuleNode may
18 // expand into zero or more module instances depending on the use of count and
19 // for_each configuration attributes within each call.
21 // RootModule points to the Config for the root module within the same
22 // module tree as this module. If this module _is_ the root module then
23 // this is self-referential.
26 // ParentModule points to the Config for the module that directly calls
27 // this module. If this is the root module then this field is nil.
30 // Path is a sequence of module logical names that traverse from the root
31 // module to this config. Path is empty for the root module.
33 // This should only be used to display paths to the end-user in rare cases
34 // where we are talking about the static module tree, before module calls
35 // have been resolved. In most cases, an addrs.ModuleInstance describing
36 // a node in the dynamic module tree is better, since it will then include
37 // any keys resulting from evaluating "count" and "for_each" arguments.
40 // ChildModules points to the Config for each of the direct child modules
41 // called from this module. The keys in this map match the keys in
42 // Module.ModuleCalls.
43 Children map[string]*Config
45 // Module points to the object describing the configuration for the
46 // various elements (variables, resources, etc) defined by this module.
49 // CallRange is the source range for the header of the module block that
50 // requested this module.
52 // This field is meaningless for the root module, where its contents are undefined.
55 // SourceAddr is the source address that the referenced module was requested
56 // from, as specified in configuration.
58 // This field is meaningless for the root module, where its contents are undefined.
61 // SourceAddrRange is the location in the configuration source where the
62 // SourceAddr value was set, for use in diagnostic messages.
64 // This field is meaningless for the root module, where its contents are undefined.
65 SourceAddrRange hcl.Range
67 // Version is the specific version that was selected for this module,
68 // based on version constraints given in configuration.
70 // This field is nil if the module was loaded from a non-registry source,
71 // since versions are not supported for other sources.
73 // This field is meaningless for the root module, where it will always
75 Version *version.Version
78 // NewEmptyConfig constructs a single-node configuration tree with an empty
79 // root module. This is generally a pretty useless thing to do, so most callers
80 // should instead use BuildConfig.
81 func NewEmptyConfig() *Config {
84 ret.Children = make(map[string]*Config)
85 ret.Module = &Module{}
89 // Depth returns the number of "hops" the receiver is from the root of its
90 // module tree, with the root module having a depth of zero.
91 func (c *Config) Depth() int {
94 for this.Parent != nil {
101 // DeepEach calls the given function once for each module in the tree, starting
102 // with the receiver.
104 // A parent is always called before its children and children of a particular
105 // node are visited in lexicographic order by their names.
106 func (c *Config) DeepEach(cb func(c *Config)) {
109 names := make([]string, 0, len(c.Children))
110 for name := range c.Children {
111 names = append(names, name)
114 for _, name := range names {
115 c.Children[name].DeepEach(cb)
119 // AllModules returns a slice of all the receiver and all of its descendent
120 // nodes in the module tree, in the same order they would be visited by
122 func (c *Config) AllModules() []*Config {
124 c.DeepEach(func(c *Config) {
130 // Descendent returns the descendent config that has the given path beneath
131 // the receiver, or nil if there is no such module.
133 // The path traverses the static module tree, prior to any expansion to handle
134 // count and for_each arguments.
136 // An empty path will just return the receiver, and is therefore pointless.
137 func (c *Config) Descendent(path addrs.Module) *Config {
139 for _, name := range path {
140 current = current.Children[name]
148 // DescendentForInstance is like Descendent except that it accepts a path
149 // to a particular module instance in the dynamic module graph, returning
150 // the node from the static module graph that corresponds to it.
152 // All instances created by a particular module call share the same
153 // configuration, so the keys within the given path are disregarded.
154 func (c *Config) DescendentForInstance(path addrs.ModuleInstance) *Config {
156 for _, step := range path {
157 current = current.Children[step.Name]
165 // ProviderTypes returns the names of each distinct provider type referenced
166 // in the receiving configuration.
168 // This is a helper for easily determining which provider types are required
169 // to fully interpret the configuration, though it does not include version
170 // information and so callers are expected to have already dealt with
171 // provider version selection in an earlier step and have identified suitable
172 // versions for each provider.
173 func (c *Config) ProviderTypes() []string {
174 m := make(map[string]struct{})
175 c.gatherProviderTypes(m)
177 ret := make([]string, 0, len(m))
184 func (c *Config) gatherProviderTypes(m map[string]struct{}) {
189 for _, pc := range c.Module.ProviderConfigs {
190 m[pc.Name] = struct{}{}
192 for _, rc := range c.Module.ManagedResources {
193 providerAddr := rc.ProviderConfigAddr()
194 m[providerAddr.Type] = struct{}{}
196 for _, rc := range c.Module.DataResources {
197 providerAddr := rc.ProviderConfigAddr()
198 m[providerAddr.Type] = struct{}{}
201 // Must also visit our child modules, recursively.
202 for _, cc := range c.Children {
203 cc.gatherProviderTypes(m)