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.
This commit is contained in:
Martin Atkins 2020-04-22 15:58:40 -07:00
parent b8856c677c
commit 8b75d1498f
6 changed files with 26 additions and 57 deletions

View File

@ -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() {}

View File

@ -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.

View File

@ -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/*"]
}

View File

@ -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")
}

View File

@ -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")
}

View File

@ -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