From 8b75d1498f2ccc260d55561d95a921ac11fd885f Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Wed, 22 Apr 2020 15:58:40 -0700 Subject: [PATCH] command/cliconfig: Use existing HTTP mirror source rather than new stub An earlier commit added a redundant stub for a new network mirror source that was already previously stubbed as HTTPMirrorSource. This commit removes the unnecessary extra stub and changes the CLI config handling to use it instead. Along the way this also switches to using a full base URL rather than just a hostname for the mirror, because using the usual "Terraform-native service discovery" protocol here doesn't isn't as useful as in the places we normally use it (the mirror mechanism is already serving as an indirection over the registry protocol) and using a direct base URL will make it easier to deploy an HTTP mirror under a path prefix on an existing static file server. --- command/cliconfig/provider_installation.go | 12 +++--- .../cliconfig/provider_installation_test.go | 4 +- .../cliconfig/testdata/provider-installation | 2 +- internal/getproviders/http_mirror_source.go | 7 ++-- .../getproviders/network_mirror_source.go | 39 ------------------- provider_source.go | 19 ++++++--- 6 files changed, 26 insertions(+), 57 deletions(-) delete mode 100644 internal/getproviders/network_mirror_source.go diff --git a/command/cliconfig/provider_installation.go b/command/cliconfig/provider_installation.go index 10e8f4fc1..d5e57ac05 100644 --- a/command/cliconfig/provider_installation.go +++ b/command/cliconfig/provider_installation.go @@ -138,7 +138,7 @@ func decodeProviderInstallationFromConfig(hclFile *hclast.File) ([]*ProviderInst exclude = bodyContent.Exclude case "network_mirror": type BodyContent struct { - Host string `hcl:"host"` + URL string `hcl:"url"` Include []string `hcl:"include"` Exclude []string `hcl:"exclude"` } @@ -152,15 +152,15 @@ func decodeProviderInstallationFromConfig(hclFile *hclast.File) ([]*ProviderInst )) continue } - if bodyContent.Host == "" { + if bodyContent.URL == "" { diags = diags.Append(tfdiags.Sourceless( tfdiags.Error, "Invalid provider_installation source block", - fmt.Sprintf("Invalid %s block at %s: \"host\" argument is required.", sourceTypeStr, block.Pos()), + fmt.Sprintf("Invalid %s block at %s: \"url\" argument is required.", sourceTypeStr, block.Pos()), )) continue } - location = ProviderInstallationNetworkMirror(bodyContent.Host) + location = ProviderInstallationNetworkMirror(bodyContent.URL) include = bodyContent.Include exclude = bodyContent.Exclude default: @@ -229,8 +229,8 @@ func (i ProviderInstallationFilesystemMirror) providerInstallationLocation() {} // ProviderInstallationNetworkMirror is a ProviderInstallationSourceLocation // representing installation from a particular local network mirror. The -// string value is the hostname exactly as written in the configuration, without -// any normalization. +// string value is the HTTP base URL exactly as written in the configuration, +// without any normalization. type ProviderInstallationNetworkMirror string func (i ProviderInstallationNetworkMirror) providerInstallationLocation() {} diff --git a/command/cliconfig/provider_installation_test.go b/command/cliconfig/provider_installation_test.go index a9cb7e00c..553d0bc75 100644 --- a/command/cliconfig/provider_installation_test.go +++ b/command/cliconfig/provider_installation_test.go @@ -22,7 +22,7 @@ func TestLoadConfig_providerInstallation(t *testing.T) { Include: []string{"example.com/*/*"}, }, { - Location: ProviderInstallationNetworkMirror("tf-Mirror.example.com"), + Location: ProviderInstallationNetworkMirror("https://tf-Mirror.example.com/"), Include: []string{"registry.terraform.io/*/*"}, Exclude: []string{"registry.Terraform.io/foobar/*"}, }, @@ -49,7 +49,7 @@ func TestLoadConfig_providerInstallationErrors(t *testing.T) { - Invalid provider_installation source block: Unknown provider installation source type "not_a_thing" at 2:3. - Invalid provider_installation source block: Invalid filesystem_mirror block at 1:1: "path" argument is required. -- Invalid provider_installation source block: Invalid network_mirror block at 1:1: "host" argument is required. +- Invalid provider_installation source block: Invalid network_mirror block at 1:1: "url" argument is required. - Invalid provider_installation source block: The items inside the provider_installation block at 1:1 must all be blocks. - Invalid provider_installation source block: The blocks inside the provider_installation block at 1:1 may not have any labels. - Invalid provider_installation block: The provider_installation block at 9:1 must not have any labels. diff --git a/command/cliconfig/testdata/provider-installation b/command/cliconfig/testdata/provider-installation index ff2d5fbec..91dc82eab 100644 --- a/command/cliconfig/testdata/provider-installation +++ b/command/cliconfig/testdata/provider-installation @@ -4,7 +4,7 @@ provider_installation { include = ["example.com/*/*"] } network_mirror { - host = "tf-Mirror.example.com" + url = "https://tf-Mirror.example.com/" include = ["registry.terraform.io/*/*"] exclude = ["registry.Terraform.io/foobar/*"] } diff --git a/internal/getproviders/http_mirror_source.go b/internal/getproviders/http_mirror_source.go index 5b5bb80f1..c2dedf9db 100644 --- a/internal/getproviders/http_mirror_source.go +++ b/internal/getproviders/http_mirror_source.go @@ -1,6 +1,7 @@ package getproviders import ( + "fmt" "net/url" "github.com/hashicorp/terraform/addrs" @@ -26,13 +27,11 @@ func NewHTTPMirrorSource(baseURL *url.URL) *HTTPMirrorSource { // AvailableVersions retrieves the available versions for the given provider // from the object's underlying HTTP mirror service. func (s *HTTPMirrorSource) AvailableVersions(provider addrs.Provider) (VersionList, error) { - // TODO: Implement - panic("HTTPMirrorSource.AvailableVersions not yet implemented") + return nil, fmt.Errorf("Network-based provider mirrors are not supported in this version of Terraform") } // PackageMeta retrieves metadata for the requested provider package // from the object's underlying HTTP mirror service. func (s *HTTPMirrorSource) PackageMeta(provider addrs.Provider, version Version, target Platform) (PackageMeta, error) { - // TODO: Implement - panic("HTTPMirrorSource.PackageMeta not yet implemented") + return PackageMeta{}, fmt.Errorf("Network-based provider mirrors are not supported in this version of Terraform") } diff --git a/internal/getproviders/network_mirror_source.go b/internal/getproviders/network_mirror_source.go deleted file mode 100644 index 26b8ba0f8..000000000 --- a/internal/getproviders/network_mirror_source.go +++ /dev/null @@ -1,39 +0,0 @@ -package getproviders - -import ( - "fmt" - - svchost "github.com/hashicorp/terraform-svchost" - - "github.com/hashicorp/terraform/addrs" -) - -// NetworkMirrorSource is a source that reads providers and their metadata -// from an HTTP server implementing the Terraform network mirror protocol. -type NetworkMirrorSource struct { - host svchost.Hostname -} - -var _ Source = (*NetworkMirrorSource)(nil) - -// NewNetworkMirrorSource constructs and returns a new network-based -// mirror source that will expect to find a mirror service on the given -// host. -func NewNetworkMirrorSource(host svchost.Hostname) *NetworkMirrorSource { - return &NetworkMirrorSource{ - host: host, - } -} - -// AvailableVersions retrieves the available versions for the given provider -// from the network mirror. -func (s *NetworkMirrorSource) AvailableVersions(provider addrs.Provider) (VersionList, error) { - return nil, fmt.Errorf("Network provider mirror is not supported in this version of Terraform") -} - -// PackageMeta checks to see if the network mirror contains a copy of the -// distribution package for the given provider version on the given target, -// and returns the metadata about it if so. -func (s *NetworkMirrorSource) PackageMeta(provider addrs.Provider, version Version, target Platform) (PackageMeta, error) { - return PackageMeta{}, fmt.Errorf("Network provider mirror is not supported in this version of Terraform") -} diff --git a/provider_source.go b/provider_source.go index bfbdf0f3f..1d804342e 100644 --- a/provider_source.go +++ b/provider_source.go @@ -3,11 +3,11 @@ package main import ( "fmt" "log" + "net/url" "os" "path/filepath" "github.com/apparentlymart/go-userdirs/userdirs" - svchost "github.com/hashicorp/terraform-svchost" "github.com/hashicorp/terraform-svchost/disco" "github.com/hashicorp/terraform/addrs" @@ -192,17 +192,26 @@ func providerSourceForCLIConfigLocation(loc cliconfig.ProviderInstallationSource return getproviders.NewFilesystemMirrorSource(string(loc)), nil case cliconfig.ProviderInstallationNetworkMirror: - host, err := svchost.ForComparison(string(loc)) + url, err := url.Parse(string(loc)) if err != nil { var diags tfdiags.Diagnostics diags = diags.Append(tfdiags.Sourceless( tfdiags.Error, - "Invalid hostname for provider installation source", - fmt.Sprintf("Cannot parse %q as a hostname for a network provider mirror: %s.", string(loc), err), + "Invalid URL for provider installation source", + fmt.Sprintf("Cannot parse %q as a URL for a network provider mirror: %s.", string(loc), err), )) return nil, diags } - return getproviders.NewNetworkMirrorSource(host), nil + if url.Scheme != "https" || url.Host == "" { + var diags tfdiags.Diagnostics + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Invalid URL for provider installation source", + fmt.Sprintf("Cannot use %q as a URL for a network provider mirror: the mirror must be at an https: URL.", string(loc)), + )) + return nil, diags + } + return getproviders.NewHTTPMirrorSource(url), nil default: // We should not get here because the set of cases above should