Merge pull request #28414 from hashicorp/jbardin/config-provider-fqns
resolve provider types when building the config
This commit is contained in:
commit
6839170274
|
@ -329,6 +329,53 @@ func (c *Config) addProviderRequirements(reqs getproviders.Requirements, recurse
|
||||||
return diags
|
return diags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// resolveProviderTypes walks through the providers in the module and ensures
|
||||||
|
// the true types are assigned based on the provider requirements for the
|
||||||
|
// module.
|
||||||
|
func (c *Config) resolveProviderTypes() {
|
||||||
|
for _, child := range c.Children {
|
||||||
|
child.resolveProviderTypes()
|
||||||
|
}
|
||||||
|
|
||||||
|
// collect the required_providers, and then add any missing default providers
|
||||||
|
providers := map[string]addrs.Provider{}
|
||||||
|
for name, p := range c.Module.ProviderRequirements.RequiredProviders {
|
||||||
|
providers[name] = p.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure all provider configs know their correct type
|
||||||
|
for _, p := range c.Module.ProviderConfigs {
|
||||||
|
addr, required := providers[p.Name]
|
||||||
|
if required {
|
||||||
|
p.providerType = addr
|
||||||
|
} else {
|
||||||
|
addr := addrs.NewDefaultProvider(p.Name)
|
||||||
|
p.providerType = addr
|
||||||
|
providers[p.Name] = addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// connect module call providers to the correct type
|
||||||
|
for _, mod := range c.Module.ModuleCalls {
|
||||||
|
for _, p := range mod.Providers {
|
||||||
|
if addr, known := providers[p.InParent.Name]; known {
|
||||||
|
p.InParent.providerType = addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill in parent module calls too
|
||||||
|
if c.Parent != nil {
|
||||||
|
for _, mod := range c.Parent.Module.ModuleCalls {
|
||||||
|
for _, p := range mod.Providers {
|
||||||
|
if addr, known := providers[p.InChild.Name]; known {
|
||||||
|
p.InChild.providerType = addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ProviderTypes returns the FQNs of each distinct provider type referenced
|
// ProviderTypes returns the FQNs of each distinct provider type referenced
|
||||||
// in the receiving configuration.
|
// in the receiving configuration.
|
||||||
//
|
//
|
||||||
|
|
|
@ -23,6 +23,10 @@ func BuildConfig(root *Module, walker ModuleWalker) (*Config, hcl.Diagnostics) {
|
||||||
cfg.Root = cfg // Root module is self-referential.
|
cfg.Root = cfg // Root module is self-referential.
|
||||||
cfg.Children, diags = buildChildModules(cfg, walker)
|
cfg.Children, diags = buildChildModules(cfg, walker)
|
||||||
|
|
||||||
|
// Now that the config is built, we can connect the provider names to all
|
||||||
|
// the known types for validation.
|
||||||
|
cfg.resolveProviderTypes()
|
||||||
|
|
||||||
diags = append(diags, validateProviderConfigs(nil, cfg, false)...)
|
diags = append(diags, validateProviderConfigs(nil, cfg, false)...)
|
||||||
|
|
||||||
return cfg, diags
|
return cfg, diags
|
||||||
|
|
|
@ -25,6 +25,13 @@ type Provider struct {
|
||||||
Config hcl.Body
|
Config hcl.Body
|
||||||
|
|
||||||
DeclRange hcl.Range
|
DeclRange hcl.Range
|
||||||
|
|
||||||
|
// TODO: this may not be set in some cases, so it is not yet suitable for
|
||||||
|
// use outside of this package. We currently only use it for internal
|
||||||
|
// validation, but once we verify that this can be set in all cases, we can
|
||||||
|
// export this so providers don't need to be re-resolved.
|
||||||
|
// This same field is also added to the ProviderConfigRef struct.
|
||||||
|
providerType addrs.Provider
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeProviderBlock(block *hcl.Block) (*Provider, hcl.Diagnostics) {
|
func decodeProviderBlock(block *hcl.Block) (*Provider, hcl.Diagnostics) {
|
||||||
|
|
|
@ -136,9 +136,18 @@ func validateProviderConfigs(call *ModuleCall, cfg *Config, noProviderConfig boo
|
||||||
|
|
||||||
// You cannot pass in a provider that cannot be used
|
// You cannot pass in a provider that cannot be used
|
||||||
for name, passed := range passedIn {
|
for name, passed := range passedIn {
|
||||||
|
childTy := passed.InChild.providerType
|
||||||
|
// get a default type if there was none set
|
||||||
|
if childTy.IsZero() {
|
||||||
|
// This means the child module is only using an inferred
|
||||||
|
// provider type. We allow this but will generate a warning to
|
||||||
|
// declare provider_requirements below.
|
||||||
|
childTy = addrs.NewDefaultProvider(passed.InChild.Name)
|
||||||
|
}
|
||||||
|
|
||||||
providerAddr := addrs.AbsProviderConfig{
|
providerAddr := addrs.AbsProviderConfig{
|
||||||
Module: cfg.Path,
|
Module: cfg.Path,
|
||||||
Provider: addrs.NewDefaultProvider(passed.InChild.Name),
|
Provider: childTy,
|
||||||
Alias: passed.InChild.Alias,
|
Alias: passed.InChild.Alias,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,9 +181,12 @@ func validateProviderConfigs(call *ModuleCall, cfg *Config, noProviderConfig boo
|
||||||
}
|
}
|
||||||
|
|
||||||
// The provider being passed in must also be of the correct type.
|
// The provider being passed in must also be of the correct type.
|
||||||
// While we would like to ensure required_providers exists here,
|
pTy := passed.InParent.providerType
|
||||||
// implied default configuration is still allowed.
|
if pTy.IsZero() {
|
||||||
pTy := addrs.NewDefaultProvider(passed.InParent.Name)
|
// While we would like to ensure required_providers exists here,
|
||||||
|
// implied default configuration is still allowed.
|
||||||
|
pTy = addrs.NewDefaultProvider(passed.InParent.Name)
|
||||||
|
}
|
||||||
|
|
||||||
// use the full address for a nice diagnostic output
|
// use the full address for a nice diagnostic output
|
||||||
parentAddr := addrs.AbsProviderConfig{
|
parentAddr := addrs.AbsProviderConfig{
|
||||||
|
|
|
@ -374,6 +374,13 @@ type ProviderConfigRef struct {
|
||||||
NameRange hcl.Range
|
NameRange hcl.Range
|
||||||
Alias string
|
Alias string
|
||||||
AliasRange *hcl.Range // nil if alias not set
|
AliasRange *hcl.Range // nil if alias not set
|
||||||
|
|
||||||
|
// TODO: this may not be set in some cases, so it is not yet suitable for
|
||||||
|
// use outside of this package. We currently only use it for internal
|
||||||
|
// validation, but once we verify that this can be set in all cases, we can
|
||||||
|
// export this so providers don't need to be re-resolved.
|
||||||
|
// This same field is also added to the Provider struct.
|
||||||
|
providerType addrs.Provider
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeProviderConfigRef(expr hcl.Expression, argName string) (*ProviderConfigRef, hcl.Diagnostics) {
|
func decodeProviderConfigRef(expr hcl.Expression, argName string) (*ProviderConfigRef, hcl.Diagnostics) {
|
||||||
|
|
|
@ -3,11 +3,13 @@ terraform {
|
||||||
bar-test = {
|
bar-test = {
|
||||||
source = "bar/test"
|
source = "bar/test"
|
||||||
}
|
}
|
||||||
|
foo-test = {
|
||||||
|
source = "foo/test"
|
||||||
|
configuration_aliases = [foo-test.other]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
provider "bar-test" {}
|
|
||||||
|
|
||||||
resource "test_instance" "explicit" {
|
resource "test_instance" "explicit" {
|
||||||
// explicitly setting provider bar-test
|
// explicitly setting provider bar-test
|
||||||
provider = bar-test
|
provider = bar-test
|
||||||
|
@ -17,3 +19,7 @@ resource "test_instance" "implicit" {
|
||||||
// since the provider type name "test" does not match an entry in
|
// since the provider type name "test" does not match an entry in
|
||||||
// required_providers, the default provider "test" should be used
|
// required_providers, the default provider "test" should be used
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resource "test_instance" "other" {
|
||||||
|
provider = foo-test.other
|
||||||
|
}
|
||||||
|
|
|
@ -10,6 +10,9 @@ provider "foo-test" {}
|
||||||
|
|
||||||
module "child" {
|
module "child" {
|
||||||
source = "./child"
|
source = "./child"
|
||||||
|
providers = {
|
||||||
|
foo-test.other = foo-test
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "test_instance" "explicit" {
|
resource "test_instance" "explicit" {
|
||||||
|
|
Loading…
Reference in New Issue