// providerFactories uses the selections made previously by an installer in
// the local cache directory (m.providerLocalCacheDir) to produce a map
// from provider addresses to factory functions to create instances of
// those providers.
//
// providerFactories will return an error if the installer's selections cannot
// be honored with what is currently in the cache, such as if a selected
// package has been removed from the cache or if the contents of a selected
// package have been modified outside of the installer. If it returns an error,
// the returned map may be incomplete or invalid, but will be as complete
// as possible given the cause of the error.
providerFactories uses the selections made previously by an installer in
the local cache directory (m.providerLocalCacheDir) to produce a map
from provider addresses to factory functions to create instances of
those providers.

providerFactories will return an error if the installer's selections cannot
be honored with what is currently in the cache, such as if a selected
package has been removed from the cache or if the contents of a selected
package have been modified outside of the installer. If it returns an error,
the returned map may be incomplete or invalid, but will be as complete
as possible given the cause of the error.
// providerFactories uses the selections made previously by an installer in // the local cache directory ( m . providerLocalCacheDir ) to produce a map // from provider addresses to factory functions to create instances of // those providers . // // providerFactories will return an error if the installer ' s selections cannot // be honored with what is currently in the cache such as if a selected // package has been removed from the cache or if the contents of a selected // package have been modified outside of the installer . If it returns an error // the returned map may be incomplete or invalid but will be as complete // as possible given the cause of the error .
func (m *Meta) providerFactories() (map[addrs.Provider]providers.Factory, error) {
	locks, diags := m.lockedDependencies()
	if diags.HasErrors() {
		return nil, fmt.Errorf("failed to read dependency lock file: %s", diags.Err())
	}
	var err error
	providerLocks := locks.AllProviders()
	cacheDir := m.providerLocalCacheDir()
	internalFactories := m.internalProviders()
	devOverrideProviders := m.ProviderDevOverrides
	unmanagedProviders := m.UnmanagedProviders
	factories := make(map[addrs.Provider]providers.Factory, len(providerLocks)+len(internalFactories)+len(unmanagedProviders))
	for name, factory := range internalFactories {
		factories[addrs.NewBuiltInProvider(name)] = factory
	}
	for provider, lock := range providerLocks {
		reportError := func(thisErr error) {
			err = multierror.Append(err, thisErr)
			factories[provider] = providerFactoryError(thisErr)
		}
		version := lock.Version()
		cached := cacheDir.ProviderVersion(provider, version)
		if cached == nil {
			reportError(fmt.Errorf(
				"there is no package for %s %s cached in %s",
				provider, version, cacheDir.BasePath(),
			))
			continue
		}
		if allowedHashes := lock.PreferredHashes(); len(allowedHashes) != 0 {
			matched, err := cached.MatchesAnyHash(allowedHashes)
			if err != nil {
				reportError(fmt.Errorf(
					"failed to verify checksum of %s %s package cached in in %s: %s",
					provider, version, cacheDir.BasePath(), err,
				))
				continue
			}
			if !matched {
				reportError(fmt.Errorf(
					"the cached package for %s %s (in %s) does not match any of the checksums recorded in the dependency lock file",
					provider, version, cacheDir.BasePath(),
				))
				continue
			}
		}
		factories[provider] = providerFactory(cached)
	}
	for provider, localDir := range devOverrideProviders {
		factories[provider] = devOverrideProviderFactory(provider, localDir)
	}
	for provider, reattach := range unmanagedProviders {
		factories[provider] = unmanagedProviderFactory(provider, reattach)
	}
	return factories, err
}
func ( m * Meta ) providerFactories ( ) ( map [ addrs . Provider ] providers . Factory , error ) { locks , diags := m . lockedDependencies ( ) if diags . HasErrors ( ) { return nil , fmt . Errorf ( " " , diags . Err ( ) ) } var err error providerLocks := locks . AllProviders ( ) cacheDir := m . providerLocalCacheDir ( ) internalFactories := m . internalProviders ( ) devOverrideProviders := m . ProviderDevOverrides unmanagedProviders := m . UnmanagedProviders factories := make ( map [ addrs . Provider ] providers . Factory , len ( providerLocks ) + len ( internalFactories ) + len ( unmanagedProviders ) ) for name , factory := range internalFactories { factories [ addrs . NewBuiltInProvider ( name ) ] = factory } for provider , lock := range providerLocks { reportError := func ( thisErr error ) { err = multierror . Append ( err , thisErr ) factories [ provider ] = providerFactoryError ( thisErr ) } version := lock . Version ( ) cached := cacheDir . ProviderVersion ( provider , version ) if cached == nil { reportError ( fmt . Errorf ( " " , provider , version , cacheDir . BasePath ( ) , ) ) continue } if allowedHashes := lock . PreferredHashes ( ) ; len ( allowedHashes ) != 0 { matched , err := cached . MatchesAnyHash ( allowedHashes ) if err != nil { reportError ( fmt . Errorf ( " " , provider , version , cacheDir . BasePath ( ) , err , ) ) continue } if ! matched { reportError ( fmt . Errorf ( " " , provider , version , cacheDir . BasePath ( ) , ) ) continue } } factories [ provider ] = providerFactory ( cached ) } for provider , localDir := range devOverrideProviders { factories [ provider ] = devOverrideProviderFactory ( provider , localDir ) } for provider , reattach := range unmanagedProviders { factories [ provider ] = unmanagedProviderFactory ( provider , reattach ) } return factories , err }
providerFactories uses the selections made previously by an installer in
the local cache directory (m.providerLocalCacheDir) to produce a map
from provider addresses to factory functions to create instances of
those providers.
providerFactories uses the selections made previously by an installer in the local cache directory ( m . providerLocalCacheDir ) to produce a map from provider addresses to factory functions to create instances of those providers .
// We'll always run through all of our providers, even if one of them // encounters an error, so that we can potentially report multiple errors // where appropriate and so that callers can potentially make use of the // partial result we return if e.g. they want to enumerate which providers // are available, or call into one of the providers that didn't fail. // For the providers from the lock file, we expect them to be already // available in the provider cache because "terraform init" should already // have put them there. // The internal providers are _always_ available, even if the configuration // doesn't request them, because they don't need any special installation // and they'll just be ignored if not used. // We have two different special cases aimed at provider development // use-cases, which are not for "production" use: // - The CLI config can specify that a particular provider should always // use a plugin from a particular local directory, ignoring anything the // lock file or cache directory might have to say about it. This is useful // for manual testing of local development builds. // - The Terraform SDK test harness (and possibly other callers in future) // can ask that we use its own already-started provider servers, which we // call "unmanaged" because Terraform isn't responsible for starting // and stopping them. This is intended for automated testing where a // calling harness is responsible both for starting the provider server // and orchestrating one or more non-interactive Terraform runs that then // exercise it. // Unmanaged providers take precedence over overridden providers because // overrides are typically a "session-level" setting while unmanaged // providers are typically scoped to a single unattended command. // We'll populate a provider factory that just echoes our error // again if called, which allows us to still report a helpful // error even if it gets detected downstream somewhere from the // caller using our partial result. // The cached package must match one of the checksums recorded in // the lock file, if any. // It's likely that providers in this map will conflict with providers // in providerLocks