addrs: ImpliedProviderForUnqualifiedType function
This encapsulates the logic for selecting an implied FQN for an unqualified type name, which could either come from a local name used in a module without specifying an explicit source for it or from the prefix of a resource type on a resource that doesn't explicitly set "provider". This replaces the previous behavior of just directly calling NewDefaultProvider everywhere so that we can use a different implication for the local name "terraform", to refer to the built-in terraform provider rather than the stale one that's on registry.terraform.io for compatibility with other Terraform versions.
This commit is contained in:
parent
27a794062e
commit
7caf0b9246
|
@ -78,6 +78,30 @@ func NewProvider(hostname svchost.Hostname, namespace, typeName string) Provider
|
|||
}
|
||||
}
|
||||
|
||||
// ImpliedProviderForUnqualifiedType represents the rules for inferring what
|
||||
// provider FQN a user intended when only a naked type name is available.
|
||||
//
|
||||
// For all except the type name "terraform" this returns a so-called "default"
|
||||
// provider, which is under the registry.terraform.io/hashicorp/ namespace.
|
||||
//
|
||||
// As a special case, the string "terraform" maps to
|
||||
// "terraform.io/builtin/terraform" because that is the more likely user
|
||||
// intent than the now-unmaintained "registry.terraform.io/hashicorp/terraform"
|
||||
// which remains only for compatibility with older Terraform versions.
|
||||
func ImpliedProviderForUnqualifiedType(typeName string) Provider {
|
||||
switch typeName {
|
||||
case "terraform":
|
||||
// Note for future maintainers: any additional strings we add here
|
||||
// as implied to be builtin must never also be use as provider names
|
||||
// in the registry.terraform.io/hashicorp/... namespace, because
|
||||
// otherwise older versions of Terraform could implicitly select
|
||||
// the registry name instead of the internal one.
|
||||
return NewBuiltInProvider(typeName)
|
||||
default:
|
||||
return NewDefaultProvider(typeName)
|
||||
}
|
||||
}
|
||||
|
||||
// NewDefaultProvider returns the default address of a HashiCorp-maintained,
|
||||
// Registry-hosted provider.
|
||||
func NewDefaultProvider(name string) Provider {
|
||||
|
|
|
@ -310,7 +310,7 @@ func (c *Config) ResolveAbsProviderAddr(addr addrs.ProviderConfig, inModule addr
|
|||
if providerReq, exists := c.Module.ProviderRequirements[addr.LocalName]; exists {
|
||||
provider = providerReq.Type
|
||||
} else {
|
||||
provider = addrs.NewDefaultProvider(addr.LocalName)
|
||||
provider = addrs.ImpliedProviderForUnqualifiedType(addr.LocalName)
|
||||
}
|
||||
|
||||
return addrs.AbsProviderConfig{
|
||||
|
|
|
@ -124,6 +124,7 @@ func TestConfigProviderRequirements(t *testing.T) {
|
|||
nullProvider := addrs.NewDefaultProvider("null")
|
||||
randomProvider := addrs.NewDefaultProvider("random")
|
||||
impliedProvider := addrs.NewDefaultProvider("implied")
|
||||
terraformProvider := addrs.NewBuiltInProvider("terraform")
|
||||
|
||||
got, diags := cfg.ProviderRequirements()
|
||||
assertNoDiagnostics(t, diags)
|
||||
|
@ -134,6 +135,7 @@ func TestConfigProviderRequirements(t *testing.T) {
|
|||
tlsProvider: getproviders.MustParseVersionConstraints("~> 3.0"),
|
||||
impliedProvider: nil,
|
||||
happycloudProvider: nil,
|
||||
terraformProvider: nil,
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(want, got); diff != "" {
|
||||
|
|
|
@ -195,7 +195,7 @@ func (m *Module) appendFile(file *File) hcl.Diagnostics {
|
|||
}
|
||||
diags = append(diags, hclDiags...)
|
||||
} else {
|
||||
fqn = addrs.NewDefaultProvider(reqd.Name)
|
||||
fqn = addrs.ImpliedProviderForUnqualifiedType(reqd.Name)
|
||||
}
|
||||
if existing, exists := m.ProviderRequirements[reqd.Name]; exists {
|
||||
if existing.Type != fqn {
|
||||
|
@ -286,11 +286,11 @@ func (m *Module) appendFile(file *File) hcl.Diagnostics {
|
|||
if existing, exists := m.ProviderRequirements[r.ProviderConfigAddr().LocalName]; exists {
|
||||
r.Provider = existing.Type
|
||||
} else {
|
||||
r.Provider = addrs.NewDefaultProvider(r.ProviderConfigAddr().LocalName)
|
||||
r.Provider = addrs.ImpliedProviderForUnqualifiedType(r.ProviderConfigAddr().LocalName)
|
||||
}
|
||||
continue
|
||||
}
|
||||
r.Provider = addrs.NewDefaultProvider(r.Addr().ImpliedProvider())
|
||||
r.Provider = addrs.ImpliedProviderForUnqualifiedType(r.Addr().ImpliedProvider())
|
||||
}
|
||||
|
||||
for _, r := range file.DataResources {
|
||||
|
@ -310,13 +310,12 @@ func (m *Module) appendFile(file *File) hcl.Diagnostics {
|
|||
if r.ProviderConfigRef != nil {
|
||||
if existing, exists := m.ProviderRequirements[r.ProviderConfigAddr().LocalName]; exists {
|
||||
r.Provider = existing.Type
|
||||
|
||||
} else {
|
||||
r.Provider = addrs.NewDefaultProvider(r.ProviderConfigAddr().LocalName)
|
||||
r.Provider = addrs.ImpliedProviderForUnqualifiedType(r.ProviderConfigAddr().LocalName)
|
||||
}
|
||||
continue
|
||||
}
|
||||
r.Provider = addrs.NewDefaultProvider(r.Addr().ImpliedProvider())
|
||||
r.Provider = addrs.ImpliedProviderForUnqualifiedType(r.Addr().ImpliedProvider())
|
||||
}
|
||||
|
||||
return diags
|
||||
|
@ -511,5 +510,5 @@ func (m *Module) ProviderForLocalConfig(pc addrs.LocalProviderConfig) addrs.Prov
|
|||
if provider, exists := m.ProviderRequirements[pc.LocalName]; exists {
|
||||
return provider.Type
|
||||
}
|
||||
return addrs.NewDefaultProvider(pc.LocalName)
|
||||
return addrs.ImpliedProviderForUnqualifiedType(pc.LocalName)
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ func mergeProviderVersionConstraints(recv map[string]ProviderRequirements, ovrd
|
|||
// any errors parsing the source string will have already been captured.
|
||||
fqn, _ = addrs.ParseProviderSourceString(reqd.Source.SourceStr)
|
||||
} else {
|
||||
fqn = addrs.NewDefaultProvider(reqd.Name)
|
||||
fqn = addrs.ImpliedProviderForUnqualifiedType(reqd.Name)
|
||||
}
|
||||
recv[reqd.Name] = ProviderRequirements{Type: fqn, VersionConstraints: []VersionConstraint{reqd.Requirement}}
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ func (r *Resource) merge(or *Resource, prs map[string]ProviderRequirements) hcl.
|
|||
if existing, exists := prs[or.ProviderConfigRef.Name]; exists {
|
||||
r.Provider = existing.Type
|
||||
} else {
|
||||
r.Provider = addrs.NewDefaultProvider(r.ProviderConfigRef.Name)
|
||||
r.Provider = addrs.ImpliedProviderForUnqualifiedType(r.ProviderConfigRef.Name)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,18 @@ func TestNewModule_provider_local_name(t *testing.T) {
|
|||
if localName != "nonexist" {
|
||||
t.Error("wrong local name returned for a non-local provider")
|
||||
}
|
||||
|
||||
// can also look up the "terraform" provider and see that it sources is
|
||||
// allowed to be overridden, even though there is a builtin provider
|
||||
// called "terraform".
|
||||
p = addrs.NewProvider(addrs.DefaultRegistryHost, "not-builtin", "not-terraform")
|
||||
if name, exists := mod.ProviderLocalNames[p]; !exists {
|
||||
t.Fatal("provider FQN not-builtin/not-terraform not found")
|
||||
} else {
|
||||
if name != "terraform" {
|
||||
t.Fatalf("provider localname mismatch: got %s, want terraform", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This test validates the provider FQNs set in each Resource
|
||||
|
|
|
@ -19,3 +19,10 @@ resource "implied_foo" "bar" {
|
|||
module "child" {
|
||||
source = "./child"
|
||||
}
|
||||
|
||||
# There is no provider in required_providers called "terraform", but for
|
||||
# this name in particular we imply terraform.io/builtin/terraform instead,
|
||||
# to avoid selecting the now-unmaintained
|
||||
# registry.terraform.io/hashicorp/terraform.
|
||||
data "terraform_remote_state" "bar" {
|
||||
}
|
||||
|
|
|
@ -4,5 +4,8 @@ terraform {
|
|||
foo-test = {
|
||||
source = "foo/test"
|
||||
}
|
||||
terraform = {
|
||||
source = "not-builtin/not-terraform"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ func (c *Config) addProviderRequirements(reqs getproviders.Requirements) tfdiags
|
|||
fqn = addr
|
||||
}
|
||||
if fqn.IsZero() {
|
||||
fqn = addrs.NewDefaultProvider(localName)
|
||||
fqn = addrs.ImpliedProviderForUnqualifiedType(localName)
|
||||
}
|
||||
if _, ok := reqs[fqn]; !ok {
|
||||
// We'll at least have an unconstrained dependency then, but might
|
||||
|
|
|
@ -305,7 +305,7 @@ func (n *NodeAbstractResource) Provider() addrs.Provider {
|
|||
if n.Config != nil {
|
||||
return n.Config.Provider
|
||||
}
|
||||
return addrs.NewDefaultProvider(n.Addr.Resource.ImpliedProvider())
|
||||
return addrs.ImpliedProviderForUnqualifiedType(n.Addr.Resource.ImpliedProvider())
|
||||
}
|
||||
|
||||
// GraphNodeProviderConsumer
|
||||
|
|
Loading…
Reference in New Issue