2024-02-08 03:48:59 -06:00
|
|
|
// Copyright (c) The OpenTofu Authors
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
// Copyright (c) 2023 HashiCorp, Inc.
|
2023-05-02 10:33:06 -05:00
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
various: helpers for collecting necessary provider types
Since schemas are required to interpret provider, resource, and
provisioner attributes in configs, states, and plans, these helpers intend
to make it easier to gather up the the necessary provider types in order
to preload all of the needed schemas before beginning further processing.
Config.ProviderTypes returns directly the list of provider types, since
at this level further detail is not useful: we've not yet run the
provider allocation algorithm, and so the only thing we can reliably
extract here is provider types themselves.
State.ProviderAddrs and Plan.ProviderAddrs each return a list of
absolute provider addresses, which can then be turned into a list of
provider types using the new helper providers.AddressedTypesAbs.
Since we're already using configs.Config throughout core, this also
updates the terraform.LoadSchemas helper to use Config.ProviderTypes
to find the necessary providers, rather than implementing its own
discovery logic. states.State is not yet plumbed in, so we cannot yet
use State.ProviderAddrs to deal with the state but there's a TODO comment
to remind us to update that in a later commit when we swap out
terraform.State for states.State.
A later commit will probably refactor this further so that we can easily
obtain schema for the providers needed to interpret a plan too, but that
is deferred here because further work is required to make core work with
the new plan types first. At that point, terraform.LoadSchemas may become
providers.LoadSchemas with a different interface that just accepts lists
of provider and provisioner names that have been gathered by the caller
using these new helpers.
2018-06-21 19:39:27 -05:00
|
|
|
package configs
|
|
|
|
|
|
|
|
import (
|
2023-07-10 08:33:15 -05:00
|
|
|
"bytes"
|
|
|
|
"fmt"
|
2023-05-11 02:04:39 -05:00
|
|
|
"os"
|
2024-02-21 13:39:59 -06:00
|
|
|
"path/filepath"
|
2023-07-10 08:33:15 -05:00
|
|
|
"strings"
|
various: helpers for collecting necessary provider types
Since schemas are required to interpret provider, resource, and
provisioner attributes in configs, states, and plans, these helpers intend
to make it easier to gather up the the necessary provider types in order
to preload all of the needed schemas before beginning further processing.
Config.ProviderTypes returns directly the list of provider types, since
at this level further detail is not useful: we've not yet run the
provider allocation algorithm, and so the only thing we can reliably
extract here is provider types themselves.
State.ProviderAddrs and Plan.ProviderAddrs each return a list of
absolute provider addresses, which can then be turned into a list of
provider types using the new helper providers.AddressedTypesAbs.
Since we're already using configs.Config throughout core, this also
updates the terraform.LoadSchemas helper to use Config.ProviderTypes
to find the necessary providers, rather than implementing its own
discovery logic. states.State is not yet plumbed in, so we cannot yet
use State.ProviderAddrs to deal with the state but there's a TODO comment
to remind us to update that in a later commit when we swap out
terraform.State for states.State.
A later commit will probably refactor this further so that we can easily
obtain schema for the providers needed to interpret a plan too, but that
is deferred here because further work is required to make core work with
the new plan types first. At that point, terraform.LoadSchemas may become
providers.LoadSchemas with a different interface that just accepts lists
of provider and provisioner names that have been gathered by the caller
using these new helpers.
2018-06-21 19:39:27 -05:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/go-test/deep"
|
2020-03-26 14:04:48 -05:00
|
|
|
"github.com/google/go-cmp/cmp"
|
2020-06-09 12:32:56 -05:00
|
|
|
"github.com/google/go-cmp/cmp/cmpopts"
|
2023-07-10 08:33:15 -05:00
|
|
|
"github.com/hashicorp/hcl/v2"
|
|
|
|
"github.com/hashicorp/hcl/v2/hclparse"
|
2020-06-09 12:32:56 -05:00
|
|
|
"github.com/zclconf/go-cty/cty"
|
Initial steps towards AbsProviderConfig/LocalProviderConfig separation (#23978)
* Introduce "Local" terminology for non-absolute provider config addresses
In a future change AbsProviderConfig and LocalProviderConfig are going to
become two entirely distinct types, rather than Abs embedding Local as
written here. This naming change is in preparation for that subsequent
work, which will also include introducing a new "ProviderConfig" type
that is an interface that AbsProviderConfig and LocalProviderConfig both
implement.
This is intended to be largely just a naming change to get started, so
we can deal with all of the messy renaming. However, this did also require
a slight change in modeling where the Resource.DefaultProviderConfig
method has become Resource.DefaultProvider returning a Provider address
directly, because this method doesn't have enough information to construct
a true and accurate LocalProviderConfig -- it would need to refer to the
configuration to know what this module is calling the provider it has
selected.
In order to leave a trail to follow for subsequent work, all of the
changes here are intended to ensure that remaining work will become
obvious via compile-time errors when all of the following changes happen:
- The concept of "legacy" provider addresses is removed from the addrs
package, including removing addrs.NewLegacyProvider and
addrs.Provider.LegacyString.
- addrs.AbsProviderConfig stops having addrs.LocalProviderConfig embedded
in it and has an addrs.Provider and a string alias directly instead.
- The provider-schema-handling parts of Terraform core are updated to
work with addrs.Provider to identify providers, rather than legacy
strings.
In particular, there are still several codepaths here making legacy
provider address assumptions (in order to limit the scope of this change)
but I've made sure each one is doing something that relies on at least
one of the above changes not having been made yet.
* addrs: ProviderConfig interface
In a (very) few special situations in the main "terraform" package we need
to make runtime decisions about whether a provider config is absolute
or local.
We currently do that by exploiting the fact that AbsProviderConfig has
LocalProviderConfig nested inside of it and so in the local case we can
just ignore the wrapping AbsProviderConfig and use the embedded value.
In a future change we'll be moving away from that embedding and making
these two types distinct in order to represent that mapping between them
requires consulting a lookup table in the configuration, and so here we
introduce a new interface type ProviderConfig that can represent either
AbsProviderConfig or LocalProviderConfig decided dynamically at runtime.
This also includes the Config.ResolveAbsProviderAddr method that will
eventually be responsible for that local-to-absolute translation, so
that callers with access to the configuration can normalize to an
addrs.AbsProviderConfig given a non-nil addrs.ProviderConfig. That's
currently unused because existing callers are still relying on the
simplistic structural transform, but we'll switch them over in a later
commit.
* rename LocalType to LocalName
Co-authored-by: Kristin Laemmert <mildwonkey@users.noreply.github.com>
2020-01-31 07:23:07 -06:00
|
|
|
|
2020-06-09 12:32:56 -05:00
|
|
|
version "github.com/hashicorp/go-version"
|
|
|
|
"github.com/hashicorp/hcl/v2/hclsyntax"
|
2020-03-26 14:04:48 -05:00
|
|
|
svchost "github.com/hashicorp/terraform-svchost"
|
2023-07-10 08:33:15 -05:00
|
|
|
|
2023-09-20 06:35:35 -05:00
|
|
|
"github.com/opentofu/opentofu/internal/addrs"
|
|
|
|
"github.com/opentofu/opentofu/internal/depsfile"
|
|
|
|
"github.com/opentofu/opentofu/internal/getproviders"
|
various: helpers for collecting necessary provider types
Since schemas are required to interpret provider, resource, and
provisioner attributes in configs, states, and plans, these helpers intend
to make it easier to gather up the the necessary provider types in order
to preload all of the needed schemas before beginning further processing.
Config.ProviderTypes returns directly the list of provider types, since
at this level further detail is not useful: we've not yet run the
provider allocation algorithm, and so the only thing we can reliably
extract here is provider types themselves.
State.ProviderAddrs and Plan.ProviderAddrs each return a list of
absolute provider addresses, which can then be turned into a list of
provider types using the new helper providers.AddressedTypesAbs.
Since we're already using configs.Config throughout core, this also
updates the terraform.LoadSchemas helper to use Config.ProviderTypes
to find the necessary providers, rather than implementing its own
discovery logic. states.State is not yet plumbed in, so we cannot yet
use State.ProviderAddrs to deal with the state but there's a TODO comment
to remind us to update that in a later commit when we swap out
terraform.State for states.State.
A later commit will probably refactor this further so that we can easily
obtain schema for the providers needed to interpret a plan too, but that
is deferred here because further work is required to make core work with
the new plan types first. At that point, terraform.LoadSchemas may become
providers.LoadSchemas with a different interface that just accepts lists
of provider and provisioner names that have been gathered by the caller
using these new helpers.
2018-06-21 19:39:27 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestConfigProviderTypes(t *testing.T) {
|
2020-03-23 08:50:35 -05:00
|
|
|
// nil cfg should return an empty map
|
|
|
|
got := NewEmptyConfig().ProviderTypes()
|
|
|
|
if len(got) != 0 {
|
|
|
|
t.Fatal("expected empty result from empty config")
|
|
|
|
}
|
|
|
|
|
2020-03-12 11:00:00 -05:00
|
|
|
cfg, diags := testModuleConfigFromFile("testdata/valid-files/providers-explicit-implied.tf")
|
various: helpers for collecting necessary provider types
Since schemas are required to interpret provider, resource, and
provisioner attributes in configs, states, and plans, these helpers intend
to make it easier to gather up the the necessary provider types in order
to preload all of the needed schemas before beginning further processing.
Config.ProviderTypes returns directly the list of provider types, since
at this level further detail is not useful: we've not yet run the
provider allocation algorithm, and so the only thing we can reliably
extract here is provider types themselves.
State.ProviderAddrs and Plan.ProviderAddrs each return a list of
absolute provider addresses, which can then be turned into a list of
provider types using the new helper providers.AddressedTypesAbs.
Since we're already using configs.Config throughout core, this also
updates the terraform.LoadSchemas helper to use Config.ProviderTypes
to find the necessary providers, rather than implementing its own
discovery logic. states.State is not yet plumbed in, so we cannot yet
use State.ProviderAddrs to deal with the state but there's a TODO comment
to remind us to update that in a later commit when we swap out
terraform.State for states.State.
A later commit will probably refactor this further so that we can easily
obtain schema for the providers needed to interpret a plan too, but that
is deferred here because further work is required to make core work with
the new plan types first. At that point, terraform.LoadSchemas may become
providers.LoadSchemas with a different interface that just accepts lists
of provider and provisioner names that have been gathered by the caller
using these new helpers.
2018-06-21 19:39:27 -05:00
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatal(diags.Error())
|
|
|
|
}
|
|
|
|
|
2020-03-23 08:50:35 -05:00
|
|
|
got = cfg.ProviderTypes()
|
Initial steps towards AbsProviderConfig/LocalProviderConfig separation (#23978)
* Introduce "Local" terminology for non-absolute provider config addresses
In a future change AbsProviderConfig and LocalProviderConfig are going to
become two entirely distinct types, rather than Abs embedding Local as
written here. This naming change is in preparation for that subsequent
work, which will also include introducing a new "ProviderConfig" type
that is an interface that AbsProviderConfig and LocalProviderConfig both
implement.
This is intended to be largely just a naming change to get started, so
we can deal with all of the messy renaming. However, this did also require
a slight change in modeling where the Resource.DefaultProviderConfig
method has become Resource.DefaultProvider returning a Provider address
directly, because this method doesn't have enough information to construct
a true and accurate LocalProviderConfig -- it would need to refer to the
configuration to know what this module is calling the provider it has
selected.
In order to leave a trail to follow for subsequent work, all of the
changes here are intended to ensure that remaining work will become
obvious via compile-time errors when all of the following changes happen:
- The concept of "legacy" provider addresses is removed from the addrs
package, including removing addrs.NewLegacyProvider and
addrs.Provider.LegacyString.
- addrs.AbsProviderConfig stops having addrs.LocalProviderConfig embedded
in it and has an addrs.Provider and a string alias directly instead.
- The provider-schema-handling parts of Terraform core are updated to
work with addrs.Provider to identify providers, rather than legacy
strings.
In particular, there are still several codepaths here making legacy
provider address assumptions (in order to limit the scope of this change)
but I've made sure each one is doing something that relies on at least
one of the above changes not having been made yet.
* addrs: ProviderConfig interface
In a (very) few special situations in the main "terraform" package we need
to make runtime decisions about whether a provider config is absolute
or local.
We currently do that by exploiting the fact that AbsProviderConfig has
LocalProviderConfig nested inside of it and so in the local case we can
just ignore the wrapping AbsProviderConfig and use the embedded value.
In a future change we'll be moving away from that embedding and making
these two types distinct in order to represent that mapping between them
requires consulting a lookup table in the configuration, and so here we
introduce a new interface type ProviderConfig that can represent either
AbsProviderConfig or LocalProviderConfig decided dynamically at runtime.
This also includes the Config.ResolveAbsProviderAddr method that will
eventually be responsible for that local-to-absolute translation, so
that callers with access to the configuration can normalize to an
addrs.AbsProviderConfig given a non-nil addrs.ProviderConfig. That's
currently unused because existing callers are still relying on the
simplistic structural transform, but we'll switch them over in a later
commit.
* rename LocalType to LocalName
Co-authored-by: Kristin Laemmert <mildwonkey@users.noreply.github.com>
2020-01-31 07:23:07 -06:00
|
|
|
want := []addrs.Provider{
|
2020-03-31 13:03:33 -05:00
|
|
|
addrs.NewDefaultProvider("aws"),
|
2023-05-11 01:38:37 -05:00
|
|
|
addrs.NewDefaultProvider("local"),
|
2020-03-31 13:03:33 -05:00
|
|
|
addrs.NewDefaultProvider("null"),
|
|
|
|
addrs.NewDefaultProvider("template"),
|
2020-09-21 15:32:50 -05:00
|
|
|
addrs.NewDefaultProvider("test"),
|
various: helpers for collecting necessary provider types
Since schemas are required to interpret provider, resource, and
provisioner attributes in configs, states, and plans, these helpers intend
to make it easier to gather up the the necessary provider types in order
to preload all of the needed schemas before beginning further processing.
Config.ProviderTypes returns directly the list of provider types, since
at this level further detail is not useful: we've not yet run the
provider allocation algorithm, and so the only thing we can reliably
extract here is provider types themselves.
State.ProviderAddrs and Plan.ProviderAddrs each return a list of
absolute provider addresses, which can then be turned into a list of
provider types using the new helper providers.AddressedTypesAbs.
Since we're already using configs.Config throughout core, this also
updates the terraform.LoadSchemas helper to use Config.ProviderTypes
to find the necessary providers, rather than implementing its own
discovery logic. states.State is not yet plumbed in, so we cannot yet
use State.ProviderAddrs to deal with the state but there's a TODO comment
to remind us to update that in a later commit when we swap out
terraform.State for states.State.
A later commit will probably refactor this further so that we can easily
obtain schema for the providers needed to interpret a plan too, but that
is deferred here because further work is required to make core work with
the new plan types first. At that point, terraform.LoadSchemas may become
providers.LoadSchemas with a different interface that just accepts lists
of provider and provisioner names that have been gathered by the caller
using these new helpers.
2018-06-21 19:39:27 -05:00
|
|
|
}
|
|
|
|
for _, problem := range deep.Equal(got, want) {
|
|
|
|
t.Error(problem)
|
|
|
|
}
|
|
|
|
}
|
Initial steps towards AbsProviderConfig/LocalProviderConfig separation (#23978)
* Introduce "Local" terminology for non-absolute provider config addresses
In a future change AbsProviderConfig and LocalProviderConfig are going to
become two entirely distinct types, rather than Abs embedding Local as
written here. This naming change is in preparation for that subsequent
work, which will also include introducing a new "ProviderConfig" type
that is an interface that AbsProviderConfig and LocalProviderConfig both
implement.
This is intended to be largely just a naming change to get started, so
we can deal with all of the messy renaming. However, this did also require
a slight change in modeling where the Resource.DefaultProviderConfig
method has become Resource.DefaultProvider returning a Provider address
directly, because this method doesn't have enough information to construct
a true and accurate LocalProviderConfig -- it would need to refer to the
configuration to know what this module is calling the provider it has
selected.
In order to leave a trail to follow for subsequent work, all of the
changes here are intended to ensure that remaining work will become
obvious via compile-time errors when all of the following changes happen:
- The concept of "legacy" provider addresses is removed from the addrs
package, including removing addrs.NewLegacyProvider and
addrs.Provider.LegacyString.
- addrs.AbsProviderConfig stops having addrs.LocalProviderConfig embedded
in it and has an addrs.Provider and a string alias directly instead.
- The provider-schema-handling parts of Terraform core are updated to
work with addrs.Provider to identify providers, rather than legacy
strings.
In particular, there are still several codepaths here making legacy
provider address assumptions (in order to limit the scope of this change)
but I've made sure each one is doing something that relies on at least
one of the above changes not having been made yet.
* addrs: ProviderConfig interface
In a (very) few special situations in the main "terraform" package we need
to make runtime decisions about whether a provider config is absolute
or local.
We currently do that by exploiting the fact that AbsProviderConfig has
LocalProviderConfig nested inside of it and so in the local case we can
just ignore the wrapping AbsProviderConfig and use the embedded value.
In a future change we'll be moving away from that embedding and making
these two types distinct in order to represent that mapping between them
requires consulting a lookup table in the configuration, and so here we
introduce a new interface type ProviderConfig that can represent either
AbsProviderConfig or LocalProviderConfig decided dynamically at runtime.
This also includes the Config.ResolveAbsProviderAddr method that will
eventually be responsible for that local-to-absolute translation, so
that callers with access to the configuration can normalize to an
addrs.AbsProviderConfig given a non-nil addrs.ProviderConfig. That's
currently unused because existing callers are still relying on the
simplistic structural transform, but we'll switch them over in a later
commit.
* rename LocalType to LocalName
Co-authored-by: Kristin Laemmert <mildwonkey@users.noreply.github.com>
2020-01-31 07:23:07 -06:00
|
|
|
|
2020-03-12 11:00:00 -05:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2020-03-16 13:36:16 -05:00
|
|
|
// config with two provider sources, and one implicit (default) provider
|
2020-03-12 11:00:00 -05:00
|
|
|
cfg, diags := testNestedModuleConfigFromDir(t, "testdata/valid-modules/nested-providers-fqns")
|
Initial steps towards AbsProviderConfig/LocalProviderConfig separation (#23978)
* Introduce "Local" terminology for non-absolute provider config addresses
In a future change AbsProviderConfig and LocalProviderConfig are going to
become two entirely distinct types, rather than Abs embedding Local as
written here. This naming change is in preparation for that subsequent
work, which will also include introducing a new "ProviderConfig" type
that is an interface that AbsProviderConfig and LocalProviderConfig both
implement.
This is intended to be largely just a naming change to get started, so
we can deal with all of the messy renaming. However, this did also require
a slight change in modeling where the Resource.DefaultProviderConfig
method has become Resource.DefaultProvider returning a Provider address
directly, because this method doesn't have enough information to construct
a true and accurate LocalProviderConfig -- it would need to refer to the
configuration to know what this module is calling the provider it has
selected.
In order to leave a trail to follow for subsequent work, all of the
changes here are intended to ensure that remaining work will become
obvious via compile-time errors when all of the following changes happen:
- The concept of "legacy" provider addresses is removed from the addrs
package, including removing addrs.NewLegacyProvider and
addrs.Provider.LegacyString.
- addrs.AbsProviderConfig stops having addrs.LocalProviderConfig embedded
in it and has an addrs.Provider and a string alias directly instead.
- The provider-schema-handling parts of Terraform core are updated to
work with addrs.Provider to identify providers, rather than legacy
strings.
In particular, there are still several codepaths here making legacy
provider address assumptions (in order to limit the scope of this change)
but I've made sure each one is doing something that relies on at least
one of the above changes not having been made yet.
* addrs: ProviderConfig interface
In a (very) few special situations in the main "terraform" package we need
to make runtime decisions about whether a provider config is absolute
or local.
We currently do that by exploiting the fact that AbsProviderConfig has
LocalProviderConfig nested inside of it and so in the local case we can
just ignore the wrapping AbsProviderConfig and use the embedded value.
In a future change we'll be moving away from that embedding and making
these two types distinct in order to represent that mapping between them
requires consulting a lookup table in the configuration, and so here we
introduce a new interface type ProviderConfig that can represent either
AbsProviderConfig or LocalProviderConfig decided dynamically at runtime.
This also includes the Config.ResolveAbsProviderAddr method that will
eventually be responsible for that local-to-absolute translation, so
that callers with access to the configuration can normalize to an
addrs.AbsProviderConfig given a non-nil addrs.ProviderConfig. That's
currently unused because existing callers are still relying on the
simplistic structural transform, but we'll switch them over in a later
commit.
* rename LocalType to LocalName
Co-authored-by: Kristin Laemmert <mildwonkey@users.noreply.github.com>
2020-01-31 07:23:07 -06:00
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatal(diags.Error())
|
|
|
|
}
|
|
|
|
|
2020-03-12 11:00:00 -05:00
|
|
|
got = cfg.ProviderTypes()
|
|
|
|
want := []addrs.Provider{
|
2021-05-27 13:09:28 -05:00
|
|
|
addrs.NewProvider(addrs.DefaultProviderRegistryHost, "bar", "test"),
|
|
|
|
addrs.NewProvider(addrs.DefaultProviderRegistryHost, "foo", "test"),
|
2020-03-31 13:03:33 -05:00
|
|
|
addrs.NewDefaultProvider("test"),
|
2020-03-12 11:00:00 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, problem := range deep.Equal(got, want) {
|
|
|
|
t.Error(problem)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfigResolveAbsProviderAddr(t *testing.T) {
|
|
|
|
cfg, diags := testModuleConfigFromDir("testdata/providers-explicit-fqn")
|
Initial steps towards AbsProviderConfig/LocalProviderConfig separation (#23978)
* Introduce "Local" terminology for non-absolute provider config addresses
In a future change AbsProviderConfig and LocalProviderConfig are going to
become two entirely distinct types, rather than Abs embedding Local as
written here. This naming change is in preparation for that subsequent
work, which will also include introducing a new "ProviderConfig" type
that is an interface that AbsProviderConfig and LocalProviderConfig both
implement.
This is intended to be largely just a naming change to get started, so
we can deal with all of the messy renaming. However, this did also require
a slight change in modeling where the Resource.DefaultProviderConfig
method has become Resource.DefaultProvider returning a Provider address
directly, because this method doesn't have enough information to construct
a true and accurate LocalProviderConfig -- it would need to refer to the
configuration to know what this module is calling the provider it has
selected.
In order to leave a trail to follow for subsequent work, all of the
changes here are intended to ensure that remaining work will become
obvious via compile-time errors when all of the following changes happen:
- The concept of "legacy" provider addresses is removed from the addrs
package, including removing addrs.NewLegacyProvider and
addrs.Provider.LegacyString.
- addrs.AbsProviderConfig stops having addrs.LocalProviderConfig embedded
in it and has an addrs.Provider and a string alias directly instead.
- The provider-schema-handling parts of Terraform core are updated to
work with addrs.Provider to identify providers, rather than legacy
strings.
In particular, there are still several codepaths here making legacy
provider address assumptions (in order to limit the scope of this change)
but I've made sure each one is doing something that relies on at least
one of the above changes not having been made yet.
* addrs: ProviderConfig interface
In a (very) few special situations in the main "terraform" package we need
to make runtime decisions about whether a provider config is absolute
or local.
We currently do that by exploiting the fact that AbsProviderConfig has
LocalProviderConfig nested inside of it and so in the local case we can
just ignore the wrapping AbsProviderConfig and use the embedded value.
In a future change we'll be moving away from that embedding and making
these two types distinct in order to represent that mapping between them
requires consulting a lookup table in the configuration, and so here we
introduce a new interface type ProviderConfig that can represent either
AbsProviderConfig or LocalProviderConfig decided dynamically at runtime.
This also includes the Config.ResolveAbsProviderAddr method that will
eventually be responsible for that local-to-absolute translation, so
that callers with access to the configuration can normalize to an
addrs.AbsProviderConfig given a non-nil addrs.ProviderConfig. That's
currently unused because existing callers are still relying on the
simplistic structural transform, but we'll switch them over in a later
commit.
* rename LocalType to LocalName
Co-authored-by: Kristin Laemmert <mildwonkey@users.noreply.github.com>
2020-01-31 07:23:07 -06:00
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatal(diags.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
t.Run("already absolute", func(t *testing.T) {
|
|
|
|
addr := addrs.AbsProviderConfig{
|
2020-03-09 16:11:57 -05:00
|
|
|
Module: addrs.RootModule,
|
2020-10-05 07:33:49 -05:00
|
|
|
Provider: addrs.NewDefaultProvider("test"),
|
2020-02-13 14:32:58 -06:00
|
|
|
Alias: "boop",
|
Initial steps towards AbsProviderConfig/LocalProviderConfig separation (#23978)
* Introduce "Local" terminology for non-absolute provider config addresses
In a future change AbsProviderConfig and LocalProviderConfig are going to
become two entirely distinct types, rather than Abs embedding Local as
written here. This naming change is in preparation for that subsequent
work, which will also include introducing a new "ProviderConfig" type
that is an interface that AbsProviderConfig and LocalProviderConfig both
implement.
This is intended to be largely just a naming change to get started, so
we can deal with all of the messy renaming. However, this did also require
a slight change in modeling where the Resource.DefaultProviderConfig
method has become Resource.DefaultProvider returning a Provider address
directly, because this method doesn't have enough information to construct
a true and accurate LocalProviderConfig -- it would need to refer to the
configuration to know what this module is calling the provider it has
selected.
In order to leave a trail to follow for subsequent work, all of the
changes here are intended to ensure that remaining work will become
obvious via compile-time errors when all of the following changes happen:
- The concept of "legacy" provider addresses is removed from the addrs
package, including removing addrs.NewLegacyProvider and
addrs.Provider.LegacyString.
- addrs.AbsProviderConfig stops having addrs.LocalProviderConfig embedded
in it and has an addrs.Provider and a string alias directly instead.
- The provider-schema-handling parts of Terraform core are updated to
work with addrs.Provider to identify providers, rather than legacy
strings.
In particular, there are still several codepaths here making legacy
provider address assumptions (in order to limit the scope of this change)
but I've made sure each one is doing something that relies on at least
one of the above changes not having been made yet.
* addrs: ProviderConfig interface
In a (very) few special situations in the main "terraform" package we need
to make runtime decisions about whether a provider config is absolute
or local.
We currently do that by exploiting the fact that AbsProviderConfig has
LocalProviderConfig nested inside of it and so in the local case we can
just ignore the wrapping AbsProviderConfig and use the embedded value.
In a future change we'll be moving away from that embedding and making
these two types distinct in order to represent that mapping between them
requires consulting a lookup table in the configuration, and so here we
introduce a new interface type ProviderConfig that can represent either
AbsProviderConfig or LocalProviderConfig decided dynamically at runtime.
This also includes the Config.ResolveAbsProviderAddr method that will
eventually be responsible for that local-to-absolute translation, so
that callers with access to the configuration can normalize to an
addrs.AbsProviderConfig given a non-nil addrs.ProviderConfig. That's
currently unused because existing callers are still relying on the
simplistic structural transform, but we'll switch them over in a later
commit.
* rename LocalType to LocalName
Co-authored-by: Kristin Laemmert <mildwonkey@users.noreply.github.com>
2020-01-31 07:23:07 -06:00
|
|
|
}
|
2020-03-09 16:11:57 -05:00
|
|
|
got := cfg.ResolveAbsProviderAddr(addr, addrs.RootModule)
|
Initial steps towards AbsProviderConfig/LocalProviderConfig separation (#23978)
* Introduce "Local" terminology for non-absolute provider config addresses
In a future change AbsProviderConfig and LocalProviderConfig are going to
become two entirely distinct types, rather than Abs embedding Local as
written here. This naming change is in preparation for that subsequent
work, which will also include introducing a new "ProviderConfig" type
that is an interface that AbsProviderConfig and LocalProviderConfig both
implement.
This is intended to be largely just a naming change to get started, so
we can deal with all of the messy renaming. However, this did also require
a slight change in modeling where the Resource.DefaultProviderConfig
method has become Resource.DefaultProvider returning a Provider address
directly, because this method doesn't have enough information to construct
a true and accurate LocalProviderConfig -- it would need to refer to the
configuration to know what this module is calling the provider it has
selected.
In order to leave a trail to follow for subsequent work, all of the
changes here are intended to ensure that remaining work will become
obvious via compile-time errors when all of the following changes happen:
- The concept of "legacy" provider addresses is removed from the addrs
package, including removing addrs.NewLegacyProvider and
addrs.Provider.LegacyString.
- addrs.AbsProviderConfig stops having addrs.LocalProviderConfig embedded
in it and has an addrs.Provider and a string alias directly instead.
- The provider-schema-handling parts of Terraform core are updated to
work with addrs.Provider to identify providers, rather than legacy
strings.
In particular, there are still several codepaths here making legacy
provider address assumptions (in order to limit the scope of this change)
but I've made sure each one is doing something that relies on at least
one of the above changes not having been made yet.
* addrs: ProviderConfig interface
In a (very) few special situations in the main "terraform" package we need
to make runtime decisions about whether a provider config is absolute
or local.
We currently do that by exploiting the fact that AbsProviderConfig has
LocalProviderConfig nested inside of it and so in the local case we can
just ignore the wrapping AbsProviderConfig and use the embedded value.
In a future change we'll be moving away from that embedding and making
these two types distinct in order to represent that mapping between them
requires consulting a lookup table in the configuration, and so here we
introduce a new interface type ProviderConfig that can represent either
AbsProviderConfig or LocalProviderConfig decided dynamically at runtime.
This also includes the Config.ResolveAbsProviderAddr method that will
eventually be responsible for that local-to-absolute translation, so
that callers with access to the configuration can normalize to an
addrs.AbsProviderConfig given a non-nil addrs.ProviderConfig. That's
currently unused because existing callers are still relying on the
simplistic structural transform, but we'll switch them over in a later
commit.
* rename LocalType to LocalName
Co-authored-by: Kristin Laemmert <mildwonkey@users.noreply.github.com>
2020-01-31 07:23:07 -06:00
|
|
|
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",
|
|
|
|
}
|
2020-03-09 16:11:57 -05:00
|
|
|
got := cfg.ResolveAbsProviderAddr(addr, addrs.RootModule)
|
Initial steps towards AbsProviderConfig/LocalProviderConfig separation (#23978)
* Introduce "Local" terminology for non-absolute provider config addresses
In a future change AbsProviderConfig and LocalProviderConfig are going to
become two entirely distinct types, rather than Abs embedding Local as
written here. This naming change is in preparation for that subsequent
work, which will also include introducing a new "ProviderConfig" type
that is an interface that AbsProviderConfig and LocalProviderConfig both
implement.
This is intended to be largely just a naming change to get started, so
we can deal with all of the messy renaming. However, this did also require
a slight change in modeling where the Resource.DefaultProviderConfig
method has become Resource.DefaultProvider returning a Provider address
directly, because this method doesn't have enough information to construct
a true and accurate LocalProviderConfig -- it would need to refer to the
configuration to know what this module is calling the provider it has
selected.
In order to leave a trail to follow for subsequent work, all of the
changes here are intended to ensure that remaining work will become
obvious via compile-time errors when all of the following changes happen:
- The concept of "legacy" provider addresses is removed from the addrs
package, including removing addrs.NewLegacyProvider and
addrs.Provider.LegacyString.
- addrs.AbsProviderConfig stops having addrs.LocalProviderConfig embedded
in it and has an addrs.Provider and a string alias directly instead.
- The provider-schema-handling parts of Terraform core are updated to
work with addrs.Provider to identify providers, rather than legacy
strings.
In particular, there are still several codepaths here making legacy
provider address assumptions (in order to limit the scope of this change)
but I've made sure each one is doing something that relies on at least
one of the above changes not having been made yet.
* addrs: ProviderConfig interface
In a (very) few special situations in the main "terraform" package we need
to make runtime decisions about whether a provider config is absolute
or local.
We currently do that by exploiting the fact that AbsProviderConfig has
LocalProviderConfig nested inside of it and so in the local case we can
just ignore the wrapping AbsProviderConfig and use the embedded value.
In a future change we'll be moving away from that embedding and making
these two types distinct in order to represent that mapping between them
requires consulting a lookup table in the configuration, and so here we
introduce a new interface type ProviderConfig that can represent either
AbsProviderConfig or LocalProviderConfig decided dynamically at runtime.
This also includes the Config.ResolveAbsProviderAddr method that will
eventually be responsible for that local-to-absolute translation, so
that callers with access to the configuration can normalize to an
addrs.AbsProviderConfig given a non-nil addrs.ProviderConfig. That's
currently unused because existing callers are still relying on the
simplistic structural transform, but we'll switch them over in a later
commit.
* rename LocalType to LocalName
Co-authored-by: Kristin Laemmert <mildwonkey@users.noreply.github.com>
2020-01-31 07:23:07 -06:00
|
|
|
want := addrs.AbsProviderConfig{
|
2020-03-31 13:03:33 -05:00
|
|
|
Module: addrs.RootModule,
|
|
|
|
Provider: addrs.NewDefaultProvider("implied"),
|
2020-02-13 14:32:58 -06:00
|
|
|
Alias: "boop",
|
Initial steps towards AbsProviderConfig/LocalProviderConfig separation (#23978)
* Introduce "Local" terminology for non-absolute provider config addresses
In a future change AbsProviderConfig and LocalProviderConfig are going to
become two entirely distinct types, rather than Abs embedding Local as
written here. This naming change is in preparation for that subsequent
work, which will also include introducing a new "ProviderConfig" type
that is an interface that AbsProviderConfig and LocalProviderConfig both
implement.
This is intended to be largely just a naming change to get started, so
we can deal with all of the messy renaming. However, this did also require
a slight change in modeling where the Resource.DefaultProviderConfig
method has become Resource.DefaultProvider returning a Provider address
directly, because this method doesn't have enough information to construct
a true and accurate LocalProviderConfig -- it would need to refer to the
configuration to know what this module is calling the provider it has
selected.
In order to leave a trail to follow for subsequent work, all of the
changes here are intended to ensure that remaining work will become
obvious via compile-time errors when all of the following changes happen:
- The concept of "legacy" provider addresses is removed from the addrs
package, including removing addrs.NewLegacyProvider and
addrs.Provider.LegacyString.
- addrs.AbsProviderConfig stops having addrs.LocalProviderConfig embedded
in it and has an addrs.Provider and a string alias directly instead.
- The provider-schema-handling parts of Terraform core are updated to
work with addrs.Provider to identify providers, rather than legacy
strings.
In particular, there are still several codepaths here making legacy
provider address assumptions (in order to limit the scope of this change)
but I've made sure each one is doing something that relies on at least
one of the above changes not having been made yet.
* addrs: ProviderConfig interface
In a (very) few special situations in the main "terraform" package we need
to make runtime decisions about whether a provider config is absolute
or local.
We currently do that by exploiting the fact that AbsProviderConfig has
LocalProviderConfig nested inside of it and so in the local case we can
just ignore the wrapping AbsProviderConfig and use the embedded value.
In a future change we'll be moving away from that embedding and making
these two types distinct in order to represent that mapping between them
requires consulting a lookup table in the configuration, and so here we
introduce a new interface type ProviderConfig that can represent either
AbsProviderConfig or LocalProviderConfig decided dynamically at runtime.
This also includes the Config.ResolveAbsProviderAddr method that will
eventually be responsible for that local-to-absolute translation, so
that callers with access to the configuration can normalize to an
addrs.AbsProviderConfig given a non-nil addrs.ProviderConfig. That's
currently unused because existing callers are still relying on the
simplistic structural transform, but we'll switch them over in a later
commit.
* rename LocalType to LocalName
Co-authored-by: Kristin Laemmert <mildwonkey@users.noreply.github.com>
2020-01-31 07:23:07 -06:00
|
|
|
}
|
|
|
|
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{
|
2020-02-14 20:10:03 -06:00
|
|
|
LocalName: "foo-test", // this is explicitly set in the config
|
Initial steps towards AbsProviderConfig/LocalProviderConfig separation (#23978)
* Introduce "Local" terminology for non-absolute provider config addresses
In a future change AbsProviderConfig and LocalProviderConfig are going to
become two entirely distinct types, rather than Abs embedding Local as
written here. This naming change is in preparation for that subsequent
work, which will also include introducing a new "ProviderConfig" type
that is an interface that AbsProviderConfig and LocalProviderConfig both
implement.
This is intended to be largely just a naming change to get started, so
we can deal with all of the messy renaming. However, this did also require
a slight change in modeling where the Resource.DefaultProviderConfig
method has become Resource.DefaultProvider returning a Provider address
directly, because this method doesn't have enough information to construct
a true and accurate LocalProviderConfig -- it would need to refer to the
configuration to know what this module is calling the provider it has
selected.
In order to leave a trail to follow for subsequent work, all of the
changes here are intended to ensure that remaining work will become
obvious via compile-time errors when all of the following changes happen:
- The concept of "legacy" provider addresses is removed from the addrs
package, including removing addrs.NewLegacyProvider and
addrs.Provider.LegacyString.
- addrs.AbsProviderConfig stops having addrs.LocalProviderConfig embedded
in it and has an addrs.Provider and a string alias directly instead.
- The provider-schema-handling parts of Terraform core are updated to
work with addrs.Provider to identify providers, rather than legacy
strings.
In particular, there are still several codepaths here making legacy
provider address assumptions (in order to limit the scope of this change)
but I've made sure each one is doing something that relies on at least
one of the above changes not having been made yet.
* addrs: ProviderConfig interface
In a (very) few special situations in the main "terraform" package we need
to make runtime decisions about whether a provider config is absolute
or local.
We currently do that by exploiting the fact that AbsProviderConfig has
LocalProviderConfig nested inside of it and so in the local case we can
just ignore the wrapping AbsProviderConfig and use the embedded value.
In a future change we'll be moving away from that embedding and making
these two types distinct in order to represent that mapping between them
requires consulting a lookup table in the configuration, and so here we
introduce a new interface type ProviderConfig that can represent either
AbsProviderConfig or LocalProviderConfig decided dynamically at runtime.
This also includes the Config.ResolveAbsProviderAddr method that will
eventually be responsible for that local-to-absolute translation, so
that callers with access to the configuration can normalize to an
addrs.AbsProviderConfig given a non-nil addrs.ProviderConfig. That's
currently unused because existing callers are still relying on the
simplistic structural transform, but we'll switch them over in a later
commit.
* rename LocalType to LocalName
Co-authored-by: Kristin Laemmert <mildwonkey@users.noreply.github.com>
2020-01-31 07:23:07 -06:00
|
|
|
Alias: "boop",
|
|
|
|
}
|
2020-03-09 16:11:57 -05:00
|
|
|
got := cfg.ResolveAbsProviderAddr(addr, addrs.RootModule)
|
Initial steps towards AbsProviderConfig/LocalProviderConfig separation (#23978)
* Introduce "Local" terminology for non-absolute provider config addresses
In a future change AbsProviderConfig and LocalProviderConfig are going to
become two entirely distinct types, rather than Abs embedding Local as
written here. This naming change is in preparation for that subsequent
work, which will also include introducing a new "ProviderConfig" type
that is an interface that AbsProviderConfig and LocalProviderConfig both
implement.
This is intended to be largely just a naming change to get started, so
we can deal with all of the messy renaming. However, this did also require
a slight change in modeling where the Resource.DefaultProviderConfig
method has become Resource.DefaultProvider returning a Provider address
directly, because this method doesn't have enough information to construct
a true and accurate LocalProviderConfig -- it would need to refer to the
configuration to know what this module is calling the provider it has
selected.
In order to leave a trail to follow for subsequent work, all of the
changes here are intended to ensure that remaining work will become
obvious via compile-time errors when all of the following changes happen:
- The concept of "legacy" provider addresses is removed from the addrs
package, including removing addrs.NewLegacyProvider and
addrs.Provider.LegacyString.
- addrs.AbsProviderConfig stops having addrs.LocalProviderConfig embedded
in it and has an addrs.Provider and a string alias directly instead.
- The provider-schema-handling parts of Terraform core are updated to
work with addrs.Provider to identify providers, rather than legacy
strings.
In particular, there are still several codepaths here making legacy
provider address assumptions (in order to limit the scope of this change)
but I've made sure each one is doing something that relies on at least
one of the above changes not having been made yet.
* addrs: ProviderConfig interface
In a (very) few special situations in the main "terraform" package we need
to make runtime decisions about whether a provider config is absolute
or local.
We currently do that by exploiting the fact that AbsProviderConfig has
LocalProviderConfig nested inside of it and so in the local case we can
just ignore the wrapping AbsProviderConfig and use the embedded value.
In a future change we'll be moving away from that embedding and making
these two types distinct in order to represent that mapping between them
requires consulting a lookup table in the configuration, and so here we
introduce a new interface type ProviderConfig that can represent either
AbsProviderConfig or LocalProviderConfig decided dynamically at runtime.
This also includes the Config.ResolveAbsProviderAddr method that will
eventually be responsible for that local-to-absolute translation, so
that callers with access to the configuration can normalize to an
addrs.AbsProviderConfig given a non-nil addrs.ProviderConfig. That's
currently unused because existing callers are still relying on the
simplistic structural transform, but we'll switch them over in a later
commit.
* rename LocalType to LocalName
Co-authored-by: Kristin Laemmert <mildwonkey@users.noreply.github.com>
2020-01-31 07:23:07 -06:00
|
|
|
want := addrs.AbsProviderConfig{
|
2020-03-09 16:11:57 -05:00
|
|
|
Module: addrs.RootModule,
|
2021-05-27 13:09:28 -05:00
|
|
|
Provider: addrs.NewProvider(addrs.DefaultProviderRegistryHost, "foo", "test"),
|
2020-02-13 14:32:58 -06:00
|
|
|
Alias: "boop",
|
Initial steps towards AbsProviderConfig/LocalProviderConfig separation (#23978)
* Introduce "Local" terminology for non-absolute provider config addresses
In a future change AbsProviderConfig and LocalProviderConfig are going to
become two entirely distinct types, rather than Abs embedding Local as
written here. This naming change is in preparation for that subsequent
work, which will also include introducing a new "ProviderConfig" type
that is an interface that AbsProviderConfig and LocalProviderConfig both
implement.
This is intended to be largely just a naming change to get started, so
we can deal with all of the messy renaming. However, this did also require
a slight change in modeling where the Resource.DefaultProviderConfig
method has become Resource.DefaultProvider returning a Provider address
directly, because this method doesn't have enough information to construct
a true and accurate LocalProviderConfig -- it would need to refer to the
configuration to know what this module is calling the provider it has
selected.
In order to leave a trail to follow for subsequent work, all of the
changes here are intended to ensure that remaining work will become
obvious via compile-time errors when all of the following changes happen:
- The concept of "legacy" provider addresses is removed from the addrs
package, including removing addrs.NewLegacyProvider and
addrs.Provider.LegacyString.
- addrs.AbsProviderConfig stops having addrs.LocalProviderConfig embedded
in it and has an addrs.Provider and a string alias directly instead.
- The provider-schema-handling parts of Terraform core are updated to
work with addrs.Provider to identify providers, rather than legacy
strings.
In particular, there are still several codepaths here making legacy
provider address assumptions (in order to limit the scope of this change)
but I've made sure each one is doing something that relies on at least
one of the above changes not having been made yet.
* addrs: ProviderConfig interface
In a (very) few special situations in the main "terraform" package we need
to make runtime decisions about whether a provider config is absolute
or local.
We currently do that by exploiting the fact that AbsProviderConfig has
LocalProviderConfig nested inside of it and so in the local case we can
just ignore the wrapping AbsProviderConfig and use the embedded value.
In a future change we'll be moving away from that embedding and making
these two types distinct in order to represent that mapping between them
requires consulting a lookup table in the configuration, and so here we
introduce a new interface type ProviderConfig that can represent either
AbsProviderConfig or LocalProviderConfig decided dynamically at runtime.
This also includes the Config.ResolveAbsProviderAddr method that will
eventually be responsible for that local-to-absolute translation, so
that callers with access to the configuration can normalize to an
addrs.AbsProviderConfig given a non-nil addrs.ProviderConfig. That's
currently unused because existing callers are still relying on the
simplistic structural transform, but we'll switch them over in a later
commit.
* rename LocalType to LocalName
Co-authored-by: Kristin Laemmert <mildwonkey@users.noreply.github.com>
2020-01-31 07:23:07 -06:00
|
|
|
}
|
|
|
|
if got, want := got.String(), want.String(); got != want {
|
|
|
|
t.Errorf("wrong result\ngot: %s\nwant: %s", got, want)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2020-03-12 11:00:00 -05:00
|
|
|
|
2020-03-26 14:04:48 -05:00
|
|
|
func TestConfigProviderRequirements(t *testing.T) {
|
|
|
|
cfg, diags := testNestedModuleConfigFromDir(t, "testdata/provider-reqs")
|
2020-09-08 07:19:00 -05:00
|
|
|
// TODO: Version Constraint Deprecation.
|
|
|
|
// Once we've removed the version argument from provider configuration
|
|
|
|
// blocks, this can go back to expected 0 diagnostics.
|
|
|
|
// assertNoDiagnostics(t, diags)
|
|
|
|
assertDiagnosticCount(t, diags, 1)
|
|
|
|
assertDiagnosticSummary(t, diags, "Version constraints inside provider configuration blocks are deprecated")
|
2020-03-26 14:04:48 -05:00
|
|
|
|
|
|
|
tlsProvider := addrs.NewProvider(
|
2021-05-27 13:09:28 -05:00
|
|
|
addrs.DefaultProviderRegistryHost,
|
2023-12-11 14:10:03 -06:00
|
|
|
"hashicorp", "tls",
|
2020-03-26 14:04:48 -05:00
|
|
|
)
|
|
|
|
happycloudProvider := addrs.NewProvider(
|
|
|
|
svchost.Hostname("tf.example.com"),
|
|
|
|
"awesomecorp", "happycloud",
|
|
|
|
)
|
2020-03-31 13:03:33 -05:00
|
|
|
nullProvider := addrs.NewDefaultProvider("null")
|
|
|
|
randomProvider := addrs.NewDefaultProvider("random")
|
|
|
|
impliedProvider := addrs.NewDefaultProvider("implied")
|
2020-04-01 18:11:15 -05:00
|
|
|
terraformProvider := addrs.NewBuiltInProvider("terraform")
|
2020-04-10 12:26:38 -05:00
|
|
|
configuredProvider := addrs.NewDefaultProvider("configured")
|
2020-06-22 11:13:35 -05:00
|
|
|
grandchildProvider := addrs.NewDefaultProvider("grandchild")
|
2020-03-26 14:04:48 -05:00
|
|
|
|
|
|
|
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"),
|
2020-04-10 12:26:38 -05:00
|
|
|
configuredProvider: getproviders.MustParseVersionConstraints("~> 1.4"),
|
2020-03-26 14:04:48 -05:00
|
|
|
impliedProvider: nil,
|
|
|
|
happycloudProvider: nil,
|
2020-04-01 18:11:15 -05:00
|
|
|
terraformProvider: nil,
|
2020-06-22 11:13:35 -05:00
|
|
|
grandchildProvider: nil,
|
2020-03-26 14:04:48 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if diff := cmp.Diff(want, got); diff != "" {
|
|
|
|
t.Errorf("wrong result\n%s", diff)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-10 08:33:15 -05:00
|
|
|
func TestConfigProviderRequirementsInclTests(t *testing.T) {
|
|
|
|
cfg, diags := testNestedModuleConfigFromDirWithTests(t, "testdata/provider-reqs-with-tests")
|
|
|
|
// TODO: Version Constraint Deprecation.
|
|
|
|
// Once we've removed the version argument from provider configuration
|
|
|
|
// blocks, this can go back to expected 0 diagnostics.
|
|
|
|
// assertNoDiagnostics(t, diags)
|
|
|
|
assertDiagnosticCount(t, diags, 1)
|
|
|
|
assertDiagnosticSummary(t, diags, "Version constraints inside provider configuration blocks are deprecated")
|
|
|
|
|
|
|
|
tlsProvider := addrs.NewProvider(
|
|
|
|
addrs.DefaultProviderRegistryHost,
|
2023-12-11 14:10:03 -06:00
|
|
|
"hashicorp", "tls",
|
2023-07-10 08:33:15 -05:00
|
|
|
)
|
|
|
|
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"),
|
|
|
|
randomProvider: getproviders.MustParseVersionConstraints("~> 1.2.0"),
|
|
|
|
tlsProvider: getproviders.MustParseVersionConstraints("~> 3.0"),
|
|
|
|
configuredProvider: getproviders.MustParseVersionConstraints("~> 1.4"),
|
|
|
|
impliedProvider: nil,
|
|
|
|
terraformProvider: nil,
|
|
|
|
}
|
|
|
|
|
|
|
|
if diff := cmp.Diff(want, got); diff != "" {
|
|
|
|
t.Errorf("wrong result\n%s", diff)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-09 13:00:10 -05:00
|
|
|
func TestConfigProviderRequirementsDuplicate(t *testing.T) {
|
|
|
|
_, diags := testNestedModuleConfigFromDir(t, "testdata/duplicate-local-name")
|
2022-06-15 10:28:45 -05:00
|
|
|
assertDiagnosticCount(t, diags, 3)
|
2022-06-09 13:00:10 -05:00
|
|
|
assertDiagnosticSummary(t, diags, "Duplicate required provider")
|
|
|
|
}
|
|
|
|
|
2021-02-05 13:01:58 -06:00
|
|
|
func TestConfigProviderRequirementsShallow(t *testing.T) {
|
|
|
|
cfg, diags := testNestedModuleConfigFromDir(t, "testdata/provider-reqs")
|
|
|
|
// TODO: Version Constraint Deprecation.
|
|
|
|
// Once we've removed the version argument from provider configuration
|
|
|
|
// blocks, this can go back to expected 0 diagnostics.
|
|
|
|
// assertNoDiagnostics(t, diags)
|
|
|
|
assertDiagnosticCount(t, diags, 1)
|
|
|
|
assertDiagnosticSummary(t, diags, "Version constraints inside provider configuration blocks are deprecated")
|
|
|
|
|
|
|
|
tlsProvider := addrs.NewProvider(
|
2021-05-27 13:09:28 -05:00
|
|
|
addrs.DefaultProviderRegistryHost,
|
2023-12-11 14:10:03 -06:00
|
|
|
"hashicorp", "tls",
|
2021-02-05 13:01:58 -06:00
|
|
|
)
|
|
|
|
nullProvider := addrs.NewDefaultProvider("null")
|
|
|
|
randomProvider := addrs.NewDefaultProvider("random")
|
|
|
|
impliedProvider := addrs.NewDefaultProvider("implied")
|
|
|
|
terraformProvider := addrs.NewBuiltInProvider("terraform")
|
|
|
|
configuredProvider := addrs.NewDefaultProvider("configured")
|
|
|
|
|
|
|
|
got, diags := cfg.ProviderRequirementsShallow()
|
|
|
|
assertNoDiagnostics(t, diags)
|
|
|
|
want := getproviders.Requirements{
|
|
|
|
// the nullProvider constraint is only from the root module
|
|
|
|
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,
|
|
|
|
}
|
|
|
|
|
|
|
|
if diff := cmp.Diff(want, got); diff != "" {
|
|
|
|
t.Errorf("wrong result\n%s", diff)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-10 08:33:15 -05:00
|
|
|
func TestConfigProviderRequirementsShallowInclTests(t *testing.T) {
|
|
|
|
cfg, diags := testNestedModuleConfigFromDirWithTests(t, "testdata/provider-reqs-with-tests")
|
|
|
|
// TODO: Version Constraint Deprecation.
|
|
|
|
// Once we've removed the version argument from provider configuration
|
|
|
|
// blocks, this can go back to expected 0 diagnostics.
|
|
|
|
// assertNoDiagnostics(t, diags)
|
|
|
|
assertDiagnosticCount(t, diags, 1)
|
|
|
|
assertDiagnosticSummary(t, diags, "Version constraints inside provider configuration blocks are deprecated")
|
|
|
|
|
|
|
|
tlsProvider := addrs.NewProvider(
|
|
|
|
addrs.DefaultProviderRegistryHost,
|
2023-12-11 14:10:03 -06:00
|
|
|
"hashicorp", "tls",
|
2023-07-10 08:33:15 -05:00
|
|
|
)
|
|
|
|
impliedProvider := addrs.NewDefaultProvider("implied")
|
|
|
|
terraformProvider := addrs.NewBuiltInProvider("terraform")
|
|
|
|
configuredProvider := addrs.NewDefaultProvider("configured")
|
|
|
|
|
|
|
|
got, diags := cfg.ProviderRequirementsShallow()
|
|
|
|
assertNoDiagnostics(t, diags)
|
|
|
|
want := getproviders.Requirements{
|
|
|
|
tlsProvider: getproviders.MustParseVersionConstraints("~> 3.0"),
|
|
|
|
configuredProvider: getproviders.MustParseVersionConstraints("~> 1.4"),
|
|
|
|
impliedProvider: nil,
|
|
|
|
terraformProvider: nil,
|
|
|
|
}
|
|
|
|
|
|
|
|
if diff := cmp.Diff(want, got); diff != "" {
|
|
|
|
t.Errorf("wrong result\n%s", diff)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-09 12:32:56 -05:00
|
|
|
func TestConfigProviderRequirementsByModule(t *testing.T) {
|
|
|
|
cfg, diags := testNestedModuleConfigFromDir(t, "testdata/provider-reqs")
|
2020-09-08 07:19:00 -05:00
|
|
|
// TODO: Version Constraint Deprecation.
|
|
|
|
// Once we've removed the version argument from provider configuration
|
|
|
|
// blocks, this can go back to expected 0 diagnostics.
|
|
|
|
// assertNoDiagnostics(t, diags)
|
|
|
|
assertDiagnosticCount(t, diags, 1)
|
|
|
|
assertDiagnosticSummary(t, diags, "Version constraints inside provider configuration blocks are deprecated")
|
2020-06-09 12:32:56 -05:00
|
|
|
|
|
|
|
tlsProvider := addrs.NewProvider(
|
2021-05-27 13:09:28 -05:00
|
|
|
addrs.DefaultProviderRegistryHost,
|
2023-12-11 14:10:03 -06:00
|
|
|
"hashicorp", "tls",
|
2020-06-09 12:32:56 -05:00
|
|
|
)
|
|
|
|
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")
|
2020-06-22 11:13:35 -05:00
|
|
|
grandchildProvider := addrs.NewDefaultProvider("grandchild")
|
2020-06-09 12:32:56 -05:00
|
|
|
|
|
|
|
got, diags := cfg.ProviderRequirementsByModule()
|
|
|
|
assertNoDiagnostics(t, diags)
|
|
|
|
want := &ModuleRequirements{
|
2020-06-09 12:33:07 -05:00
|
|
|
Name: "",
|
Refactoring of module source addresses and module installation
It's been a long while since we gave close attention to the codepaths for
module source address parsing and external module package installation.
Due to their age, these codepaths often diverged from our modern practices
such as representing address types in the addrs package, and encapsulating
package installation details only in a particular location.
In particular, this refactor makes source address parsing a separate step
from module installation, which therefore makes the result of that parsing
available to other Terraform subsystems which work with the configuration
representation objects.
This also presented the opportunity to better encapsulate our use of
go-getter into a new package "getmodules" (echoing "getproviders"), which
is intended to be the only part of Terraform that directly interacts with
go-getter.
This is largely just a refactor of the existing functionality into a new
code organization, but there is one notable change in behavior here: the
source address parsing now happens during configuration loading rather
than module installation, which may cause errors about invalid addresses
to be returned in different situations than before. That counts as
backward compatible because we only promise to remain compatible with
configurations that are _valid_, which means that they can be initialized,
planned, and applied without any errors. This doesn't introduce any new
error cases, and instead just makes a pre-existing error case be detected
earlier.
Our module registry client is still using its own special module address
type from registry/regsrc for now, with a small shim from the new
addrs.ModuleSourceRegistry type. Hopefully in a later commit we'll also
rework the registry client to work with the new address type, but this
commit is already big enough as it is.
2021-05-27 21:24:59 -05:00
|
|
|
SourceAddr: nil,
|
2020-06-09 12:33:07 -05:00
|
|
|
SourceDir: "testdata/provider-reqs",
|
2020-06-09 12:32:56 -05:00
|
|
|
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": {
|
2020-06-09 12:33:07 -05:00
|
|
|
Name: "kinder",
|
Refactoring of module source addresses and module installation
It's been a long while since we gave close attention to the codepaths for
module source address parsing and external module package installation.
Due to their age, these codepaths often diverged from our modern practices
such as representing address types in the addrs package, and encapsulating
package installation details only in a particular location.
In particular, this refactor makes source address parsing a separate step
from module installation, which therefore makes the result of that parsing
available to other Terraform subsystems which work with the configuration
representation objects.
This also presented the opportunity to better encapsulate our use of
go-getter into a new package "getmodules" (echoing "getproviders"), which
is intended to be the only part of Terraform that directly interacts with
go-getter.
This is largely just a refactor of the existing functionality into a new
code organization, but there is one notable change in behavior here: the
source address parsing now happens during configuration loading rather
than module installation, which may cause errors about invalid addresses
to be returned in different situations than before. That counts as
backward compatible because we only promise to remain compatible with
configurations that are _valid_, which means that they can be initialized,
planned, and applied without any errors. This doesn't introduce any new
error cases, and instead just makes a pre-existing error case be detected
earlier.
Our module registry client is still using its own special module address
type from registry/regsrc for now, with a small shim from the new
addrs.ModuleSourceRegistry type. Hopefully in a later commit we'll also
rework the registry client to work with the new address type, but this
commit is already big enough as it is.
2021-05-27 21:24:59 -05:00
|
|
|
SourceAddr: addrs.ModuleSourceLocal("./child"),
|
2024-02-21 13:39:59 -06:00
|
|
|
SourceDir: filepath.FromSlash("testdata/provider-reqs/child"),
|
2020-06-09 12:32:56 -05:00
|
|
|
Requirements: getproviders.Requirements{
|
|
|
|
nullProvider: getproviders.MustParseVersionConstraints("= 2.0.1"),
|
|
|
|
happycloudProvider: nil,
|
|
|
|
},
|
2020-06-22 11:13:35 -05:00
|
|
|
Children: map[string]*ModuleRequirements{
|
|
|
|
"nested": {
|
|
|
|
Name: "nested",
|
Refactoring of module source addresses and module installation
It's been a long while since we gave close attention to the codepaths for
module source address parsing and external module package installation.
Due to their age, these codepaths often diverged from our modern practices
such as representing address types in the addrs package, and encapsulating
package installation details only in a particular location.
In particular, this refactor makes source address parsing a separate step
from module installation, which therefore makes the result of that parsing
available to other Terraform subsystems which work with the configuration
representation objects.
This also presented the opportunity to better encapsulate our use of
go-getter into a new package "getmodules" (echoing "getproviders"), which
is intended to be the only part of Terraform that directly interacts with
go-getter.
This is largely just a refactor of the existing functionality into a new
code organization, but there is one notable change in behavior here: the
source address parsing now happens during configuration loading rather
than module installation, which may cause errors about invalid addresses
to be returned in different situations than before. That counts as
backward compatible because we only promise to remain compatible with
configurations that are _valid_, which means that they can be initialized,
planned, and applied without any errors. This doesn't introduce any new
error cases, and instead just makes a pre-existing error case be detected
earlier.
Our module registry client is still using its own special module address
type from registry/regsrc for now, with a small shim from the new
addrs.ModuleSourceRegistry type. Hopefully in a later commit we'll also
rework the registry client to work with the new address type, but this
commit is already big enough as it is.
2021-05-27 21:24:59 -05:00
|
|
|
SourceAddr: addrs.ModuleSourceLocal("./grandchild"),
|
2024-02-21 13:39:59 -06:00
|
|
|
SourceDir: filepath.FromSlash("testdata/provider-reqs/child/grandchild"),
|
2020-06-22 11:13:35 -05:00
|
|
|
Requirements: getproviders.Requirements{
|
|
|
|
grandchildProvider: nil,
|
|
|
|
},
|
|
|
|
Children: map[string]*ModuleRequirements{},
|
2023-07-10 08:33:15 -05:00
|
|
|
Tests: make(map[string]*TestFileModuleRequirements),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Tests: make(map[string]*TestFileModuleRequirements),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Tests: make(map[string]*TestFileModuleRequirements),
|
|
|
|
}
|
|
|
|
|
|
|
|
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 TestConfigProviderRequirementsByModuleInclTests(t *testing.T) {
|
|
|
|
cfg, diags := testNestedModuleConfigFromDirWithTests(t, "testdata/provider-reqs-with-tests")
|
|
|
|
// TODO: Version Constraint Deprecation.
|
|
|
|
// Once we've removed the version argument from provider configuration
|
|
|
|
// blocks, this can go back to expected 0 diagnostics.
|
|
|
|
// assertNoDiagnostics(t, diags)
|
|
|
|
assertDiagnosticCount(t, diags, 1)
|
|
|
|
assertDiagnosticSummary(t, diags, "Version constraints inside provider configuration blocks are deprecated")
|
|
|
|
|
|
|
|
tlsProvider := addrs.NewProvider(
|
|
|
|
addrs.DefaultProviderRegistryHost,
|
2023-12-11 14:10:03 -06:00
|
|
|
"hashicorp", "tls",
|
2023-07-10 08:33:15 -05:00
|
|
|
)
|
|
|
|
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: nil,
|
|
|
|
SourceDir: "testdata/provider-reqs-with-tests",
|
|
|
|
Requirements: getproviders.Requirements{
|
|
|
|
// Only the root module's version is present here
|
|
|
|
tlsProvider: getproviders.MustParseVersionConstraints("~> 3.0"),
|
|
|
|
impliedProvider: nil,
|
|
|
|
terraformProvider: nil,
|
|
|
|
},
|
|
|
|
Children: make(map[string]*ModuleRequirements),
|
|
|
|
Tests: map[string]*TestFileModuleRequirements{
|
2023-07-20 09:57:05 -05:00
|
|
|
"provider-reqs-root.tftest.hcl": {
|
2023-07-10 08:33:15 -05:00
|
|
|
Requirements: getproviders.Requirements{
|
|
|
|
configuredProvider: getproviders.MustParseVersionConstraints("~> 1.4"),
|
|
|
|
},
|
|
|
|
Runs: map[string]*ModuleRequirements{
|
|
|
|
"setup": {
|
|
|
|
Name: "setup",
|
|
|
|
SourceAddr: addrs.ModuleSourceLocal("./setup"),
|
2024-02-21 13:39:59 -06:00
|
|
|
SourceDir: filepath.FromSlash("testdata/provider-reqs-with-tests/setup"),
|
2023-07-10 08:33:15 -05:00
|
|
|
Requirements: getproviders.Requirements{
|
|
|
|
nullProvider: getproviders.MustParseVersionConstraints("~> 2.0.0"),
|
|
|
|
randomProvider: getproviders.MustParseVersionConstraints("~> 1.2.0"),
|
|
|
|
},
|
|
|
|
Children: make(map[string]*ModuleRequirements),
|
|
|
|
Tests: make(map[string]*TestFileModuleRequirements),
|
2020-06-22 11:13:35 -05:00
|
|
|
},
|
|
|
|
},
|
2020-06-09 12:32:56 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
ignore := cmpopts.IgnoreUnexported(version.Constraint{}, cty.Value{}, hclsyntax.Body{})
|
|
|
|
if diff := cmp.Diff(want, got, ignore); diff != "" {
|
|
|
|
t.Errorf("wrong result\n%s", diff)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
backend/local: Check dependency lock consistency before any operations
In historical versions of Terraform the responsibility to check this was
inside the terraform.NewContext function, along with various other
assorted concerns that made that function particularly complicated.
More recently, we reduced the responsibility of the "terraform" package
only to instantiating particular named plugins, assuming that its caller
is responsible for selecting appropriate versions of any providers that
_are_ external. However, until this commit we were just assuming that
"terraform init" had correctly selected appropriate plugins and recorded
them in the lock file, and so nothing was dealing with the problem of
ensuring that there haven't been any changes to the lock file or config
since the most recent "terraform init" which would cause us to need to
re-evaluate those decisions.
Part of the game here is to slightly extend the role of the dependency
locks object to also carry information about a subset of provider
addresses whose lock entries we're intentionally disregarding as part of
the various little edge-case features we have for overridding providers:
dev_overrides, "unmanaged providers", and the testing overrides in our
own unit tests. This is an in-memory-only annotation, never included in
the serialized plan files on disk.
I had originally intended to create a new package to encapsulate all of
this plugin-selection logic, including both the version constraint
checking here and also the handling of the provider factory functions, but
as an interim step I've just made version constraint consistency checks
the responsibility of the backend/local package, which means that we'll
always catch problems as part of preparing for local operations, while
not imposing these additional checks on commands that _don't_ run local
operations, such as "terraform apply" when in remote operations mode.
2021-09-29 19:31:43 -05:00
|
|
|
func TestVerifyDependencySelections(t *testing.T) {
|
|
|
|
cfg, diags := testNestedModuleConfigFromDir(t, "testdata/provider-reqs")
|
|
|
|
// TODO: Version Constraint Deprecation.
|
|
|
|
// Once we've removed the version argument from provider configuration
|
|
|
|
// blocks, this can go back to expected 0 diagnostics.
|
|
|
|
// assertNoDiagnostics(t, diags)
|
|
|
|
assertDiagnosticCount(t, diags, 1)
|
|
|
|
assertDiagnosticSummary(t, diags, "Version constraints inside provider configuration blocks are deprecated")
|
|
|
|
|
|
|
|
tlsProvider := addrs.NewProvider(
|
|
|
|
addrs.DefaultProviderRegistryHost,
|
2023-12-11 14:10:03 -06:00
|
|
|
"hashicorp", "tls",
|
backend/local: Check dependency lock consistency before any operations
In historical versions of Terraform the responsibility to check this was
inside the terraform.NewContext function, along with various other
assorted concerns that made that function particularly complicated.
More recently, we reduced the responsibility of the "terraform" package
only to instantiating particular named plugins, assuming that its caller
is responsible for selecting appropriate versions of any providers that
_are_ external. However, until this commit we were just assuming that
"terraform init" had correctly selected appropriate plugins and recorded
them in the lock file, and so nothing was dealing with the problem of
ensuring that there haven't been any changes to the lock file or config
since the most recent "terraform init" which would cause us to need to
re-evaluate those decisions.
Part of the game here is to slightly extend the role of the dependency
locks object to also carry information about a subset of provider
addresses whose lock entries we're intentionally disregarding as part of
the various little edge-case features we have for overridding providers:
dev_overrides, "unmanaged providers", and the testing overrides in our
own unit tests. This is an in-memory-only annotation, never included in
the serialized plan files on disk.
I had originally intended to create a new package to encapsulate all of
this plugin-selection logic, including both the version constraint
checking here and also the handling of the provider factory functions, but
as an interim step I've just made version constraint consistency checks
the responsibility of the backend/local package, which means that we'll
always catch problems as part of preparing for local operations, while
not imposing these additional checks on commands that _don't_ run local
operations, such as "terraform apply" when in remote operations mode.
2021-09-29 19:31:43 -05:00
|
|
|
)
|
|
|
|
happycloudProvider := addrs.NewProvider(
|
|
|
|
svchost.Hostname("tf.example.com"),
|
|
|
|
"awesomecorp", "happycloud",
|
|
|
|
)
|
|
|
|
nullProvider := addrs.NewDefaultProvider("null")
|
|
|
|
randomProvider := addrs.NewDefaultProvider("random")
|
|
|
|
impliedProvider := addrs.NewDefaultProvider("implied")
|
|
|
|
configuredProvider := addrs.NewDefaultProvider("configured")
|
|
|
|
grandchildProvider := addrs.NewDefaultProvider("grandchild")
|
|
|
|
|
|
|
|
tests := map[string]struct {
|
|
|
|
PrepareLocks func(*depsfile.Locks)
|
|
|
|
WantErrs []string
|
|
|
|
}{
|
|
|
|
"empty locks": {
|
|
|
|
func(*depsfile.Locks) {
|
|
|
|
// Intentionally blank
|
|
|
|
},
|
|
|
|
[]string{
|
2023-12-11 14:10:03 -06:00
|
|
|
`provider registry.opentofu.org/hashicorp/configured: required by this configuration but no version is selected`,
|
|
|
|
`provider registry.opentofu.org/hashicorp/grandchild: required by this configuration but no version is selected`,
|
|
|
|
`provider registry.opentofu.org/hashicorp/implied: required by this configuration but no version is selected`,
|
|
|
|
`provider registry.opentofu.org/hashicorp/null: required by this configuration but no version is selected`,
|
|
|
|
`provider registry.opentofu.org/hashicorp/random: required by this configuration but no version is selected`,
|
|
|
|
`provider registry.opentofu.org/hashicorp/tls: required by this configuration but no version is selected`,
|
backend/local: Check dependency lock consistency before any operations
In historical versions of Terraform the responsibility to check this was
inside the terraform.NewContext function, along with various other
assorted concerns that made that function particularly complicated.
More recently, we reduced the responsibility of the "terraform" package
only to instantiating particular named plugins, assuming that its caller
is responsible for selecting appropriate versions of any providers that
_are_ external. However, until this commit we were just assuming that
"terraform init" had correctly selected appropriate plugins and recorded
them in the lock file, and so nothing was dealing with the problem of
ensuring that there haven't been any changes to the lock file or config
since the most recent "terraform init" which would cause us to need to
re-evaluate those decisions.
Part of the game here is to slightly extend the role of the dependency
locks object to also carry information about a subset of provider
addresses whose lock entries we're intentionally disregarding as part of
the various little edge-case features we have for overridding providers:
dev_overrides, "unmanaged providers", and the testing overrides in our
own unit tests. This is an in-memory-only annotation, never included in
the serialized plan files on disk.
I had originally intended to create a new package to encapsulate all of
this plugin-selection logic, including both the version constraint
checking here and also the handling of the provider factory functions, but
as an interim step I've just made version constraint consistency checks
the responsibility of the backend/local package, which means that we'll
always catch problems as part of preparing for local operations, while
not imposing these additional checks on commands that _don't_ run local
operations, such as "terraform apply" when in remote operations mode.
2021-09-29 19:31:43 -05:00
|
|
|
`provider tf.example.com/awesomecorp/happycloud: required by this configuration but no version is selected`,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"suitable locks": {
|
|
|
|
func(locks *depsfile.Locks) {
|
|
|
|
locks.SetProvider(configuredProvider, getproviders.MustParseVersion("1.4.0"), nil, nil)
|
|
|
|
locks.SetProvider(grandchildProvider, getproviders.MustParseVersion("0.1.0"), nil, nil)
|
|
|
|
locks.SetProvider(impliedProvider, getproviders.MustParseVersion("0.2.0"), nil, nil)
|
|
|
|
locks.SetProvider(nullProvider, getproviders.MustParseVersion("2.0.1"), nil, nil)
|
|
|
|
locks.SetProvider(randomProvider, getproviders.MustParseVersion("1.2.2"), nil, nil)
|
|
|
|
locks.SetProvider(tlsProvider, getproviders.MustParseVersion("3.0.1"), nil, nil)
|
|
|
|
locks.SetProvider(happycloudProvider, getproviders.MustParseVersion("0.0.1"), nil, nil)
|
|
|
|
},
|
|
|
|
nil,
|
|
|
|
},
|
|
|
|
"null provider constraints changed": {
|
|
|
|
func(locks *depsfile.Locks) {
|
|
|
|
locks.SetProvider(configuredProvider, getproviders.MustParseVersion("1.4.0"), nil, nil)
|
|
|
|
locks.SetProvider(grandchildProvider, getproviders.MustParseVersion("0.1.0"), nil, nil)
|
|
|
|
locks.SetProvider(impliedProvider, getproviders.MustParseVersion("0.2.0"), nil, nil)
|
|
|
|
locks.SetProvider(nullProvider, getproviders.MustParseVersion("3.0.0"), nil, nil)
|
|
|
|
locks.SetProvider(randomProvider, getproviders.MustParseVersion("1.2.2"), nil, nil)
|
|
|
|
locks.SetProvider(tlsProvider, getproviders.MustParseVersion("3.0.1"), nil, nil)
|
|
|
|
locks.SetProvider(happycloudProvider, getproviders.MustParseVersion("0.0.1"), nil, nil)
|
|
|
|
},
|
|
|
|
[]string{
|
2023-12-11 14:10:03 -06:00
|
|
|
`provider registry.opentofu.org/hashicorp/null: locked version selection 3.0.0 doesn't match the updated version constraints "~> 2.0.0, 2.0.1"`,
|
backend/local: Check dependency lock consistency before any operations
In historical versions of Terraform the responsibility to check this was
inside the terraform.NewContext function, along with various other
assorted concerns that made that function particularly complicated.
More recently, we reduced the responsibility of the "terraform" package
only to instantiating particular named plugins, assuming that its caller
is responsible for selecting appropriate versions of any providers that
_are_ external. However, until this commit we were just assuming that
"terraform init" had correctly selected appropriate plugins and recorded
them in the lock file, and so nothing was dealing with the problem of
ensuring that there haven't been any changes to the lock file or config
since the most recent "terraform init" which would cause us to need to
re-evaluate those decisions.
Part of the game here is to slightly extend the role of the dependency
locks object to also carry information about a subset of provider
addresses whose lock entries we're intentionally disregarding as part of
the various little edge-case features we have for overridding providers:
dev_overrides, "unmanaged providers", and the testing overrides in our
own unit tests. This is an in-memory-only annotation, never included in
the serialized plan files on disk.
I had originally intended to create a new package to encapsulate all of
this plugin-selection logic, including both the version constraint
checking here and also the handling of the provider factory functions, but
as an interim step I've just made version constraint consistency checks
the responsibility of the backend/local package, which means that we'll
always catch problems as part of preparing for local operations, while
not imposing these additional checks on commands that _don't_ run local
operations, such as "terraform apply" when in remote operations mode.
2021-09-29 19:31:43 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
"null provider lock changed": {
|
|
|
|
func(locks *depsfile.Locks) {
|
|
|
|
// In this case, we set the lock file version constraints to
|
|
|
|
// match the configuration, and so our error message changes
|
|
|
|
// to not assume the configuration changed anymore.
|
|
|
|
locks.SetProvider(nullProvider, getproviders.MustParseVersion("3.0.0"), getproviders.MustParseVersionConstraints("~> 2.0.0, 2.0.1"), nil)
|
|
|
|
|
|
|
|
locks.SetProvider(configuredProvider, getproviders.MustParseVersion("1.4.0"), nil, nil)
|
|
|
|
locks.SetProvider(grandchildProvider, getproviders.MustParseVersion("0.1.0"), nil, nil)
|
|
|
|
locks.SetProvider(impliedProvider, getproviders.MustParseVersion("0.2.0"), nil, nil)
|
|
|
|
locks.SetProvider(randomProvider, getproviders.MustParseVersion("1.2.2"), nil, nil)
|
|
|
|
locks.SetProvider(tlsProvider, getproviders.MustParseVersion("3.0.1"), nil, nil)
|
|
|
|
locks.SetProvider(happycloudProvider, getproviders.MustParseVersion("0.0.1"), nil, nil)
|
|
|
|
},
|
|
|
|
[]string{
|
2023-12-11 14:10:03 -06:00
|
|
|
`provider registry.opentofu.org/hashicorp/null: version constraints "~> 2.0.0, 2.0.1" don't match the locked version selection 3.0.0`,
|
backend/local: Check dependency lock consistency before any operations
In historical versions of Terraform the responsibility to check this was
inside the terraform.NewContext function, along with various other
assorted concerns that made that function particularly complicated.
More recently, we reduced the responsibility of the "terraform" package
only to instantiating particular named plugins, assuming that its caller
is responsible for selecting appropriate versions of any providers that
_are_ external. However, until this commit we were just assuming that
"terraform init" had correctly selected appropriate plugins and recorded
them in the lock file, and so nothing was dealing with the problem of
ensuring that there haven't been any changes to the lock file or config
since the most recent "terraform init" which would cause us to need to
re-evaluate those decisions.
Part of the game here is to slightly extend the role of the dependency
locks object to also carry information about a subset of provider
addresses whose lock entries we're intentionally disregarding as part of
the various little edge-case features we have for overridding providers:
dev_overrides, "unmanaged providers", and the testing overrides in our
own unit tests. This is an in-memory-only annotation, never included in
the serialized plan files on disk.
I had originally intended to create a new package to encapsulate all of
this plugin-selection logic, including both the version constraint
checking here and also the handling of the provider factory functions, but
as an interim step I've just made version constraint consistency checks
the responsibility of the backend/local package, which means that we'll
always catch problems as part of preparing for local operations, while
not imposing these additional checks on commands that _don't_ run local
operations, such as "terraform apply" when in remote operations mode.
2021-09-29 19:31:43 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
"overridden provider": {
|
|
|
|
func(locks *depsfile.Locks) {
|
|
|
|
locks.SetProviderOverridden(happycloudProvider)
|
|
|
|
},
|
|
|
|
[]string{
|
|
|
|
// We still catch all of the other ones, because only happycloud was overridden
|
2023-12-11 14:10:03 -06:00
|
|
|
`provider registry.opentofu.org/hashicorp/configured: required by this configuration but no version is selected`,
|
|
|
|
`provider registry.opentofu.org/hashicorp/grandchild: required by this configuration but no version is selected`,
|
|
|
|
`provider registry.opentofu.org/hashicorp/implied: required by this configuration but no version is selected`,
|
|
|
|
`provider registry.opentofu.org/hashicorp/null: required by this configuration but no version is selected`,
|
|
|
|
`provider registry.opentofu.org/hashicorp/random: required by this configuration but no version is selected`,
|
|
|
|
`provider registry.opentofu.org/hashicorp/tls: required by this configuration but no version is selected`,
|
backend/local: Check dependency lock consistency before any operations
In historical versions of Terraform the responsibility to check this was
inside the terraform.NewContext function, along with various other
assorted concerns that made that function particularly complicated.
More recently, we reduced the responsibility of the "terraform" package
only to instantiating particular named plugins, assuming that its caller
is responsible for selecting appropriate versions of any providers that
_are_ external. However, until this commit we were just assuming that
"terraform init" had correctly selected appropriate plugins and recorded
them in the lock file, and so nothing was dealing with the problem of
ensuring that there haven't been any changes to the lock file or config
since the most recent "terraform init" which would cause us to need to
re-evaluate those decisions.
Part of the game here is to slightly extend the role of the dependency
locks object to also carry information about a subset of provider
addresses whose lock entries we're intentionally disregarding as part of
the various little edge-case features we have for overridding providers:
dev_overrides, "unmanaged providers", and the testing overrides in our
own unit tests. This is an in-memory-only annotation, never included in
the serialized plan files on disk.
I had originally intended to create a new package to encapsulate all of
this plugin-selection logic, including both the version constraint
checking here and also the handling of the provider factory functions, but
as an interim step I've just made version constraint consistency checks
the responsibility of the backend/local package, which means that we'll
always catch problems as part of preparing for local operations, while
not imposing these additional checks on commands that _don't_ run local
operations, such as "terraform apply" when in remote operations mode.
2021-09-29 19:31:43 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for name, test := range tests {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
depLocks := depsfile.NewLocks()
|
|
|
|
test.PrepareLocks(depLocks)
|
|
|
|
gotErrs := cfg.VerifyDependencySelections(depLocks)
|
|
|
|
|
|
|
|
var gotErrsStr []string
|
|
|
|
if gotErrs != nil {
|
|
|
|
gotErrsStr = make([]string, len(gotErrs))
|
|
|
|
for i, err := range gotErrs {
|
|
|
|
gotErrsStr[i] = err.Error()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if diff := cmp.Diff(test.WantErrs, gotErrsStr); diff != "" {
|
|
|
|
t.Errorf("wrong errors\n%s", diff)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-31 13:03:33 -05:00
|
|
|
func TestConfigProviderForConfigAddr(t *testing.T) {
|
2020-03-12 11:00:00 -05:00
|
|
|
cfg, diags := testModuleConfigFromDir("testdata/valid-modules/providers-fqns")
|
|
|
|
assertNoDiagnostics(t, diags)
|
|
|
|
|
|
|
|
got := cfg.ProviderForConfigAddr(addrs.NewDefaultLocalProviderConfig("foo-test"))
|
2021-05-27 13:09:28 -05:00
|
|
|
want := addrs.NewProvider(addrs.DefaultProviderRegistryHost, "foo", "test")
|
2020-03-12 11:00:00 -05:00
|
|
|
if !got.Equals(want) {
|
|
|
|
t.Errorf("wrong result\ngot: %s\nwant: %s", got, want)
|
|
|
|
}
|
|
|
|
|
2020-03-31 13:03:33 -05:00
|
|
|
// now check a provider that isn't in the configuration. It should return a DefaultProvider.
|
2020-03-12 11:00:00 -05:00
|
|
|
got = cfg.ProviderForConfigAddr(addrs.NewDefaultLocalProviderConfig("bar-test"))
|
2020-03-31 13:03:33 -05:00
|
|
|
want = addrs.NewDefaultProvider("bar-test")
|
2020-03-12 11:00:00 -05:00
|
|
|
if !got.Equals(want) {
|
|
|
|
t.Errorf("wrong result\ngot: %s\nwant: %s", got, want)
|
|
|
|
}
|
|
|
|
}
|
2020-06-02 08:29:59 -05:00
|
|
|
|
|
|
|
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,
|
|
|
|
}
|
2023-07-10 08:33:15 -05:00
|
|
|
diags = cfg.addProviderRequirements(reqs, true, false)
|
2020-06-02 08:29:59 -05:00
|
|
|
assertNoDiagnostics(t, diags)
|
|
|
|
}
|
2023-05-11 02:04:39 -05:00
|
|
|
|
|
|
|
func TestConfigImportProviderClashesWithModules(t *testing.T) {
|
|
|
|
src, err := os.ReadFile("testdata/invalid-import-files/import-and-module-clash.tf")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
parser := testParser(map[string]string{
|
|
|
|
"main.tf": string(src),
|
|
|
|
})
|
|
|
|
|
|
|
|
_, diags := parser.LoadConfigFile("main.tf")
|
|
|
|
assertExactDiagnostics(t, diags, []string{
|
|
|
|
`main.tf:9,3-19: Invalid import provider argument; The provider argument can only be specified in import blocks that will generate configuration.
|
|
|
|
|
|
|
|
Use the providers argument within the module block to configure providers for all resources within a module, including imported resources.`,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfigImportProviderClashesWithResources(t *testing.T) {
|
|
|
|
cfg, diags := testModuleConfigFromFile("testdata/invalid-import-files/import-and-resource-clash.tf")
|
|
|
|
assertNoDiagnostics(t, diags)
|
|
|
|
|
2023-07-10 08:33:15 -05:00
|
|
|
diags = cfg.addProviderRequirements(getproviders.Requirements{}, true, false)
|
2023-05-11 02:04:39 -05:00
|
|
|
assertExactDiagnostics(t, diags, []string{
|
|
|
|
`testdata/invalid-import-files/import-and-resource-clash.tf:9,3-19: Invalid import provider argument; The provider argument can only be specified in import blocks that will generate configuration.
|
|
|
|
|
|
|
|
Use the provider argument in the target resource block to configure the provider for a resource with explicit provider configuration.`,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConfigImportProviderWithNoResourceProvider(t *testing.T) {
|
|
|
|
cfg, diags := testModuleConfigFromFile("testdata/invalid-import-files/import-and-no-resource.tf")
|
|
|
|
assertNoDiagnostics(t, diags)
|
|
|
|
|
2023-07-10 08:33:15 -05:00
|
|
|
diags = cfg.addProviderRequirements(getproviders.Requirements{}, true, false)
|
2023-05-11 02:04:39 -05:00
|
|
|
assertExactDiagnostics(t, diags, []string{
|
|
|
|
`testdata/invalid-import-files/import-and-no-resource.tf:5,3-19: Invalid import provider argument; The provider argument can only be specified in import blocks that will generate configuration.
|
|
|
|
|
|
|
|
Use the provider argument in the target resource block to configure the provider for a resource with explicit provider configuration.`,
|
|
|
|
})
|
|
|
|
}
|
2023-07-10 08:33:15 -05:00
|
|
|
|
|
|
|
func TestTransformForTest(t *testing.T) {
|
|
|
|
|
|
|
|
str := func(providers map[string]string) string {
|
|
|
|
var buffer bytes.Buffer
|
|
|
|
for key, config := range providers {
|
|
|
|
buffer.WriteString(fmt.Sprintf("%s: %s\n", key, config))
|
|
|
|
}
|
|
|
|
return buffer.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
convertToProviders := func(t *testing.T, contents map[string]string) map[string]*Provider {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
providers := make(map[string]*Provider)
|
|
|
|
for key, content := range contents {
|
|
|
|
parser := hclparse.NewParser()
|
|
|
|
file, diags := parser.ParseHCL([]byte(content), fmt.Sprintf("%s.hcl", key))
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatal(diags.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
provider := &Provider{
|
|
|
|
Config: file.Body,
|
|
|
|
}
|
|
|
|
|
|
|
|
parts := strings.Split(key, ".")
|
|
|
|
provider.Name = parts[0]
|
|
|
|
if len(parts) > 1 {
|
|
|
|
provider.Alias = parts[1]
|
|
|
|
}
|
|
|
|
|
|
|
|
providers[key] = provider
|
|
|
|
}
|
|
|
|
return providers
|
|
|
|
}
|
|
|
|
|
|
|
|
validate := func(t *testing.T, msg string, expected map[string]string, actual map[string]*Provider) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
converted := make(map[string]string)
|
|
|
|
for key, provider := range actual {
|
|
|
|
content, err := provider.Config.Content(&hcl.BodySchema{
|
|
|
|
Attributes: []hcl.AttributeSchema{
|
|
|
|
{Name: "source", Required: true},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
source, diags := content.Attributes["source"].Expr.Value(nil)
|
|
|
|
if diags.HasErrors() {
|
|
|
|
t.Fatal(diags.Error())
|
|
|
|
}
|
|
|
|
converted[key] = fmt.Sprintf("source = %q", source.AsString())
|
|
|
|
}
|
|
|
|
|
|
|
|
if diff := cmp.Diff(expected, converted); len(diff) > 0 {
|
|
|
|
t.Errorf("%s\nexpected:\n%s\nactual:\n%s\ndiff:\n%s", msg, str(expected), str(converted), diff)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tcs := map[string]struct {
|
|
|
|
configProviders map[string]string
|
|
|
|
fileProviders map[string]string
|
|
|
|
runProviders []PassedProviderConfig
|
|
|
|
expectedProviders map[string]string
|
|
|
|
expectedErrors []string
|
|
|
|
}{
|
|
|
|
"empty": {
|
|
|
|
configProviders: make(map[string]string),
|
|
|
|
expectedProviders: make(map[string]string),
|
|
|
|
},
|
|
|
|
"only providers in config": {
|
|
|
|
configProviders: map[string]string{
|
|
|
|
"foo": "source = \"config\"",
|
|
|
|
"bar": "source = \"config\"",
|
|
|
|
},
|
|
|
|
expectedProviders: map[string]string{
|
|
|
|
"foo": "source = \"config\"",
|
|
|
|
"bar": "source = \"config\"",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"only providers in test file": {
|
|
|
|
configProviders: make(map[string]string),
|
|
|
|
fileProviders: map[string]string{
|
|
|
|
"foo": "source = \"testfile\"",
|
|
|
|
"bar": "source = \"testfile\"",
|
|
|
|
},
|
|
|
|
expectedProviders: map[string]string{
|
|
|
|
"foo": "source = \"testfile\"",
|
|
|
|
"bar": "source = \"testfile\"",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"only providers in run block": {
|
|
|
|
configProviders: make(map[string]string),
|
|
|
|
runProviders: []PassedProviderConfig{
|
|
|
|
{
|
|
|
|
InChild: &ProviderConfigRef{
|
|
|
|
Name: "foo",
|
|
|
|
},
|
|
|
|
InParent: &ProviderConfigRef{
|
|
|
|
Name: "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedProviders: make(map[string]string),
|
|
|
|
expectedErrors: []string{
|
|
|
|
":0,0-0: Missing provider definition for bar; This provider block references a provider definition that does not exist.",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"subset of providers in test file": {
|
|
|
|
configProviders: make(map[string]string),
|
|
|
|
fileProviders: map[string]string{
|
|
|
|
"bar": "source = \"testfile\"",
|
|
|
|
},
|
|
|
|
runProviders: []PassedProviderConfig{
|
|
|
|
{
|
|
|
|
InChild: &ProviderConfigRef{
|
|
|
|
Name: "foo",
|
|
|
|
},
|
|
|
|
InParent: &ProviderConfigRef{
|
|
|
|
Name: "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedProviders: map[string]string{
|
|
|
|
"foo": "source = \"testfile\"",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"overrides providers in config": {
|
|
|
|
configProviders: map[string]string{
|
|
|
|
"foo": "source = \"config\"",
|
|
|
|
"bar": "source = \"config\"",
|
|
|
|
},
|
|
|
|
fileProviders: map[string]string{
|
|
|
|
"bar": "source = \"testfile\"",
|
|
|
|
},
|
|
|
|
expectedProviders: map[string]string{
|
|
|
|
"foo": "source = \"config\"",
|
|
|
|
"bar": "source = \"testfile\"",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"overrides subset of providers in config": {
|
|
|
|
configProviders: map[string]string{
|
|
|
|
"foo": "source = \"config\"",
|
|
|
|
"bar": "source = \"config\"",
|
|
|
|
},
|
|
|
|
fileProviders: map[string]string{
|
|
|
|
"foo": "source = \"testfile\"",
|
|
|
|
"bar": "source = \"testfile\"",
|
|
|
|
},
|
|
|
|
runProviders: []PassedProviderConfig{
|
|
|
|
{
|
|
|
|
InChild: &ProviderConfigRef{
|
|
|
|
Name: "bar",
|
|
|
|
},
|
|
|
|
InParent: &ProviderConfigRef{
|
|
|
|
Name: "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedProviders: map[string]string{
|
|
|
|
"foo": "source = \"config\"",
|
|
|
|
"bar": "source = \"testfile\"",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"handles aliases": {
|
|
|
|
configProviders: map[string]string{
|
|
|
|
"foo.primary": "source = \"config\"",
|
|
|
|
"foo.secondary": "source = \"config\"",
|
|
|
|
},
|
|
|
|
fileProviders: map[string]string{
|
|
|
|
"foo": "source = \"testfile\"",
|
|
|
|
},
|
|
|
|
runProviders: []PassedProviderConfig{
|
|
|
|
{
|
|
|
|
InChild: &ProviderConfigRef{
|
|
|
|
Name: "foo.secondary",
|
|
|
|
},
|
|
|
|
InParent: &ProviderConfigRef{
|
|
|
|
Name: "foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
expectedProviders: map[string]string{
|
|
|
|
"foo.primary": "source = \"config\"",
|
|
|
|
"foo.secondary": "source = \"testfile\"",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, tc := range tcs {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
config := &Config{
|
|
|
|
Module: &Module{
|
|
|
|
ProviderConfigs: convertToProviders(t, tc.configProviders),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
file := &TestFile{
|
|
|
|
Providers: convertToProviders(t, tc.fileProviders),
|
|
|
|
}
|
|
|
|
|
|
|
|
run := &TestRun{
|
|
|
|
Providers: tc.runProviders,
|
|
|
|
}
|
|
|
|
|
|
|
|
reset, diags := config.TransformForTest(run, file)
|
|
|
|
|
|
|
|
var actualErrs []string
|
|
|
|
for _, err := range diags.Errs() {
|
|
|
|
actualErrs = append(actualErrs, err.Error())
|
|
|
|
}
|
|
|
|
if diff := cmp.Diff(actualErrs, tc.expectedErrors, cmpopts.IgnoreUnexported()); len(diff) > 0 {
|
|
|
|
t.Errorf("unmatched errors\nexpected:\n%s\nactual:\n%s\ndiff:\n%s", strings.Join(tc.expectedErrors, "\n"), strings.Join(actualErrs, "\n"), diff)
|
|
|
|
}
|
|
|
|
|
|
|
|
validate(t, "after transform mismatch", tc.expectedProviders, config.Module.ProviderConfigs)
|
|
|
|
reset()
|
|
|
|
validate(t, "after reset mismatch", tc.configProviders, config.Module.ProviderConfigs)
|
|
|
|
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|