opentofu/internal/terraform/node_resource_abstract_instance_test.go
James Bardin 8e18922170 ProvidedBy should return the resolved provider
Once the ProviderTransformer has resolved and set the exact provider,
the ProvidedBy method should return that exact provider again.

We can hoist the stored provider addr into the AbstractInstance and
avoid the method duplication and slight differences between the
implementations.
2022-11-22 09:41:53 -05:00

184 lines
5.2 KiB
Go

package terraform
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/internal/addrs"
"github.com/hashicorp/terraform/internal/configs"
"github.com/hashicorp/terraform/internal/configs/configschema"
"github.com/hashicorp/terraform/internal/states"
"github.com/zclconf/go-cty/cty"
)
func TestNodeAbstractResourceInstanceProvider(t *testing.T) {
tests := []struct {
Addr addrs.AbsResourceInstance
Config *configs.Resource
StoredProviderConfig addrs.AbsProviderConfig
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.DefaultProviderRegistryHost,
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.DefaultProviderRegistryHost,
Namespace: "awesomecorp",
Type: "happycloud",
},
},
// The config overrides the default behavior.
Want: addrs.Provider{
Hostname: addrs.DefaultProviderRegistryHost,
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.DefaultProviderRegistryHost,
Namespace: "awesomecorp",
Type: "happycloud",
},
},
// The config overrides the default behavior.
Want: addrs.Provider{
Hostname: addrs.DefaultProviderRegistryHost,
Namespace: "awesomecorp",
Type: "happycloud",
},
},
{
Addr: addrs.Resource{
Mode: addrs.DataResourceMode,
Type: "null_resource",
Name: "baz",
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
Config: nil,
StoredProviderConfig: addrs.AbsProviderConfig{
Module: addrs.RootModule,
Provider: addrs.Provider{
Hostname: addrs.DefaultProviderRegistryHost,
Namespace: "awesomecorp",
Type: "null",
},
},
// The stored provider config overrides the default behavior.
Want: addrs.Provider{
Hostname: addrs.DefaultProviderRegistryHost,
Namespace: "awesomecorp",
Type: "null",
},
},
}
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{
Addr: test.Addr.ConfigResource(),
Config: test.Config,
storedProviderConfig: test.StoredProviderConfig,
},
}
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 TestNodeAbstractResourceInstance_WriteResourceInstanceState(t *testing.T) {
state := states.NewState()
ctx := new(MockEvalContext)
ctx.StateState = state.SyncWrapper()
ctx.PathPath = addrs.RootModuleInstance
mockProvider := mockProviderWithResourceTypeSchema("aws_instance", &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"id": {
Type: cty.String,
Optional: true,
},
},
})
obj := &states.ResourceInstanceObject{
Value: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("i-abc123"),
}),
Status: states.ObjectReady,
}
node := &NodeAbstractResourceInstance{
Addr: mustResourceInstanceAddr("aws_instance.foo"),
// instanceState: obj,
NodeAbstractResource: NodeAbstractResource{
ResolvedProvider: mustProviderConfig(`provider["registry.terraform.io/hashicorp/aws"]`),
},
}
ctx.ProviderProvider = mockProvider
ctx.ProviderSchemaSchema = mockProvider.ProviderSchema()
err := node.writeResourceInstanceState(ctx, obj, workingState)
if err != nil {
t.Fatalf("unexpected error: %s", err.Error())
}
checkStateString(t, state, `
aws_instance.foo:
ID = i-abc123
provider = provider["registry.terraform.io/hashicorp/aws"]
`)
}