addrs: "built-in" provider namespace

The introduction of a heirarchical addressing scheme for providers gives
us an opportunity to make more explicit the special case of "built-in"
providers.

Thus far we've just had a special case in the "command" package that the
provider named "terraform" is handled differently than all others, though
there's nothing especially obvious about that in the UI.

Moving forward we'll put such "built-in" providers under the special
namespace terraform.io/builtin/terraform, which will be visible in the UI
as being different than the other providers and we can use the namespace
itself (rather than a particular name) as the trigger for our special-case
behaviors around built-in plugins.

We have no plans to introduce any built-in providers other than
"terraform" in the foreseeable future, so any others will produce an
error.

This commit just establishes the addressing convention, without making use
of it anywhere yet. Subsequent commits will make the provider installer
and resolver codepaths aware of it, replacing existing checks for the
provider just being called "terraform".
This commit is contained in:
Martin Atkins 2020-03-30 12:02:33 -07:00
parent ae080481c0
commit 5aa2e5ec8c
2 changed files with 106 additions and 0 deletions

View File

@ -23,6 +23,20 @@ type Provider struct {
// not have an explicit hostname.
const DefaultRegistryHost = svchost.Hostname("registry.terraform.io")
// BuiltInProviderHost is the pseudo-hostname used for the "built-in" provider
// namespace. Built-in provider addresses must also have their namespace set
// to BuiltInProviderNamespace in order to be considered as built-in.
const BuiltInProviderHost = svchost.Hostname("terraform.io")
// BuiltInProviderNamespace is the provider namespace used for "built-in"
// providers. Built-in provider addresses must also have their hostname
// set to BuiltInProviderHost in order to be considered as built-in.
//
// The this namespace is literally named "builtin", in the hope that users
// who see FQNs containing this will be able to infer the way in which they are
// special, even if they haven't encountered the concept formally yet.
const BuiltInProviderNamespace = "builtin"
// LegacyProviderNamespace is the special string used in the Namespace field
// of type Provider to mark a legacy provider address. This special namespace
// value would normally be invalid, and can be used only when the hostname is
@ -74,6 +88,16 @@ func NewDefaultProvider(name string) Provider {
}
}
// NewBuiltInProvider returns the address of a "built-in" provider. See
// the docs for Provider.IsBuiltIn for more information.
func NewBuiltInProvider(name string) Provider {
return Provider{
Type: MustParseProviderPart(name),
Namespace: BuiltInProviderNamespace,
Hostname: BuiltInProviderHost,
}
}
// NewLegacyProvider returns a mock address for a provider.
// This will be removed when ProviderType is fully integrated.
func NewLegacyProvider(name string) Provider {
@ -109,6 +133,17 @@ func (pt Provider) IsZero() bool {
return pt == Provider{}
}
// IsBuiltIn returns true if the receiver is the address of a "built-in"
// provider. That is, a provider under terraform.io/builtin/ which is
// included as part of the Terraform binary itself rather than one to be
// installed from elsewhere.
//
// These are ignored by the provider installer because they are assumed to
// already be available without any further installation.
func (pt Provider) IsBuiltIn() bool {
return pt.Hostname == BuiltInProviderHost && pt.Namespace == BuiltInProviderNamespace
}
// LessThan returns true if the receiver should sort before the other given
// address in an ordered list of provider addresses.
//

View File

@ -46,6 +46,77 @@ func TestProviderIsDefault(t *testing.T) {
}
}
func TestProviderIsBuiltIn(t *testing.T) {
tests := []struct {
Input Provider
Want bool
}{
{
Provider{
Type: "test",
Hostname: BuiltInProviderHost,
Namespace: BuiltInProviderNamespace,
},
true,
},
{
Provider{
Type: "terraform",
Hostname: BuiltInProviderHost,
Namespace: BuiltInProviderNamespace,
},
true,
},
{
Provider{
Type: "test",
Hostname: BuiltInProviderHost,
Namespace: "boop",
},
false,
},
{
Provider{
Type: "test",
Hostname: DefaultRegistryHost,
Namespace: BuiltInProviderNamespace,
},
false,
},
{
Provider{
Type: "test",
Hostname: DefaultRegistryHost,
Namespace: "hashicorp",
},
false,
},
{
Provider{
Type: "test",
Hostname: "registry.terraform.com",
Namespace: "hashicorp",
},
false,
},
{
Provider{
Type: "test",
Hostname: DefaultRegistryHost,
Namespace: "othercorp",
},
false,
},
}
for _, test := range tests {
got := test.Input.IsBuiltIn()
if got != test.Want {
t.Errorf("wrong result for %s\ngot: %#v\nwant: %#v", test.Input.String(), got, test.Want)
}
}
}
func TestProviderIsLegacy(t *testing.T) {
tests := []struct {
Input Provider