addrs: Simplify presentation of provider FQNs
The provider fully-qualified name string used in configuration is very long, and since most providers are hosted in the public registry, most of that length is redundant. This commit adds and uses a `ForDisplay` method, which simplifies the presentation of provider FQNs. If the hostname is the default hostname, we now display only the namespace and type. This is only used in UI, but should still be unambiguous, as it matches the FQN string parsing behaviour.
This commit is contained in:
parent
8c928e8358
commit
b233aa39e9
|
@ -44,7 +44,7 @@ const BuiltInProviderNamespace = "builtin"
|
||||||
// FQN.
|
// FQN.
|
||||||
const LegacyProviderNamespace = "-"
|
const LegacyProviderNamespace = "-"
|
||||||
|
|
||||||
// String returns an FQN string, indended for use in output.
|
// String returns an FQN string, indended for use in machine-readable output.
|
||||||
func (pt Provider) String() string {
|
func (pt Provider) String() string {
|
||||||
if pt.IsZero() {
|
if pt.IsZero() {
|
||||||
panic("called String on zero-value addrs.Provider")
|
panic("called String on zero-value addrs.Provider")
|
||||||
|
@ -52,6 +52,19 @@ func (pt Provider) String() string {
|
||||||
return pt.Hostname.ForDisplay() + "/" + pt.Namespace + "/" + pt.Type
|
return pt.Hostname.ForDisplay() + "/" + pt.Namespace + "/" + pt.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ForDisplay returns a user-friendly FQN string, simplified for readability. If
|
||||||
|
// the provider is using the default hostname, the hostname is omitted.
|
||||||
|
func (pt Provider) ForDisplay() string {
|
||||||
|
if pt.IsZero() {
|
||||||
|
panic("called ForDisplay on zero-value addrs.Provider")
|
||||||
|
}
|
||||||
|
|
||||||
|
if pt.Hostname == DefaultRegistryHost {
|
||||||
|
return pt.Namespace + "/" + pt.Type
|
||||||
|
}
|
||||||
|
return pt.Hostname.ForDisplay() + "/" + pt.Namespace + "/" + pt.Type
|
||||||
|
}
|
||||||
|
|
||||||
// NewProvider constructs a provider address from its parts, and normalizes
|
// NewProvider constructs a provider address from its parts, and normalizes
|
||||||
// the namespace and type parts to lowercase using unicode case folding rules
|
// the namespace and type parts to lowercase using unicode case folding rules
|
||||||
// so that resulting addrs.Provider values can be compared using standard
|
// so that resulting addrs.Provider values can be compared using standard
|
||||||
|
|
|
@ -7,6 +7,84 @@ import (
|
||||||
svchost "github.com/hashicorp/terraform-svchost"
|
svchost "github.com/hashicorp/terraform-svchost"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestProviderString(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
Input Provider
|
||||||
|
Want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Provider{
|
||||||
|
Type: "test",
|
||||||
|
Hostname: DefaultRegistryHost,
|
||||||
|
Namespace: "hashicorp",
|
||||||
|
},
|
||||||
|
DefaultRegistryHost.ForDisplay() + "/hashicorp/test",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Provider{
|
||||||
|
Type: "test",
|
||||||
|
Hostname: "registry.terraform.com",
|
||||||
|
Namespace: "hashicorp",
|
||||||
|
},
|
||||||
|
"registry.terraform.com/hashicorp/test",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Provider{
|
||||||
|
Type: "test",
|
||||||
|
Hostname: DefaultRegistryHost,
|
||||||
|
Namespace: "othercorp",
|
||||||
|
},
|
||||||
|
DefaultRegistryHost.ForDisplay() + "/othercorp/test",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
got := test.Input.String()
|
||||||
|
if got != test.Want {
|
||||||
|
t.Errorf("wrong result for %s\n", test.Input.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProviderDisplay(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
Input Provider
|
||||||
|
Want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Provider{
|
||||||
|
Type: "test",
|
||||||
|
Hostname: DefaultRegistryHost,
|
||||||
|
Namespace: "hashicorp",
|
||||||
|
},
|
||||||
|
"hashicorp/test",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Provider{
|
||||||
|
Type: "test",
|
||||||
|
Hostname: "registry.terraform.com",
|
||||||
|
Namespace: "hashicorp",
|
||||||
|
},
|
||||||
|
"registry.terraform.com/hashicorp/test",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Provider{
|
||||||
|
Type: "test",
|
||||||
|
Hostname: DefaultRegistryHost,
|
||||||
|
Namespace: "othercorp",
|
||||||
|
},
|
||||||
|
"othercorp/test",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
got := test.Input.ForDisplay()
|
||||||
|
if got != test.Want {
|
||||||
|
t.Errorf("wrong result for %s\n", test.Input.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestProviderIsDefault(t *testing.T) {
|
func TestProviderIsDefault(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
Input Provider
|
Input Provider
|
||||||
|
|
|
@ -461,50 +461,50 @@ func (c *InitCommand) getProviders(earlyConfig *earlyconfig.Config, state *state
|
||||||
))
|
))
|
||||||
},
|
},
|
||||||
ProviderAlreadyInstalled: func(provider addrs.Provider, selectedVersion getproviders.Version) {
|
ProviderAlreadyInstalled: func(provider addrs.Provider, selectedVersion getproviders.Version) {
|
||||||
c.Ui.Info(fmt.Sprintf("- Using previously-installed %s v%s", provider, selectedVersion))
|
c.Ui.Info(fmt.Sprintf("- Using previously-installed %s v%s", provider.ForDisplay(), selectedVersion))
|
||||||
},
|
},
|
||||||
BuiltInProviderAvailable: func(provider addrs.Provider) {
|
BuiltInProviderAvailable: func(provider addrs.Provider) {
|
||||||
c.Ui.Info(fmt.Sprintf("- %s is built in to Terraform", provider))
|
c.Ui.Info(fmt.Sprintf("- %s is built in to Terraform", provider.ForDisplay()))
|
||||||
},
|
},
|
||||||
BuiltInProviderFailure: func(provider addrs.Provider, err error) {
|
BuiltInProviderFailure: func(provider addrs.Provider, err error) {
|
||||||
diags = diags.Append(tfdiags.Sourceless(
|
diags = diags.Append(tfdiags.Sourceless(
|
||||||
tfdiags.Error,
|
tfdiags.Error,
|
||||||
"Invalid dependency on built-in provider",
|
"Invalid dependency on built-in provider",
|
||||||
fmt.Sprintf("Cannot use %s: %s.", provider, err),
|
fmt.Sprintf("Cannot use %s: %s.", provider.ForDisplay(), err),
|
||||||
))
|
))
|
||||||
},
|
},
|
||||||
QueryPackagesBegin: func(provider addrs.Provider, versionConstraints getproviders.VersionConstraints) {
|
QueryPackagesBegin: func(provider addrs.Provider, versionConstraints getproviders.VersionConstraints) {
|
||||||
if len(versionConstraints) > 0 {
|
if len(versionConstraints) > 0 {
|
||||||
c.Ui.Info(fmt.Sprintf("- Finding %s versions matching %q...", provider, getproviders.VersionConstraintsString(versionConstraints)))
|
c.Ui.Info(fmt.Sprintf("- Finding %s versions matching %q...", provider.ForDisplay(), getproviders.VersionConstraintsString(versionConstraints)))
|
||||||
} else {
|
} else {
|
||||||
c.Ui.Info(fmt.Sprintf("- Finding latest version of %s...", provider))
|
c.Ui.Info(fmt.Sprintf("- Finding latest version of %s...", provider.ForDisplay()))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
LinkFromCacheBegin: func(provider addrs.Provider, version getproviders.Version, cacheRoot string) {
|
LinkFromCacheBegin: func(provider addrs.Provider, version getproviders.Version, cacheRoot string) {
|
||||||
c.Ui.Info(fmt.Sprintf("- Using %s v%s from the shared cache directory", provider, version))
|
c.Ui.Info(fmt.Sprintf("- Using %s v%s from the shared cache directory", provider.ForDisplay(), version))
|
||||||
},
|
},
|
||||||
FetchPackageBegin: func(provider addrs.Provider, version getproviders.Version, location getproviders.PackageLocation) {
|
FetchPackageBegin: func(provider addrs.Provider, version getproviders.Version, location getproviders.PackageLocation) {
|
||||||
c.Ui.Info(fmt.Sprintf("- Installing %s v%s...", provider, version))
|
c.Ui.Info(fmt.Sprintf("- Installing %s v%s...", provider.ForDisplay(), version))
|
||||||
},
|
},
|
||||||
QueryPackagesFailure: func(provider addrs.Provider, err error) {
|
QueryPackagesFailure: func(provider addrs.Provider, err error) {
|
||||||
diags = diags.Append(tfdiags.Sourceless(
|
diags = diags.Append(tfdiags.Sourceless(
|
||||||
tfdiags.Error,
|
tfdiags.Error,
|
||||||
"Failed to query available provider packages",
|
"Failed to query available provider packages",
|
||||||
fmt.Sprintf("Could not retrieve the list of available versions for provider %s: %s.", provider, err),
|
fmt.Sprintf("Could not retrieve the list of available versions for provider %s: %s.", provider.ForDisplay(), err),
|
||||||
))
|
))
|
||||||
},
|
},
|
||||||
LinkFromCacheFailure: func(provider addrs.Provider, version getproviders.Version, err error) {
|
LinkFromCacheFailure: func(provider addrs.Provider, version getproviders.Version, err error) {
|
||||||
diags = diags.Append(tfdiags.Sourceless(
|
diags = diags.Append(tfdiags.Sourceless(
|
||||||
tfdiags.Error,
|
tfdiags.Error,
|
||||||
"Failed to install provider from shared cache",
|
"Failed to install provider from shared cache",
|
||||||
fmt.Sprintf("Error while importing %s v%s from the shared cache directory: %s.", provider, version, err),
|
fmt.Sprintf("Error while importing %s v%s from the shared cache directory: %s.", provider.ForDisplay(), version, err),
|
||||||
))
|
))
|
||||||
},
|
},
|
||||||
FetchPackageFailure: func(provider addrs.Provider, version getproviders.Version, err error) {
|
FetchPackageFailure: func(provider addrs.Provider, version getproviders.Version, err error) {
|
||||||
diags = diags.Append(tfdiags.Sourceless(
|
diags = diags.Append(tfdiags.Sourceless(
|
||||||
tfdiags.Error,
|
tfdiags.Error,
|
||||||
"Failed to install provider",
|
"Failed to install provider",
|
||||||
fmt.Sprintf("Error while installing %s v%s: %s.", provider, version, err),
|
fmt.Sprintf("Error while installing %s v%s: %s.", provider.ForDisplay(), version, err),
|
||||||
))
|
))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue