diff --git a/command/meta_providers.go b/command/meta_providers.go new file mode 100644 index 000000000..8c2a554cf --- /dev/null +++ b/command/meta_providers.go @@ -0,0 +1,63 @@ +package command + +import ( + "path/filepath" + + "github.com/hashicorp/terraform/internal/getproviders" + "github.com/hashicorp/terraform/internal/providercache" +) + +// providerLocalCacheDir returns an object representing the +// configuration-specific local cache directory. This is the +// only location consulted for provider plugin packages for Terraform +// operations other than provider installation. +// +// Only the provider installer (in "terraform init") is permitted to make +// modifications to this cache directory. All other commands must treat it +// as read-only. +func (m *Meta) providerLocalCacheDir() *providercache.Dir { + dir := filepath.Join(m.DataDir(), "plugins") + if dir == "" { + return nil // cache disabled + } + return providercache.NewDir(dir) +} + +// providerGlobalCacheDir returns an object representing the shared global +// provider cache directory, used as a read-through cache when installing +// new provider plugin packages. +// +// This function may return nil, in which case there is no global cache +// configured and new packages should be downloaded directly into individual +// configuration-specific cache directories. +func (m *Meta) providerGlobalCacheDir() *providercache.Dir { + dir := m.PluginCacheDir + if dir == "" { + return nil // cache disabled + } + return providercache.NewDir(dir) +} + +// providerInstallSource returns an object that knows how to consult one or +// more external sources to determine the availability of and package +// locations for versions of Terraform providers that are available for +// automatic installation. +// +// This returns the standard provider install source that consults a number +// of directories selected either automatically or via the CLI configuration. +// Users may choose to override this during a "terraform init" command by +// specifying one or more -plugin-dir options, in which case the installation +// process will construct its own source consulting only those directories +// and use that instead. +func (m *Meta) providerInstallSource() getproviders.Source { + // A provider source should always be provided in normal use, but our + // unit tests might not always populate Meta fully and so we'll be robust + // by returning a non-nil source that just always answers that no plugins + // are available. + if m.ProviderSource == nil { + // A multi-source with no underlying sources is effectively an + // always-empty source. + return getproviders.MultiSource(nil) + } + return m.ProviderSource +} diff --git a/internal/getproviders/types.go b/internal/getproviders/types.go index 9d720be66..fce626d1d 100644 --- a/internal/getproviders/types.go +++ b/internal/getproviders/types.go @@ -35,6 +35,12 @@ func ParseVersion(str string) (Version, error) { return versions.ParseVersion(str) } +// ParseVersionConstraints parses a "Ruby-like" version constraint string +// into a VersionConstraints value. +func ParseVersionConstraints(str string) (VersionConstraints, error) { + return constraints.ParseRubyStyleMulti(str) +} + // Platform represents a target platform that a provider is or might be // available for. type Platform struct { diff --git a/internal/providercache/installer.go b/internal/providercache/installer.go index 72ef59106..60ae2bac7 100644 --- a/internal/providercache/installer.go +++ b/internal/providercache/installer.go @@ -345,7 +345,7 @@ func (err InstallerError) Error() string { b.WriteString("some providers could not be installed:\n") for _, addr := range addrs { providerErr := err.ProviderErrors[addr] - fmt.Fprintf(&b, "- %s: %s\n", addr, providerErr.Error()) + fmt.Fprintf(&b, "- %s: %s\n", addr, providerErr) } return b.String() }