github.com/pulumi/terraform@v1.4.0/pkg/configs/config.go (about)

     1  package configs
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"sort"
     7  
     8  	version "github.com/hashicorp/go-version"
     9  	"github.com/hashicorp/hcl/v2"
    10  	"github.com/pulumi/terraform/pkg/addrs"
    11  	"github.com/pulumi/terraform/pkg/depsfile"
    12  	"github.com/pulumi/terraform/pkg/getproviders"
    13  )
    14  
    15  // A Config is a node in the tree of modules within a configuration.
    16  //
    17  // The module tree is constructed by following ModuleCall instances recursively
    18  // through the root module transitively into descendent modules.
    19  //
    20  // A module tree described in *this* package represents the static tree
    21  // represented by configuration. During evaluation a static ModuleNode may
    22  // expand into zero or more module instances depending on the use of count and
    23  // for_each configuration attributes within each call.
    24  type Config struct {
    25  	// RootModule points to the Config for the root module within the same
    26  	// module tree as this module. If this module _is_ the root module then
    27  	// this is self-referential.
    28  	Root *Config
    29  
    30  	// ParentModule points to the Config for the module that directly calls
    31  	// this module. If this is the root module then this field is nil.
    32  	Parent *Config
    33  
    34  	// Path is a sequence of module logical names that traverse from the root
    35  	// module to this config. Path is empty for the root module.
    36  	//
    37  	// This should only be used to display paths to the end-user in rare cases
    38  	// where we are talking about the static module tree, before module calls
    39  	// have been resolved. In most cases, an addrs.ModuleInstance describing
    40  	// a node in the dynamic module tree is better, since it will then include
    41  	// any keys resulting from evaluating "count" and "for_each" arguments.
    42  	Path addrs.Module
    43  
    44  	// ChildModules points to the Config for each of the direct child modules
    45  	// called from this module. The keys in this map match the keys in
    46  	// Module.ModuleCalls.
    47  	Children map[string]*Config
    48  
    49  	// Module points to the object describing the configuration for the
    50  	// various elements (variables, resources, etc) defined by this module.
    51  	Module *Module
    52  
    53  	// CallRange is the source range for the header of the module block that
    54  	// requested this module.
    55  	//
    56  	// This field is meaningless for the root module, where its contents are undefined.
    57  	CallRange hcl.Range
    58  
    59  	// SourceAddr is the source address that the referenced module was requested
    60  	// from, as specified in configuration. SourceAddrRaw is the same
    61  	// information, but as the raw string the user originally entered.
    62  	//
    63  	// These fields are meaningless for the root module, where their contents are undefined.
    64  	SourceAddr    addrs.ModuleSource
    65  	SourceAddrRaw string
    66  
    67  	// SourceAddrRange is the location in the configuration source where the
    68  	// SourceAddr value was set, for use in diagnostic messages.
    69  	//
    70  	// This field is meaningless for the root module, where its contents are undefined.
    71  	SourceAddrRange hcl.Range
    72  
    73  	// Version is the specific version that was selected for this module,
    74  	// based on version constraints given in configuration.
    75  	//
    76  	// This field is nil if the module was loaded from a non-registry source,
    77  	// since versions are not supported for other sources.
    78  	//
    79  	// This field is meaningless for the root module, where it will always
    80  	// be nil.
    81  	Version *version.Version
    82  }
    83  
    84  // ModuleRequirements represents the provider requirements for an individual
    85  // module, along with references to any child modules. This is used to
    86  // determine which modules require which providers.
    87  type ModuleRequirements struct {
    88  	Name         string
    89  	SourceAddr   addrs.ModuleSource
    90  	SourceDir    string
    91  	Requirements getproviders.Requirements
    92  	Children     map[string]*ModuleRequirements
    93  }
    94  
    95  // NewEmptyConfig constructs a single-node configuration tree with an empty
    96  // root module. This is generally a pretty useless thing to do, so most callers
    97  // should instead use BuildConfig.
    98  func NewEmptyConfig() *Config {
    99  	ret := &Config{}
   100  	ret.Root = ret
   101  	ret.Children = make(map[string]*Config)
   102  	ret.Module = &Module{}
   103  	return ret
   104  }
   105  
   106  // Depth returns the number of "hops" the receiver is from the root of its
   107  // module tree, with the root module having a depth of zero.
   108  func (c *Config) Depth() int {
   109  	ret := 0
   110  	this := c
   111  	for this.Parent != nil {
   112  		ret++
   113  		this = this.Parent
   114  	}
   115  	return ret
   116  }
   117  
   118  // DeepEach calls the given function once for each module in the tree, starting
   119  // with the receiver.
   120  //
   121  // A parent is always called before its children and children of a particular
   122  // node are visited in lexicographic order by their names.
   123  func (c *Config) DeepEach(cb func(c *Config)) {
   124  	cb(c)
   125  
   126  	names := make([]string, 0, len(c.Children))
   127  	for name := range c.Children {
   128  		names = append(names, name)
   129  	}
   130  
   131  	for _, name := range names {
   132  		c.Children[name].DeepEach(cb)
   133  	}
   134  }
   135  
   136  // AllModules returns a slice of all the receiver and all of its descendent
   137  // nodes in the module tree, in the same order they would be visited by
   138  // DeepEach.
   139  func (c *Config) AllModules() []*Config {
   140  	var ret []*Config
   141  	c.DeepEach(func(c *Config) {
   142  		ret = append(ret, c)
   143  	})
   144  	return ret
   145  }
   146  
   147  // Descendent returns the descendent config that has the given path beneath
   148  // the receiver, or nil if there is no such module.
   149  //
   150  // The path traverses the static module tree, prior to any expansion to handle
   151  // count and for_each arguments.
   152  //
   153  // An empty path will just return the receiver, and is therefore pointless.
   154  func (c *Config) Descendent(path addrs.Module) *Config {
   155  	current := c
   156  	for _, name := range path {
   157  		current = current.Children[name]
   158  		if current == nil {
   159  			return nil
   160  		}
   161  	}
   162  	return current
   163  }
   164  
   165  // DescendentForInstance is like Descendent except that it accepts a path
   166  // to a particular module instance in the dynamic module graph, returning
   167  // the node from the static module graph that corresponds to it.
   168  //
   169  // All instances created by a particular module call share the same
   170  // configuration, so the keys within the given path are disregarded.
   171  func (c *Config) DescendentForInstance(path addrs.ModuleInstance) *Config {
   172  	current := c
   173  	for _, step := range path {
   174  		current = current.Children[step.Name]
   175  		if current == nil {
   176  			return nil
   177  		}
   178  	}
   179  	return current
   180  }
   181  
   182  // EntersNewPackage returns true if this call is to an external module, either
   183  // directly via a remote source address or indirectly via a registry source
   184  // address.
   185  //
   186  // Other behaviors in Terraform may treat package crossings as a special
   187  // situation, because that indicates that the caller and callee can change
   188  // independently of one another and thus we should disallow using any features
   189  // where the caller assumes anything about the callee other than its input
   190  // variables, required provider configurations, and output values.
   191  //
   192  // It's not meaningful to ask if the Config representing the root module enters
   193  // a new package because the root module is always outside of all module
   194  // packages, and so this function will arbitrarily return false in that case.
   195  func (c *Config) EntersNewPackage() bool {
   196  	return moduleSourceAddrEntersNewPackage(c.SourceAddr)
   197  }
   198  
   199  // VerifyDependencySelections checks whether the given locked dependencies
   200  // are acceptable for all of the version constraints reported in the
   201  // configuration tree represented by the reciever.
   202  //
   203  // This function will errors only if any of the locked dependencies are out of
   204  // range for corresponding constraints in the configuration. If there are
   205  // multiple inconsistencies then it will attempt to describe as many of them
   206  // as possible, rather than stopping at the first problem.
   207  //
   208  // It's typically the responsibility of "terraform init" to change the locked
   209  // dependencies to conform with the configuration, and so
   210  // VerifyDependencySelections is intended for other commands to check whether
   211  // it did so correctly and to catch if anything has changed in configuration
   212  // since the last "terraform init" which requires re-initialization. However,
   213  // it's up to the caller to decide how to advise users recover from these
   214  // errors, because the advise can vary depending on what operation the user
   215  // is attempting.
   216  func (c *Config) VerifyDependencySelections(depLocks *depsfile.Locks) []error {
   217  	var errs []error
   218  
   219  	reqs, diags := c.ProviderRequirements()
   220  	if diags.HasErrors() {
   221  		// It should be very unusual to get here, but unfortunately we can
   222  		// end up here in some edge cases where the config loader doesn't
   223  		// process version constraint strings in exactly the same way as
   224  		// the requirements resolver. (See the addProviderRequirements method
   225  		// for more information.)
   226  		errs = append(errs, fmt.Errorf("failed to determine the configuration's provider requirements: %s", diags.Error()))
   227  	}
   228  
   229  	for providerAddr, constraints := range reqs {
   230  		if !depsfile.ProviderIsLockable(providerAddr) {
   231  			continue // disregard builtin providers, and such
   232  		}
   233  		if depLocks != nil && depLocks.ProviderIsOverridden(providerAddr) {
   234  			// The "overridden" case is for unusual special situations like
   235  			// dev overrides, so we'll explicitly note it in the logs just in
   236  			// case we see bug reports with these active and it helps us
   237  			// understand why we ended up using the "wrong" plugin.
   238  			log.Printf("[DEBUG] Config.VerifyDependencySelections: skipping %s because it's overridden by a special configuration setting", providerAddr)
   239  			continue
   240  		}
   241  
   242  		var lock *depsfile.ProviderLock
   243  		if depLocks != nil { // Should always be true in main code, but unfortunately sometimes not true in old tests that don't fill out arguments completely
   244  			lock = depLocks.Provider(providerAddr)
   245  		}
   246  		if lock == nil {
   247  			log.Printf("[TRACE] Config.VerifyDependencySelections: provider %s has no lock file entry to satisfy %q", providerAddr, getproviders.VersionConstraintsString(constraints))
   248  			errs = append(errs, fmt.Errorf("provider %s: required by this configuration but no version is selected", providerAddr))
   249  			continue
   250  		}
   251  
   252  		selectedVersion := lock.Version()
   253  		allowedVersions := getproviders.MeetingConstraints(constraints)
   254  		log.Printf("[TRACE] Config.VerifyDependencySelections: provider %s has %s to satisfy %q", providerAddr, selectedVersion.String(), getproviders.VersionConstraintsString(constraints))
   255  		if !allowedVersions.Has(selectedVersion) {
   256  			// The most likely cause of this is that the author of a module
   257  			// has changed its constraints, but this could also happen in
   258  			// some other unusual situations, such as the user directly
   259  			// editing the lock file to record something invalid. We'll
   260  			// distinguish those cases here in order to avoid the more
   261  			// specific error message potentially being a red herring in
   262  			// the edge-cases.
   263  			currentConstraints := getproviders.VersionConstraintsString(constraints)
   264  			lockedConstraints := getproviders.VersionConstraintsString(lock.VersionConstraints())
   265  			switch {
   266  			case currentConstraints != lockedConstraints:
   267  				errs = append(errs, fmt.Errorf("provider %s: locked version selection %s doesn't match the updated version constraints %q", providerAddr, selectedVersion.String(), currentConstraints))
   268  			default:
   269  				errs = append(errs, fmt.Errorf("provider %s: version constraints %q don't match the locked version selection %s", providerAddr, currentConstraints, selectedVersion.String()))
   270  			}
   271  		}
   272  	}
   273  
   274  	// Return multiple errors in an arbitrary-but-deterministic order.
   275  	sort.Slice(errs, func(i, j int) bool {
   276  		return errs[i].Error() < errs[j].Error()
   277  	})
   278  
   279  	return errs
   280  }
   281  
   282  // ProviderRequirements searches the full tree of modules under the receiver
   283  // for both explicit and implicit dependencies on providers.
   284  //
   285  // The result is a full manifest of all of the providers that must be available
   286  // in order to work with the receiving configuration.
   287  //
   288  // If the returned diagnostics includes errors then the resulting Requirements
   289  // may be incomplete.
   290  func (c *Config) ProviderRequirements() (getproviders.Requirements, hcl.Diagnostics) {
   291  	reqs := make(getproviders.Requirements)
   292  	diags := c.addProviderRequirements(reqs, true)
   293  
   294  	return reqs, diags
   295  }
   296  
   297  // ProviderRequirementsShallow searches only the direct receiver for explicit
   298  // and implicit dependencies on providers. Descendant modules are ignored.
   299  //
   300  // If the returned diagnostics includes errors then the resulting Requirements
   301  // may be incomplete.
   302  func (c *Config) ProviderRequirementsShallow() (getproviders.Requirements, hcl.Diagnostics) {
   303  	reqs := make(getproviders.Requirements)
   304  	diags := c.addProviderRequirements(reqs, false)
   305  
   306  	return reqs, diags
   307  }
   308  
   309  // ProviderRequirementsByModule searches the full tree of modules under the
   310  // receiver for both explicit and implicit dependencies on providers,
   311  // constructing a tree where the requirements are broken out by module.
   312  //
   313  // If the returned diagnostics includes errors then the resulting Requirements
   314  // may be incomplete.
   315  func (c *Config) ProviderRequirementsByModule() (*ModuleRequirements, hcl.Diagnostics) {
   316  	reqs := make(getproviders.Requirements)
   317  	diags := c.addProviderRequirements(reqs, false)
   318  
   319  	children := make(map[string]*ModuleRequirements)
   320  	for name, child := range c.Children {
   321  		childReqs, childDiags := child.ProviderRequirementsByModule()
   322  		childReqs.Name = name
   323  		children[name] = childReqs
   324  		diags = append(diags, childDiags...)
   325  	}
   326  
   327  	ret := &ModuleRequirements{
   328  		SourceAddr:   c.SourceAddr,
   329  		SourceDir:    c.Module.SourceDir,
   330  		Requirements: reqs,
   331  		Children:     children,
   332  	}
   333  
   334  	return ret, diags
   335  }
   336  
   337  // addProviderRequirements is the main part of the ProviderRequirements
   338  // implementation, gradually mutating a shared requirements object to
   339  // eventually return. If the recurse argument is true, the requirements will
   340  // include all descendant modules; otherwise, only the specified module.
   341  func (c *Config) addProviderRequirements(reqs getproviders.Requirements, recurse bool) hcl.Diagnostics {
   342  	var diags hcl.Diagnostics
   343  
   344  	// First we'll deal with the requirements directly in _our_ module...
   345  	if c.Module.ProviderRequirements != nil {
   346  		for _, providerReqs := range c.Module.ProviderRequirements.RequiredProviders {
   347  			fqn := providerReqs.Type
   348  			if _, ok := reqs[fqn]; !ok {
   349  				// We'll at least have an unconstrained dependency then, but might
   350  				// add to this in the loop below.
   351  				reqs[fqn] = nil
   352  			}
   353  			// The model of version constraints in this package is still the
   354  			// old one using a different upstream module to represent versions,
   355  			// so we'll need to shim that out here for now. The two parsers
   356  			// don't exactly agree in practice 🙄 so this might produce new errors.
   357  			// TODO: Use the new parser throughout this package so we can get the
   358  			// better error messages it produces in more situations.
   359  			constraints, err := getproviders.ParseVersionConstraints(providerReqs.Requirement.Required.String())
   360  			if err != nil {
   361  				diags = diags.Append(&hcl.Diagnostic{
   362  					Severity: hcl.DiagError,
   363  					Summary:  "Invalid version constraint",
   364  					// The errors returned by ParseVersionConstraint already include
   365  					// the section of input that was incorrect, so we don't need to
   366  					// include that here.
   367  					Detail:  fmt.Sprintf("Incorrect version constraint syntax: %s.", err.Error()),
   368  					Subject: providerReqs.Requirement.DeclRange.Ptr(),
   369  				})
   370  			}
   371  			reqs[fqn] = append(reqs[fqn], constraints...)
   372  		}
   373  	}
   374  
   375  	// Each resource in the configuration creates an *implicit* provider
   376  	// dependency, though we'll only record it if there isn't already
   377  	// an explicit dependency on the same provider.
   378  	for _, rc := range c.Module.ManagedResources {
   379  		fqn := rc.Provider
   380  		if _, exists := reqs[fqn]; exists {
   381  			// Explicit dependency already present
   382  			continue
   383  		}
   384  		reqs[fqn] = nil
   385  	}
   386  	for _, rc := range c.Module.DataResources {
   387  		fqn := rc.Provider
   388  		if _, exists := reqs[fqn]; exists {
   389  			// Explicit dependency already present
   390  			continue
   391  		}
   392  		reqs[fqn] = nil
   393  	}
   394  
   395  	// "provider" block can also contain version constraints
   396  	for _, provider := range c.Module.ProviderConfigs {
   397  		fqn := c.Module.ProviderForLocalConfig(addrs.LocalProviderConfig{LocalName: provider.Name})
   398  		if _, ok := reqs[fqn]; !ok {
   399  			// We'll at least have an unconstrained dependency then, but might
   400  			// add to this in the loop below.
   401  			reqs[fqn] = nil
   402  		}
   403  		if provider.Version.Required != nil {
   404  			// The model of version constraints in this package is still the
   405  			// old one using a different upstream module to represent versions,
   406  			// so we'll need to shim that out here for now. The two parsers
   407  			// don't exactly agree in practice 🙄 so this might produce new errors.
   408  			// TODO: Use the new parser throughout this package so we can get the
   409  			// better error messages it produces in more situations.
   410  			constraints, err := getproviders.ParseVersionConstraints(provider.Version.Required.String())
   411  			if err != nil {
   412  				diags = diags.Append(&hcl.Diagnostic{
   413  					Severity: hcl.DiagError,
   414  					Summary:  "Invalid version constraint",
   415  					// The errors returned by ParseVersionConstraint already include
   416  					// the section of input that was incorrect, so we don't need to
   417  					// include that here.
   418  					Detail:  fmt.Sprintf("Incorrect version constraint syntax: %s.", err.Error()),
   419  					Subject: provider.Version.DeclRange.Ptr(),
   420  				})
   421  			}
   422  			reqs[fqn] = append(reqs[fqn], constraints...)
   423  		}
   424  	}
   425  
   426  	if recurse {
   427  		for _, childConfig := range c.Children {
   428  			moreDiags := childConfig.addProviderRequirements(reqs, true)
   429  			diags = append(diags, moreDiags...)
   430  		}
   431  	}
   432  
   433  	return diags
   434  }
   435  
   436  // resolveProviderTypes walks through the providers in the module and ensures
   437  // the true types are assigned based on the provider requirements for the
   438  // module.
   439  func (c *Config) resolveProviderTypes() {
   440  	for _, child := range c.Children {
   441  		child.resolveProviderTypes()
   442  	}
   443  
   444  	// collect the required_providers, and then add any missing default providers
   445  	providers := map[string]addrs.Provider{}
   446  	for name, p := range c.Module.ProviderRequirements.RequiredProviders {
   447  		providers[name] = p.Type
   448  	}
   449  
   450  	// ensure all provider configs know their correct type
   451  	for _, p := range c.Module.ProviderConfigs {
   452  		addr, required := providers[p.Name]
   453  		if required {
   454  			p.providerType = addr
   455  		} else {
   456  			addr := addrs.NewDefaultProvider(p.Name)
   457  			p.providerType = addr
   458  			providers[p.Name] = addr
   459  		}
   460  	}
   461  
   462  	// connect module call providers to the correct type
   463  	for _, mod := range c.Module.ModuleCalls {
   464  		for _, p := range mod.Providers {
   465  			if addr, known := providers[p.InParent.Name]; known {
   466  				p.InParent.providerType = addr
   467  			}
   468  		}
   469  	}
   470  
   471  	// fill in parent module calls too
   472  	if c.Parent != nil {
   473  		for _, mod := range c.Parent.Module.ModuleCalls {
   474  			for _, p := range mod.Providers {
   475  				if addr, known := providers[p.InChild.Name]; known {
   476  					p.InChild.providerType = addr
   477  				}
   478  			}
   479  		}
   480  	}
   481  }
   482  
   483  // ProviderTypes returns the FQNs of each distinct provider type referenced
   484  // in the receiving configuration.
   485  //
   486  // This is a helper for easily determining which provider types are required
   487  // to fully interpret the configuration, though it does not include version
   488  // information and so callers are expected to have already dealt with
   489  // provider version selection in an earlier step and have identified suitable
   490  // versions for each provider.
   491  func (c *Config) ProviderTypes() []addrs.Provider {
   492  	// Ignore diagnostics here because they relate to version constraints
   493  	reqs, _ := c.ProviderRequirements()
   494  
   495  	ret := make([]addrs.Provider, 0, len(reqs))
   496  	for k := range reqs {
   497  		ret = append(ret, k)
   498  	}
   499  	sort.Slice(ret, func(i, j int) bool {
   500  		return ret[i].String() < ret[j].String()
   501  	})
   502  	return ret
   503  }
   504  
   505  // ResolveAbsProviderAddr returns the AbsProviderConfig represented by the given
   506  // ProviderConfig address, which must not be nil or this method will panic.
   507  //
   508  // If the given address is already an AbsProviderConfig then this method returns
   509  // it verbatim, and will always succeed. If it's a LocalProviderConfig then
   510  // it will consult the local-to-FQN mapping table for the given module
   511  // to find the absolute address corresponding to the given local one.
   512  //
   513  // The module address to resolve local addresses in must be given in the second
   514  // argument, and must refer to a module that exists under the receiver or
   515  // else this method will panic.
   516  func (c *Config) ResolveAbsProviderAddr(addr addrs.ProviderConfig, inModule addrs.Module) addrs.AbsProviderConfig {
   517  	switch addr := addr.(type) {
   518  
   519  	case addrs.AbsProviderConfig:
   520  		return addr
   521  
   522  	case addrs.LocalProviderConfig:
   523  		// Find the descendent Config that contains the module that this
   524  		// local config belongs to.
   525  		mc := c.Descendent(inModule)
   526  		if mc == nil {
   527  			panic(fmt.Sprintf("ResolveAbsProviderAddr with non-existent module %s", inModule.String()))
   528  		}
   529  
   530  		var provider addrs.Provider
   531  		if providerReq, exists := c.Module.ProviderRequirements.RequiredProviders[addr.LocalName]; exists {
   532  			provider = providerReq.Type
   533  		} else {
   534  			provider = addrs.ImpliedProviderForUnqualifiedType(addr.LocalName)
   535  		}
   536  
   537  		return addrs.AbsProviderConfig{
   538  			Module:   inModule,
   539  			Provider: provider,
   540  			Alias:    addr.Alias,
   541  		}
   542  
   543  	default:
   544  		panic(fmt.Sprintf("cannot ResolveAbsProviderAddr(%v, ...)", addr))
   545  	}
   546  
   547  }
   548  
   549  // ProviderForConfigAddr returns the FQN for a given addrs.ProviderConfig, first
   550  // by checking for the provider in module.ProviderRequirements and falling
   551  // back to addrs.NewDefaultProvider if it is not found.
   552  func (c *Config) ProviderForConfigAddr(addr addrs.LocalProviderConfig) addrs.Provider {
   553  	if provider, exists := c.Module.ProviderRequirements.RequiredProviders[addr.LocalName]; exists {
   554  		return provider.Type
   555  	}
   556  	return c.ResolveAbsProviderAddr(addr, addrs.RootModule).Provider
   557  }