configs: attach provider fqn to Resource (#24382)

* configs: attach provider fqn to Resource
This commit is contained in:
Kristin Laemmert 2020-03-16 14:36:16 -04:00 committed by GitHub
parent 42f7beff31
commit ef19fb6203
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 160 additions and 4 deletions

View File

@ -33,7 +33,7 @@ func TestConfigProviderTypes_nested(t *testing.T) {
t.Fatalf("wrong result!\ngot: %#v\nwant: nil\n", got) t.Fatalf("wrong result!\ngot: %#v\nwant: nil\n", got)
} }
// config with two provider sources // config with two provider sources, and one implicit (default) provider
cfg, diags := testNestedModuleConfigFromDir(t, "testdata/valid-modules/nested-providers-fqns") cfg, diags := testNestedModuleConfigFromDir(t, "testdata/valid-modules/nested-providers-fqns")
if diags.HasErrors() { if diags.HasErrors() {
t.Fatal(diags.Error()) t.Fatal(diags.Error())
@ -41,6 +41,8 @@ func TestConfigProviderTypes_nested(t *testing.T) {
got = cfg.ProviderTypes() got = cfg.ProviderTypes()
want := []addrs.Provider{ want := []addrs.Provider{
// FIXME: this will be updated to NewDefaultProvider as we remove `Legacy*`
addrs.NewLegacyProvider("test"),
addrs.NewProvider(addrs.DefaultRegistryHost, "bar", "test"), addrs.NewProvider(addrs.DefaultRegistryHost, "bar", "test"),
addrs.NewProvider(addrs.DefaultRegistryHost, "foo", "test"), addrs.NewProvider(addrs.DefaultRegistryHost, "foo", "test"),
} }

View File

@ -280,6 +280,21 @@ func (m *Module) appendFile(file *File) hcl.Diagnostics {
continue continue
} }
m.ManagedResources[key] = r m.ManagedResources[key] = r
// set the provider FQN for the resource
var provider addrs.Provider
if r.ProviderConfigRef != nil {
if existing, exists := m.ProviderRequirements[r.ProviderConfigAddr().LocalName]; exists {
provider = existing.Type
} else {
// FIXME: This will be a NewDefaultProvider
provider = addrs.NewLegacyProvider(r.ProviderConfigAddr().LocalName)
}
r.Provider = provider
continue
}
// FIXME: r.Addr().DefaultProvider() will be refactored to return a string
r.Provider = r.Addr().DefaultProvider()
} }
for _, r := range file.DataResources { for _, r := range file.DataResources {
@ -294,6 +309,21 @@ func (m *Module) appendFile(file *File) hcl.Diagnostics {
continue continue
} }
m.DataResources[key] = r m.DataResources[key] = r
// set the provider FQN for the resource
var provider addrs.Provider
if r.ProviderConfigRef != nil {
if existing, exists := m.ProviderRequirements[r.ProviderConfigAddr().LocalName]; exists {
provider = existing.Type
} else {
// FIXME: This will be a NewDefaultProvider
provider = addrs.NewLegacyProvider(r.ProviderConfigAddr().LocalName)
}
r.Provider = provider
continue
}
// FIXME: r.Addr().DefaultProvider() will be refactored to return a string
r.Provider = r.Addr().DefaultProvider()
} }
return diags return diags
@ -436,7 +466,7 @@ func (m *Module) mergeFile(file *File) hcl.Diagnostics {
}) })
continue continue
} }
mergeDiags := existing.merge(r) mergeDiags := existing.merge(r, m.ProviderRequirements)
diags = append(diags, mergeDiags...) diags = append(diags, mergeDiags...)
} }
@ -452,7 +482,7 @@ func (m *Module) mergeFile(file *File) hcl.Diagnostics {
}) })
continue continue
} }
mergeDiags := existing.merge(r) mergeDiags := existing.merge(r, m.ProviderRequirements)
diags = append(diags, mergeDiags...) diags = append(diags, mergeDiags...)
} }

View File

