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  }