github.com/hashicorp/terraform-plugin-sdk@v1.17.2/internal/configs/config.go (about) 1 package configs 2 3 import ( 4 "sort" 5 6 version "github.com/hashicorp/go-version" 7 "github.com/hashicorp/hcl/v2" 8 "github.com/hashicorp/terraform-plugin-sdk/internal/addrs" 9 ) 10 11 // A Config is a node in the tree of modules within a configuration. 12 // 13 // The module tree is constructed by following ModuleCall instances recursively 14 // through the root module transitively into descendent modules. 15 // 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. 20 type Config struct { 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. 24 Root *Config 25 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. 28 Parent *Config 29 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. 32 // 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. 38 Path addrs.Module 39 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 44 45 // Module points to the object describing the configuration for the 46 // various elements (variables, resources, etc) defined by this module. 47 Module *Module 48 49 // CallRange is the source range for the header of the module block that 50 // requested this module. 51 // 52 // This field is meaningless for the root module, where its contents are undefined. 53 CallRange hcl.Range 54 55 // SourceAddr is the source address that the referenced module was requested 56 // from, as specified in configuration. 57 // 58 // This field is meaningless for the root module, where its contents are undefined. 59 SourceAddr string 60 61 // SourceAddrRange is the location in the configuration source where the 62 // SourceAddr value was set, for use in diagnostic messages. 63 // 64 // This field is meaningless for the root module, where its contents are undefined. 65 SourceAddrRange hcl.Range 66 67 // Version is the specific version that was selected for this module, 68 // based on version constraints given in configuration. 69 // 70 // This field is nil if the module was loaded from a non-registry source, 71 // since versions are not supported for other sources. 72 // 73 // This field is meaningless for the root module, where it will always 74 // be nil. 75 Version *version.Version 76 } 77 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 { 82 ret := &Config{} 83 ret.Root = ret 84 ret.Children = make(map[string]*Config) 85 ret.Module = &Module{} 86 return ret 87 } 88 89 // DeepEach calls the given function once for each module in the tree, starting 90 // with the receiver. 91 // 92 // A parent is always called before its children and children of a particular 93 // node are visited in lexicographic order by their names. 94 func (c *Config) DeepEach(cb func(c *Config)) { 95 cb(c) 96 97 names := make([]string, 0, len(c.Children)) 98 for name := range c.Children { 99 names = append(names, name) 100 } 101 102 for _, name := range names { 103 c.Children[name].DeepEach(cb) 104 } 105 } 106 107 // DescendentForInstance is like Descendent except that it accepts a path 108 // to a particular module instance in the dynamic module graph, returning 109 // the node from the static module graph that corresponds to it. 110 // 111 // All instances created by a particular module call share the same 112 // configuration, so the keys within the given path are disregarded. 113 func (c *Config) DescendentForInstance(path addrs.ModuleInstance) *Config { 114 current := c 115 for _, step := range path { 116 current = current.Children[step.Name] 117 if current == nil { 118 return nil 119 } 120 } 121 return current 122 } 123 124 // ProviderTypes returns the names of each distinct provider type referenced 125 // in the receiving configuration. 126 // 127 // This is a helper for easily determining which provider types are required 128 // to fully interpret the configuration, though it does not include version 129 // information and so callers are expected to have already dealt with 130 // provider version selection in an earlier step and have identified suitable 131 // versions for each provider. 132 func (c *Config) ProviderTypes() []string { 133 m := make(map[string]struct{}) 134 c.gatherProviderTypes(m) 135 136 ret := make([]string, 0, len(m)) 137 for k := range m { 138 ret = append(ret, k) 139 } 140 sort.Strings(ret) 141 return ret 142 } 143 func (c *Config) gatherProviderTypes(m map[string]struct{}) { 144 if c == nil { 145 return 146 } 147 148 for _, pc := range c.Module.ProviderConfigs { 149 m[pc.Name] = struct{}{} 150 } 151 for _, rc := range c.Module.ManagedResources { 152 providerAddr := rc.ProviderConfigAddr() 153 m[providerAddr.Type] = struct{}{} 154 } 155 for _, rc := range c.Module.DataResources { 156 providerAddr := rc.ProviderConfigAddr() 157 m[providerAddr.Type] = struct{}{} 158 } 159 160 // Must also visit our child modules, recursively. 161 for _, cc := range c.Children { 162 cc.gatherProviderTypes(m) 163 } 164 }