opentofu/configs/config_test.go
Alisdair McDiarmid 9263b28e99 command/init: Improve diags for legacy providers
When initializing a configuration which refers to re-namespaced legacy
providers, we attempt to detect this and display a diagnostic message.
Previously this message would direct the user to run the 0.13upgrade
command, but without specifying in which directories.

This commit detects which modules are using the providers in question,
and for local modules displays a list of upgrade commands which specify
the source directories of these modules.

For remote modules, we display a separate list noting that they need to
be upgraded elsewhere, providing both the local module call name and the
module source address.
2020-06-12 09:57:01 -04:00

233 lines
7.3 KiB
Go

package configs
import (
"testing"
"github.com/go-test/deep"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/zclconf/go-cty/cty"
version "github.com/hashicorp/go-version"
"github.com/hashicorp/hcl/v2/hclsyntax"
svchost "github.com/hashicorp/terraform-svchost"
"github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/internal/getproviders"
)
func TestConfigProviderTypes(t *testing.T) {
// nil cfg should return an empty map
got := NewEmptyConfig().ProviderTypes()
if len(got) != 0 {
t.Fatal("expected empty result from empty config")
}
cfg, diags := testModuleConfigFromFile("testdata/valid-files/providers-explicit-implied.tf")
if diags.HasErrors() {
t.Fatal(diags.Error())
}
got = cfg.ProviderTypes()
want := []addrs.Provider{
addrs.NewDefaultProvider("aws"),
addrs.NewDefaultProvider("null"),
addrs.NewDefaultProvider("template"),
}
for _, problem := range deep.Equal(got, want) {
t.Error(problem)
}
}
func TestConfigProviderTypes_nested(t *testing.T) {
// basic test with a nil config
c := NewEmptyConfig()
got := c.ProviderTypes()
if len(got) != 0 {
t.Fatalf("wrong result!\ngot: %#v\nwant: nil\n", got)
}
// config with two provider sources, and one implicit (default) provider
cfg, diags := testNestedModuleConfigFromDir(t, "testdata/valid-modules/nested-providers-fqns")
if diags.HasErrors() {
t.Fatal(diags.Error())
}
got = cfg.ProviderTypes()
want := []addrs.Provider{
addrs.NewProvider(addrs.DefaultRegistryHost, "bar", "test"),
addrs.NewProvider(addrs.DefaultRegistryHost, "foo", "test"),
addrs.NewDefaultProvider("test"),
}
for _, problem := range deep.Equal(got, want) {
t.Error(problem)
}
}
func TestConfigResolveAbsProviderAddr(t *testing.T) {
cfg, diags := testModuleConfigFromDir("testdata/providers-explicit-fqn")
if diags.HasErrors() {
t.Fatal(diags.Error())
}
t.Run("already absolute", func(t *testing.T) {
addr := addrs.AbsProviderConfig{
Module: addrs.RootModule,
Provider: addrs.NewLegacyProvider("test"),
Alias: "boop",
}
got := cfg.ResolveAbsProviderAddr(addr, addrs.RootModule)
if got, want := got.String(), addr.String(); got != want {
t.Errorf("wrong result\ngot: %s\nwant: %s", got, want)
}
})
t.Run("local, implied mapping", func(t *testing.T) {
addr := addrs.LocalProviderConfig{
LocalName: "implied",
Alias: "boop",
}
got := cfg.ResolveAbsProviderAddr(addr, addrs.RootModule)
want := addrs.AbsProviderConfig{
Module: addrs.RootModule,
Provider: addrs.NewDefaultProvider("implied"),
Alias: "boop",
}
if got, want := got.String(), want.String(); got != want {
t.Errorf("wrong result\ngot: %s\nwant: %s", got, want)
}
})
t.Run("local, explicit mapping", func(t *testing.T) {
addr := addrs.LocalProviderConfig{
LocalName: "foo-test", // this is explicitly set in the config
Alias: "boop",
}
got := cfg.ResolveAbsProviderAddr(addr, addrs.RootModule)
want := addrs.AbsProviderConfig{
Module: addrs.RootModule,
Provider: addrs.NewProvider(addrs.DefaultRegistryHost, "foo", "test"),
Alias: "boop",
}
if got, want := got.String(), want.String(); got != want {
t.Errorf("wrong result\ngot: %s\nwant: %s", got, want)
}
})
}
func TestConfigProviderRequirements(t *testing.T) {
cfg, diags := testNestedModuleConfigFromDir(t, "testdata/provider-reqs")
assertNoDiagnostics(t, diags)
tlsProvider := addrs.NewProvider(
addrs.DefaultRegistryHost,
"hashicorp", "tls",
)
happycloudProvider := addrs.NewProvider(
svchost.Hostname("tf.example.com"),
"awesomecorp", "happycloud",
)
nullProvider := addrs.NewDefaultProvider("null")
randomProvider := addrs.NewDefaultProvider("random")
impliedProvider := addrs.NewDefaultProvider("implied")
terraformProvider := addrs.NewBuiltInProvider("terraform")
configuredProvider := addrs.NewDefaultProvider("configured")
got, diags := cfg.ProviderRequirements()
assertNoDiagnostics(t, diags)
want := getproviders.Requirements{
// the nullProvider constraints from the two modules are merged
nullProvider: getproviders.MustParseVersionConstraints("~> 2.0.0, 2.0.1"),
randomProvider: getproviders.MustParseVersionConstraints("~> 1.2.0"),
tlsProvider: getproviders.MustParseVersionConstraints("~> 3.0"),
configuredProvider: getproviders.MustParseVersionConstraints("~> 1.4"),
impliedProvider: nil,
happycloudProvider: nil,
terraformProvider: nil,
}
if diff := cmp.Diff(want, got); diff != "" {
t.Errorf("wrong result\n%s", diff)
}
}
func TestConfigProviderRequirementsByModule(t *testing.T) {
cfg, diags := testNestedModuleConfigFromDir(t, "testdata/provider-reqs")
assertNoDiagnostics(t, diags)
tlsProvider := addrs.NewProvider(
addrs.DefaultRegistryHost,
"hashicorp", "tls",
)
happycloudProvider := addrs.NewProvider(
svchost.Hostname("tf.example.com"),
"awesomecorp", "happycloud",
)
nullProvider := addrs.NewDefaultProvider("null")
randomProvider := addrs.NewDefaultProvider("random")
impliedProvider := addrs.NewDefaultProvider("implied")
terraformProvider := addrs.NewBuiltInProvider("terraform")
configuredProvider := addrs.NewDefaultProvider("configured")
got, diags := cfg.ProviderRequirementsByModule()
assertNoDiagnostics(t, diags)
want := &ModuleRequirements{
Name: "",
SourceAddr: "",
SourceDir: "testdata/provider-reqs",
Requirements: getproviders.Requirements{
// Only the root module's version is present here
nullProvider: getproviders.MustParseVersionConstraints("~> 2.0.0"),
randomProvider: getproviders.MustParseVersionConstraints("~> 1.2.0"),
tlsProvider: getproviders.MustParseVersionConstraints("~> 3.0"),
configuredProvider: getproviders.MustParseVersionConstraints("~> 1.4"),
impliedProvider: nil,
terraformProvider: nil,
},
Children: map[string]*ModuleRequirements{
"kinder": {
Name: "kinder",
SourceAddr: "./child",
SourceDir: "testdata/provider-reqs/child",
Requirements: getproviders.Requirements{
nullProvider: getproviders.MustParseVersionConstraints("= 2.0.1"),
happycloudProvider: nil,
},
Children: map[string]*ModuleRequirements{},
},
},
}
ignore := cmpopts.IgnoreUnexported(version.Constraint{}, cty.Value{}, hclsyntax.Body{})
if diff := cmp.Diff(want, got, ignore); diff != "" {
t.Errorf("wrong result\n%s", diff)
}
}
func TestConfigProviderForConfigAddr(t *testing.T) {
cfg, diags := testModuleConfigFromDir("testdata/valid-modules/providers-fqns")
assertNoDiagnostics(t, diags)
got := cfg.ProviderForConfigAddr(addrs.NewDefaultLocalProviderConfig("foo-test"))
want := addrs.NewProvider(addrs.DefaultRegistryHost, "foo", "test")
if !got.Equals(want) {
t.Errorf("wrong result\ngot: %s\nwant: %s", got, want)
}
// now check a provider that isn't in the configuration. It should return a DefaultProvider.
got = cfg.ProviderForConfigAddr(addrs.NewDefaultLocalProviderConfig("bar-test"))
want = addrs.NewDefaultProvider("bar-test")
if !got.Equals(want) {
t.Errorf("wrong result\ngot: %s\nwant: %s", got, want)
}
}
func TestConfigAddProviderRequirements(t *testing.T) {
cfg, diags := testModuleConfigFromFile("testdata/valid-files/providers-explicit-implied.tf")
assertNoDiagnostics(t, diags)
reqs := getproviders.Requirements{
addrs.NewDefaultProvider("null"): nil,
}
diags = cfg.addProviderRequirements(reqs)
assertNoDiagnostics(t, diags)
}