@ -197,7 +197,7 @@ func (mc *ModuleCall) merge(omc *ModuleCall) hcl.Diagnostics {
return diags return diags
} }
func (r *Resource) merge(or *Resource) hcl.Diagnostics { func (r *Resource) merge(or *Resource, prs map[string]ProviderRequirements) hcl.Diagnostics {
var diags hcl.Diagnostics var diags hcl.Diagnostics
if r.Mode != or.Mode { if r.Mode != or.Mode {
@ -212,9 +212,18 @@ func (r *Resource) merge(or *Resource) hcl.Diagnostics {
if or.ForEach != nil { if or.ForEach != nil {
r.ForEach = or.ForEach r.ForEach = or.ForEach
} }
if or.ProviderConfigRef != nil { if or.ProviderConfigRef != nil {
r.ProviderConfigRef = or.ProviderConfigRef r.ProviderConfigRef = or.ProviderConfigRef
if existing, exists := prs[or.ProviderConfigRef.Name]; exists {
r.Provider = existing.Type
} else {
r.Provider = addrs.NewLegacyProvider(r.ProviderConfigRef.Name)
}
} }
// Provider FQN is set by Terraform during Merge
if r.Mode == addrs.ManagedResourceMode { if r.Mode == addrs.ManagedResourceMode {
// or.Managed is always non-nil for managed resource mode // or.Managed is always non-nil for managed resource mode

View File

@ -202,6 +202,37 @@ func TestModuleOverrideDynamic(t *testing.T) {
}) })
} }
func TestModuleOverrideResourceFQNs(t *testing.T) {
mod, diags := testModuleFromDir("testdata/valid-modules/override-resource-provider")
assertNoDiagnostics(t, diags)
got := mod.ManagedResources["test_instance.explicit"]
wantProvider := addrs.NewProvider(addrs.DefaultRegistryHost, "bar", "test")
wantProviderCfg := &ProviderConfigRef{
Name: "bar-test",
NameRange: hcl.Range{
Filename: "testdata/valid-modules/override-resource-provider/a_override.tf",
Start: hcl.Pos{Line: 2, Column: 14, Byte: 51},
End: hcl.Pos{Line: 2, Column: 22, Byte: 59},
},
}
if !got.Provider.Equals(wantProvider) {
t.Fatalf("wrong provider %s, want %s", got.Provider, wantProvider)
}
assertResultDeepEqual(t, got.ProviderConfigRef, wantProviderCfg)
// now verify that a resource with no provider config falls back to default
got = mod.ManagedResources["test_instance.default"]
wantProvider = addrs.NewLegacyProvider("test")
if !got.Provider.Equals(wantProvider) {
t.Fatalf("wrong provider %s, want %s", got.Provider, wantProvider)
}
if got.ProviderConfigRef != nil {
t.Fatalf("wrong result: found provider config ref %s, expected nil", got.ProviderConfigRef)
}
}
func TestMergeProviderVersionConstraints(t *testing.T) { func TestMergeProviderVersionConstraints(t *testing.T) {
v1, _ := version.NewConstraint("1.0.0") v1, _ := version.NewConstraint("1.0.0")
vc1 := VersionConstraint{ vc1 := VersionConstraint{

View File

@ -29,6 +29,50 @@ func TestNewModule_provider_local_name(t *testing.T) {
} }
} }
// This test validates the provider FQNs set in each Resource
func TestNewModule_resource_providers(t *testing.T) {
cfg, diags := testNestedModuleConfigFromDir(t, "testdata/valid-modules/nested-providers-fqns")
if diags.HasErrors() {
t.Fatal(diags.Error())
}
// both the root and child module have two resources, one which should use
// the default implied provider and one explicitly using a provider set in
// required_providers
wantImplicit := addrs.NewLegacyProvider("test")
wantFoo := addrs.NewProvider(addrs.DefaultRegistryHost, "foo", "test")
wantBar := addrs.NewProvider(addrs.DefaultRegistryHost, "bar", "test")
// root module
if !cfg.Module.ManagedResources["test_instance.explicit"].Provider.Equals(wantFoo) {
t.Fatalf("wrong provider for \"test_instance.explicit\"\ngot: %s\nwant: %s",
cfg.Module.ManagedResources["test_instance.explicit"].Provider,
wantFoo,
)
}
if !cfg.Module.ManagedResources["test_instance.implicit"].Provider.Equals(wantImplicit) {
t.Fatalf("wrong provider for \"test_instance.implicit\"\ngot: %s\nwant: %s",
cfg.Module.ManagedResources["test_instance.implicit"].Provider,
wantImplicit,
)
}
// child module
cm := cfg.Children["child"].Module
if !cm.ManagedResources["test_instance.explicit"].Provider.Equals(wantBar) {
t.Fatalf("wrong provider for \"module.child.test_instance.explicit\"\ngot: %s\nwant: %s",
cfg.Module.ManagedResources["test_instance.explicit"].Provider,
wantBar,
)
}
if !cm.ManagedResources["test_instance.implicit"].Provider.Equals(wantImplicit) {
t.Fatalf("wrong provider for \"module.child.test_instance.implicit\"\ngot: %s\nwant: %s",
cfg.Module.ManagedResources["test_instance.implicit"].Provider,
wantImplicit,
)
}
}
func TestProviderForLocalConfig(t *testing.T) { func TestProviderForLocalConfig(t *testing.T) {
mod, diags := testModuleFromDir("testdata/providers-explicit-fqn") mod, diags := testModuleFromDir("testdata/providers-explicit-fqn")
if diags.HasErrors() { if diags.HasErrors() {

View File

@ -20,6 +20,7 @@ type Resource struct {
ForEach hcl.Expression ForEach hcl.Expression
ProviderConfigRef *ProviderConfigRef ProviderConfigRef *ProviderConfigRef
Provider addrs.Provider
DependsOn []hcl.Traversal DependsOn []hcl.Traversal

View File

@ -7,3 +7,13 @@ terraform {
} }
provider "bar-test" {} provider "bar-test" {}
resource "test_instance" "explicit" {
// explicitly setting provider bar-test
provider = bar-test
}
resource "test_instance" "implicit" {
// since the provider type name "test" does not match an entry in
// required_providers, the default provider "test" should be used
}

View File

@ -11,3 +11,12 @@ provider "foo-test" {}
module "child" { module "child" {
source = "./child" source = "./child"
} }
resource "test_instance" "explicit" {
provider = foo-test
}
resource "test_instance" "implicit" {
// since the provider type name "test" does not match an entry in
// required_providers, the default provider "test" should be used
}

View File

@ -0,0 +1,3 @@
resource "test_instance" "explicit" {
provider = bar-test
}

View File

@ -0,0 +1,17 @@
terraform {
required_providers {
foo-test = {
source = "foo/test"
}
bar-test = {
source = "bar/test"
}
}
}
resource "test_instance" "explicit" {
provider = foo-test
}
// the provider for this resource should default to "hashicorp/test"
resource "test_instance" "default" {}