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 exclude = bodyContent.Exclude
case "network_mirror": case "network_mirror":
type BodyContent struct { type BodyContent struct {
Host string `hcl:"host"` URL string `hcl:"url"`
Include []string `hcl:"include"` Include []string `hcl:"include"`
Exclude []string `hcl:"exclude"` Exclude []string `hcl:"exclude"`
} }
@ -152,15 +152,15 @@ func decodeProviderInstallationFromConfig(hclFile *hclast.File) ([]*ProviderInst
)) ))
continue continue
} }
if bodyContent.Host == "" { if bodyContent.URL == "" {
diags = diags.Append(tfdiags.Sourceless( diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error, tfdiags.Error,
"Invalid provider_installation source block", "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 continue
} }
location = ProviderInstallationNetworkMirror(bodyContent.Host) location = ProviderInstallationNetworkMirror(bodyContent.URL)
include = bodyContent.Include include = bodyContent.Include
exclude = bodyContent.Exclude exclude = bodyContent.Exclude
default: default:
@ -229,8 +229,8 @@ func (i ProviderInstallationFilesystemMirror) providerInstallationLocation() {}
// ProviderInstallationNetworkMirror is a ProviderInstallationSourceLocation // ProviderInstallationNetworkMirror is a ProviderInstallationSourceLocation
// representing installation from a particular local network mirror. The // representing installation from a particular local network mirror. The
// string value is the hostname exactly as written in the configuration, without // string value is the HTTP base URL exactly as written in the configuration,
// any normalization. // without any normalization.
type ProviderInstallationNetworkMirror string type ProviderInstallationNetworkMirror string
func (i ProviderInstallationNetworkMirror) providerInstallationLocation() {} func (i ProviderInstallationNetworkMirror) providerInstallationLocation() {}

View File

@ -22,7 +22,7 @@ func TestLoadConfig_providerInstallation(t *testing.T) {
Include: []string{"example.com/*/*"}, Include: []string{"example.com/*/*"},
}, },
{ {
Location: ProviderInstallationNetworkMirror("tf-Mirror.example.com"), Location: ProviderInstallationNetworkMirror("https://tf-Mirror.example.com/"),
Include: []string{"registry.terraform.io/*/*"}, Include: []string{"registry.terraform.io/*/*"},
Exclude: []string{"registry.Terraform.io/foobar/*"}, 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: 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 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 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 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. - 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/*/*"] include = ["example.com/*/*"]
} }
network_mirror { network_mirror {
host = "tf-Mirror.example.com" url = "https://tf-Mirror.example.com/"
include = ["registry.terraform.io/*/*"] include = ["registry.terraform.io/*/*"]
exclude = ["registry.Terraform.io/foobar/*"] exclude = ["registry.Terraform.io/foobar/*"]
} }

View File

@ -1,6 +1,7 @@
package getproviders package getproviders
import ( import (
"fmt"
"net/url" "net/url"
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
@ -26,13 +27,11 @@ func NewHTTPMirrorSource(baseURL *url.URL) *HTTPMirrorSource {
// AvailableVersions retrieves the available versions for the given provider // AvailableVersions retrieves the available versions for the given provider
// from the object's underlying HTTP mirror service. // from the object's underlying HTTP mirror service.
func (s *HTTPMirrorSource) AvailableVersions(provider addrs.Provider) (VersionList, error) { func (s *HTTPMirrorSource) AvailableVersions(provider addrs.Provider) (VersionList, error) {
// TODO: Implement return nil, fmt.Errorf("Network-based provider mirrors are not supported in this version of Terraform")
panic("HTTPMirrorSource.AvailableVersions not yet implemented")
} }
// PackageMeta retrieves metadata for the requested provider package // PackageMeta retrieves metadata for the requested provider package
// from the object's underlying HTTP mirror service. // from the object's underlying HTTP mirror service.
func (s *HTTPMirrorSource) PackageMeta(provider addrs.Provider, version Version, target Platform) (PackageMeta, error) { func (s *HTTPMirrorSource) PackageMeta(provider addrs.Provider, version Version, target Platform) (PackageMeta, error) {
// TODO: Implement return PackageMeta{}, fmt.Errorf("Network-based provider mirrors are not supported in this version of Terraform")
panic("HTTPMirrorSource.PackageMeta not yet implemented")
} }

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 ( import (
"fmt" "fmt"
"log" "log"
"net/url"
"os" "os"
"path/filepath" "path/filepath"
"github.com/apparentlymart/go-userdirs/userdirs" "github.com/apparentlymart/go-userdirs/userdirs"
svchost "github.com/hashicorp/terraform-svchost"
"github.com/hashicorp/terraform-svchost/disco" "github.com/hashicorp/terraform-svchost/disco"
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
@ -192,17 +192,26 @@ func providerSourceForCLIConfigLocation(loc cliconfig.ProviderInstallationSource
return getproviders.NewFilesystemMirrorSource(string(loc)), nil return getproviders.NewFilesystemMirrorSource(string(loc)), nil
case cliconfig.ProviderInstallationNetworkMirror: case cliconfig.ProviderInstallationNetworkMirror:
host, err := svchost.ForComparison(string(loc)) url, err := url.Parse(string(loc))
if err != nil { if err != nil {
var diags tfdiags.Diagnostics var diags tfdiags.Diagnostics
diags = diags.Append(tfdiags.Sourceless( diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error, tfdiags.Error,
"Invalid hostname for provider installation source", "Invalid URL for provider installation source",
fmt.Sprintf("Cannot parse %q as a hostname for a network provider mirror: %s.", string(loc), err), fmt.Sprintf("Cannot parse %q as a URL for a network provider mirror: %s.", string(loc), err),
)) ))
return nil, diags 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: default:
// We should not get here because the set of cases above should // We should not get here because the set of cases above should