internal/getproviders: Implement MultiSource
We previously had only a stub implementation for a totally-empty MultiSource. Here we have an initial implementation of the full functionality, which we'll need to support "terraform init -plugin-dir=..." in a subsequent commit.
This commit is contained in:
parent
2ff4582be2
commit
f7072a8f29
|
@ -145,3 +145,24 @@ func (err ErrQueryFailed) Error() string {
|
|||
func (err ErrQueryFailed) Unwrap() error {
|
||||
return err.Wrapped
|
||||
}
|
||||
|
||||
// ErrIsNotExist returns true if and only if the given error is one of the
|
||||
// errors from this package that represents an affirmative response that a
|
||||
// requested object does not exist.
|
||||
//
|
||||
// This is as opposed to errors indicating that the source is unavailable
|
||||
// or misconfigured in some way, where we therefore cannot say for certain
|
||||
// whether the requested object exists.
|
||||
//
|
||||
// If a caller needs to take a special action based on something not existing,
|
||||
// such as falling back on some other source, use this function rather than
|
||||
// direct type assertions so that the set of possible "not exist" errors can
|
||||
// grow in future.
|
||||
func ErrIsNotExist(err error) bool {
|
||||
switch err.(type) {
|
||||
case ErrProviderNotKnown, ErrPlatformNotSupported:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package getproviders
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
svchost "github.com/hashicorp/terraform-svchost"
|
||||
|
@ -34,19 +33,68 @@ func (s MultiSource) AvailableVersions(provider addrs.Provider) (VersionList, er
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
// TODO: Implement
|
||||
panic("MultiSource.AvailableVersions not yet implemented")
|
||||
// We will return the union of all versions reported by the nested
|
||||
// sources that have matching patterns that accept the given provider.
|
||||
vs := make(map[Version]struct{})
|
||||
for _, selector := range s {
|
||||
if !selector.CanHandleProvider(provider) {
|
||||
continue // doesn't match the given patterns
|
||||
}
|
||||
thisSourceVersions, err := selector.Source.AvailableVersions(provider)
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
// okay
|
||||
case ErrProviderNotKnown:
|
||||
continue // ignore, then
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
for _, v := range thisSourceVersions {
|
||||
vs[v] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
if len(vs) == 0 {
|
||||
return nil, ErrProviderNotKnown{provider}
|
||||
}
|
||||
ret := make(VersionList, 0, len(vs))
|
||||
for v := range vs {
|
||||
ret = append(ret, v)
|
||||
}
|
||||
ret.Sort()
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// PackageMeta retrieves the package metadata for the given provider from the
|
||||
// first selector that indicates support for it.
|
||||
// PackageMeta retrieves the package metadata for the requested provider package
|
||||
// from the first selector that indicates availability of it.
|
||||
func (s MultiSource) PackageMeta(provider addrs.Provider, version Version, target Platform) (PackageMeta, error) {
|
||||
if len(s) == 0 { // Easy case: no providers exist at all
|
||||
return PackageMeta{}, ErrProviderNotKnown{provider}
|
||||
}
|
||||
|
||||
// TODO: Implement
|
||||
panic("MultiSource.PackageMeta not yet implemented")
|
||||
for _, selector := range s {
|
||||
if !selector.CanHandleProvider(provider) {
|
||||
continue // doesn't match the given patterns
|
||||
}
|
||||
meta, err := selector.Source.PackageMeta(provider, version, target)
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
return meta, nil
|
||||
case ErrProviderNotKnown, ErrPlatformNotSupported:
|
||||
continue // ignore, then
|
||||
default:
|
||||
return PackageMeta{}, err
|
||||
}
|
||||
}
|
||||
|
||||
// If we fall out here then none of the sources have the requested
|
||||
// package.
|
||||
return PackageMeta{}, ErrPlatformNotSupported{
|
||||
Provider: provider,
|
||||
Version: version,
|
||||
Platform: target,
|
||||
}
|
||||
}
|
||||
|
||||
// MultiSourceSelector is an element of the source selection configuration on
|
||||
|
@ -103,10 +151,10 @@ func ParseMultiSourceMatchingPatterns(strs []string) (MultiSourceMatchingPattern
|
|||
parts = parts[1:]
|
||||
}
|
||||
|
||||
if !validProviderNamePattern.MatchString(parts[1]) {
|
||||
if !validProviderNameOrWildcard(parts[1]) {
|
||||
return nil, fmt.Errorf("invalid provider type %q in provider matching pattern %q: must either be the wildcard * or a provider type name", parts[1], str)
|
||||
}
|
||||
if !validProviderNamePattern.MatchString(parts[0]) {
|
||||
if !validProviderNameOrWildcard(parts[0]) {
|
||||
return nil, fmt.Errorf("invalid registry namespace %q in provider matching pattern %q: must either be the wildcard * or a literal namespace", parts[1], str)
|
||||
}
|
||||
|
||||
|
@ -165,6 +213,12 @@ const Wildcard string = "*"
|
|||
// We'll read the default registry host from over in the addrs package, to
|
||||
// avoid duplicating it. A "default" provider uses the default registry host
|
||||
// by definition.
|
||||
var defaultRegistryHost = addrs.NewDefaultProvider("placeholder").Hostname
|
||||
var defaultRegistryHost = addrs.DefaultRegistryHost
|
||||
|
||||
var validProviderNamePattern = regexp.MustCompile("^[a-zA-Z0-9_-]+|\\*$")
|
||||
func validProviderNameOrWildcard(s string) bool {
|
||||
if s == Wildcard {
|
||||
return true
|
||||
}
|
||||
_, err := addrs.ParseProviderPart(s)
|
||||
return err == nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue