diff --git a/terraform/node_resource_abstract.go b/terraform/node_resource_abstract.go index 35c6ce27ff..50abadb387 100644 --- a/terraform/node_resource_abstract.go +++ b/terraform/node_resource_abstract.go @@ -360,7 +360,7 @@ func (n *NodeAbstractResourceInstance) Provider() addrs.Provider { if n.Config != nil { return n.Config.Provider } - return addrs.NewDefaultProvider(n.Addr.Resource.ContainingResource().ImpliedProvider()) + return addrs.ImpliedProviderForUnqualifiedType(n.Addr.Resource.ContainingResource().ImpliedProvider()) } // GraphNodeProvisionerConsumer diff --git a/terraform/node_resource_abstract_test.go b/terraform/node_resource_abstract_test.go new file mode 100644 index 0000000000..570f84079f --- /dev/null +++ b/terraform/node_resource_abstract_test.go @@ -0,0 +1,211 @@ +package terraform + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/addrs" + "github.com/hashicorp/terraform/configs" +) + +func TestNodeAbstractResourceProvider(t *testing.T) { + tests := []struct { + Addr addrs.ConfigResource + Config *configs.Resource + Want addrs.Provider + }{ + { + Addr: addrs.Resource{ + Mode: addrs.ManagedResourceMode, + Type: "null_resource", + Name: "baz", + }.InModule(addrs.RootModule), + Want: addrs.Provider{ + Hostname: addrs.DefaultRegistryHost, + Namespace: "hashicorp", + Type: "null", + }, + }, + { + Addr: addrs.Resource{ + Mode: addrs.DataResourceMode, + Type: "terraform_remote_state", + Name: "baz", + }.InModule(addrs.RootModule), + Want: addrs.Provider{ + // As a special case, the type prefix "terraform_" maps to + // the builtin provider, not the default one. + Hostname: addrs.BuiltInProviderHost, + Namespace: addrs.BuiltInProviderNamespace, + Type: "terraform", + }, + }, + { + Addr: addrs.Resource{ + Mode: addrs.ManagedResourceMode, + Type: "null_resource", + Name: "baz", + }.InModule(addrs.RootModule), + Config: &configs.Resource{ + // Just enough configs.Resource for the Provider method. Not + // actually valid for general use. + Provider: addrs.Provider{ + Hostname: addrs.DefaultRegistryHost, + Namespace: "awesomecorp", + Type: "happycloud", + }, + }, + // The config overrides the default behavior. + Want: addrs.Provider{ + Hostname: addrs.DefaultRegistryHost, + Namespace: "awesomecorp", + Type: "happycloud", + }, + }, + { + Addr: addrs.Resource{ + Mode: addrs.DataResourceMode, + Type: "terraform_remote_state", + Name: "baz", + }.InModule(addrs.RootModule), + Config: &configs.Resource{ + // Just enough configs.Resource for the Provider method. Not + // actually valid for general use. + Provider: addrs.Provider{ + Hostname: addrs.DefaultRegistryHost, + Namespace: "awesomecorp", + Type: "happycloud", + }, + }, + // The config overrides the default behavior. + Want: addrs.Provider{ + Hostname: addrs.DefaultRegistryHost, + Namespace: "awesomecorp", + Type: "happycloud", + }, + }, + } + + for _, test := range tests { + var name string + if test.Config != nil { + name = fmt.Sprintf("%s with configured %s", test.Addr, test.Config.Provider) + } else { + name = fmt.Sprintf("%s with no configuration", test.Addr) + } + t.Run(name, func(t *testing.T) { + node := &NodeAbstractResource{ + // Just enough NodeAbstractResource for the Provider function. + // (This would not be valid for some other functions.) + Addr: test.Addr, + Config: test.Config, + } + got := node.Provider() + if got != test.Want { + t.Errorf("wrong result\naddr: %s\nconfig: %#v\ngot: %s\nwant: %s", test.Addr, test.Config, got, test.Want) + } + }) + } +} + +func TestNodeAbstractResourceInstanceProvider(t *testing.T) { + tests := []struct { + Addr addrs.AbsResourceInstance + Config *configs.Resource + Want addrs.Provider + }{ + { + Addr: addrs.Resource{ + Mode: addrs.ManagedResourceMode, + Type: "null_resource", + Name: "baz", + }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), + Want: addrs.Provider{ + Hostname: addrs.DefaultRegistryHost, + Namespace: "hashicorp", + Type: "null", + }, + }, + { + Addr: addrs.Resource{ + Mode: addrs.DataResourceMode, + Type: "terraform_remote_state", + Name: "baz", + }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), + Want: addrs.Provider{ + // As a special case, the type prefix "terraform_" maps to + // the builtin provider, not the default one. + Hostname: addrs.BuiltInProviderHost, + Namespace: addrs.BuiltInProviderNamespace, + Type: "terraform", + }, + }, + { + Addr: addrs.Resource{ + Mode: addrs.ManagedResourceMode, + Type: "null_resource", + Name: "baz", + }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), + Config: &configs.Resource{ + // Just enough configs.Resource for the Provider method. Not + // actually valid for general use. + Provider: addrs.Provider{ + Hostname: addrs.DefaultRegistryHost, + Namespace: "awesomecorp", + Type: "happycloud", + }, + }, + // The config overrides the default behavior. + Want: addrs.Provider{ + Hostname: addrs.DefaultRegistryHost, + Namespace: "awesomecorp", + Type: "happycloud", + }, + }, + { + Addr: addrs.Resource{ + Mode: addrs.DataResourceMode, + Type: "terraform_remote_state", + Name: "baz", + }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), + Config: &configs.Resource{ + // Just enough configs.Resource for the Provider method. Not + // actually valid for general use. + Provider: addrs.Provider{ + Hostname: addrs.DefaultRegistryHost, + Namespace: "awesomecorp", + Type: "happycloud", + }, + }, + // The config overrides the default behavior. + Want: addrs.Provider{ + Hostname: addrs.DefaultRegistryHost, + Namespace: "awesomecorp", + Type: "happycloud", + }, + }, + } + + for _, test := range tests { + var name string + if test.Config != nil { + name = fmt.Sprintf("%s with configured %s", test.Addr, test.Config.Provider) + } else { + name = fmt.Sprintf("%s with no configuration", test.Addr) + } + t.Run(name, func(t *testing.T) { + node := &NodeAbstractResourceInstance{ + // Just enough NodeAbstractResourceInstance for the Provider + // function. (This would not be valid for some other functions.) + Addr: test.Addr, + NodeAbstractResource: NodeAbstractResource{ + Config: test.Config, + }, + } + got := node.Provider() + if got != test.Want { + t.Errorf("wrong result\naddr: %s\nconfig: %#v\ngot: %s\nwant: %s", test.Addr, test.Config, got, test.Want) + } + }) + } +}