command/init: Remove the warnings about the "legacy" cache directory
We included these warnings in v0.14 after noticing that we'd accidentally published some incorrect documentation about the purpose of the plugin cache directory under .terraform/plugins. We switched to using .terraform/providers instead so that we could treat any missing providers that appear in the legacy directory as likely to be a result of following that documentation, and thus produce this extra warning. However, the further we get from v0.13 the more likely it is for this warning to be a confusing false positive rather than something helpful, and this is a non-trivial codepath requiring us to retain a concept that we otherwise don't need (the "legacy cache dir"), so here we'll remove those warnings and support code for v0.15 onwards. These warnings were always accompanied by an error message saying that a provider could not be found, and that error message remains after this change. This just removes the "by the way..."-style warning we had been emitting alongside the errors.
This commit is contained in:
parent
9b0af78f24
commit
bab4979128
|
@ -5,7 +5,6 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
|
@ -483,7 +482,6 @@ func (c *InitCommand) getProviders(config *configs.Config, state *states.State,
|
|||
// things relatively concise. Later it'd be nice to have a progress UI
|
||||
// where statuses update in-place, but we can't do that as long as we
|
||||
// are shimming our vt100 output to the legacy console API on Windows.
|
||||
missingProviders := make(map[addrs.Provider]struct{})
|
||||
evts := &providercache.InstallerEvents{
|
||||
PendingProviders: func(reqs map[addrs.Provider]getproviders.VersionConstraints) {
|
||||
c.Ui.Output(c.Colorize().Color(
|
||||
|
@ -521,10 +519,6 @@ func (c *InitCommand) getProviders(config *configs.Config, state *states.State,
|
|||
c.Ui.Info(fmt.Sprintf("- Installing %s v%s...", provider.ForDisplay(), version))
|
||||
},
|
||||
QueryPackagesFailure: func(provider addrs.Provider, err error) {
|
||||
// We track providers that had missing metadata because we might
|
||||
// generate additional hints for some of them at the end.
|
||||
missingProviders[provider] = struct{}{}
|
||||
|
||||
switch errorTy := err.(type) {
|
||||
case getproviders.ErrProviderNotFound:
|
||||
sources := errorTy.Sources
|
||||
|
@ -769,60 +763,6 @@ func (c *InitCommand) getProviders(config *configs.Config, state *states.State,
|
|||
c.Ui.Error("Provider installation was canceled by an interrupt signal.")
|
||||
return true, true, diags
|
||||
}
|
||||
if len(missingProviders) > 0 {
|
||||
// If we encountered requirements for one or more providers where we
|
||||
// weren't able to find any metadata, that _might_ be because a
|
||||
// user had previously (before 0.14) been incorrectly using the
|
||||
// .terraform/plugins directory as if it were a local filesystem
|
||||
// mirror, rather than as the main cache directory.
|
||||
//
|
||||
// We no longer allow that because it'd be ambiguous whether plugins in
|
||||
// there are explictly intended to be a local mirror or if they are
|
||||
// just leftover cache entries from provider installation in
|
||||
// Terraform 0.13.
|
||||
//
|
||||
// To help those users migrate we have a specialized warning message
|
||||
// for it, which we'll produce only if one of the missing providers can
|
||||
// be seen in the "legacy" cache directory, which is what we're now
|
||||
// considering .terraform/plugins to be. (The _current_ cache directory
|
||||
// is .terraform/providers.)
|
||||
//
|
||||
// This is only a heuristic, so it might potentially produce false
|
||||
// positives if a user happens to encounter another sort of error
|
||||
// while they are upgrading from Terraform 0.13 to 0.14. Aside from
|
||||
// upgrading users should not end up in here because they won't
|
||||
// have a legacy cache directory at all.
|
||||
legacyDir := c.providerLegacyCacheDir()
|
||||
if legacyDir != nil { // if the legacy directory is present at all
|
||||
for missingProvider := range missingProviders {
|
||||
if missingProvider.IsDefault() {
|
||||
// If we get here for a default provider then it's more
|
||||
// likely that something _else_ went wrong, like a network
|
||||
// problem, so we'll skip the warning in this case to
|
||||
// avoid potentially misleading the user into creating an
|
||||
// unnecessary local mirror for an official provider.
|
||||
continue
|
||||
}
|
||||
entry := legacyDir.ProviderLatestVersion(missingProvider)
|
||||
if entry == nil {
|
||||
continue
|
||||
}
|
||||
// If we get here then the missing provider was cached, which
|
||||
// implies that it might be an in-house provider the user
|
||||
// placed manually to try to make Terraform use it as if it
|
||||
// were a local mirror directory.
|
||||
wantDir := filepath.FromSlash(fmt.Sprintf("terraform.d/plugins/%s/%s/%s", missingProvider, entry.Version, getproviders.CurrentPlatform))
|
||||
diags = diags.Append(tfdiags.Sourceless(
|
||||
tfdiags.Warning,
|
||||
"Missing provider is in legacy cache directory",
|
||||
fmt.Sprintf(
|
||||
"Terraform supports a number of local directories that can serve as automatic local filesystem mirrors, but .terraform/plugins is not one of them because Terraform v0.13 and earlier used this directory to cache copies of provider plugins retrieved from elsewhere.\n\nIf you intended to use this directory as a filesystem mirror for %s, place it instead in the following directory:\n %s",
|
||||
missingProvider, wantDir,
|
||||
),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
// The errors captured in "err" should be redundant with what we
|
||||
// received via the InstallerEvents callbacks above, so we'll
|
||||
|
|
|
@ -1053,85 +1053,6 @@ func TestInit_getProviderSource(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestInit_getProviderInLegacyPluginCacheDir(t *testing.T) {
|
||||
// Create a temporary working directory that is empty
|
||||
td := tempDir(t)
|
||||
testCopyDir(t, testFixturePath("init-legacy-provider-cache"), td)
|
||||
defer os.RemoveAll(td)
|
||||
defer testChdir(t, td)()
|
||||
|
||||
// The test fixture has placeholder os_arch directories which we must
|
||||
// now rename to match the current platform, or else the entries inside
|
||||
// will be ignored.
|
||||
platformStr := getproviders.CurrentPlatform.String()
|
||||
if err := os.Rename(
|
||||
".terraform/plugins/example.com/test/b/1.1.0/os_arch",
|
||||
".terraform/plugins/example.com/test/b/1.1.0/"+platformStr,
|
||||
); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.Rename(
|
||||
".terraform/plugins/registry.terraform.io/hashicorp/c/2.0.0/os_arch",
|
||||
".terraform/plugins/registry.terraform.io/hashicorp/c/2.0.0/"+platformStr,
|
||||
); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// An empty MultiSource serves as a way to make sure no providers are
|
||||
// actually available for installation, which suits us here because
|
||||
// we're testing an error case.
|
||||
providerSource := getproviders.MultiSource{}
|
||||
|
||||
ui := cli.NewMockUi()
|
||||
m := Meta{
|
||||
Ui: ui,
|
||||
ProviderSource: providerSource,
|
||||
}
|
||||
|
||||
c := &InitCommand{
|
||||
Meta: m,
|
||||
}
|
||||
|
||||
args := []string{
|
||||
"-backend=false",
|
||||
}
|
||||
if code := c.Run(args); code == 0 {
|
||||
t.Fatalf("succeeded; want error\n%s", ui.OutputWriter.String())
|
||||
}
|
||||
|
||||
// We remove all of the newlines so that we don't need to contend with
|
||||
// the automatic word wrapping that our diagnostic printer does.
|
||||
stderr := strings.Replace(ui.ErrorWriter.String(), "\n", " ", -1)
|
||||
|
||||
if got, want := stderr, `example.com/test/a: no available releases match the given constraints`; !strings.Contains(got, want) {
|
||||
t.Errorf("missing error about example.com/test/a\nwant substring: %s\n%s", want, got)
|
||||
}
|
||||
if got, want := stderr, `example.com/test/b: no available releases match the given constraints`; !strings.Contains(got, want) {
|
||||
t.Errorf("missing error about example.com/test/b\nwant substring: %s\n%s", want, got)
|
||||
}
|
||||
if got, want := stderr, `hashicorp/c: no available releases match the given constraints`; !strings.Contains(got, want) {
|
||||
t.Errorf("missing error about registry.terraform.io/hashicorp/c\nwant substring: %s\n%s", want, got)
|
||||
}
|
||||
|
||||
if got, want := stderr, `terraform.d/plugins/example.com/test/a`; strings.Contains(got, want) {
|
||||
// We _don't_ expect to see a warning about the "a" provider, because
|
||||
// there's no copy of that in the legacy plugin cache dir.
|
||||
t.Errorf("unexpected suggested path for local example.com/test/a\ndon't want substring: %s\n%s", want, got)
|
||||
}
|
||||
if got, want := stderr, `terraform.d/plugins/example.com/test/b/1.1.0/`+platformStr; !strings.Contains(got, want) {
|
||||
// ...but we should see a warning about the "b" provider, because
|
||||
// there's an entry for that in the legacy cache dir.
|
||||
t.Errorf("missing suggested path for local example.com/test/b 1.0.0 on %s\nwant substring: %s\n%s", platformStr, want, got)
|
||||
}
|
||||
if got, want := stderr, `terraform.d/plugins/registry.terraform.io/hashicorp/c`; strings.Contains(got, want) {
|
||||
// We _don't_ expect to see a warning about the "a" provider, even
|
||||
// though it's in the cache dir, because it's an official provider
|
||||
// and so we assume it ended up there as a result of normal provider
|
||||
// installation in Terraform 0.13.
|
||||
t.Errorf("unexpected suggested path for local hashicorp/c\ndon't want substring: %s\n%s", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInit_getProviderLegacyFromState(t *testing.T) {
|
||||
// Create a temporary working directory that is empty
|
||||
td := tempDir(t)
|
||||
|
|
|
@ -128,31 +128,6 @@ func (m *Meta) providerGlobalCacheDir() *providercache.Dir {
|
|||
return providercache.NewDir(dir)
|
||||
}
|
||||
|
||||
// providerLegacyCacheDir returns an object representing the former location
|
||||
// of the local cache directory from Terraform 0.13 and earlier.
|
||||
//
|
||||
// This is no longer viable for use as a real cache directory because some
|
||||
// incorrect documentation called for Terraform Cloud users to use it as if it
|
||||
// were an implied local filesystem mirror directory. Therefore we now use it
|
||||
// only to generate some hopefully-helpful migration guidance during
|
||||
// "terraform init" for anyone who _was_ trying to use it as a local filesystem
|
||||
// mirror directory.
|
||||
//
|
||||
// providerLegacyCacheDir returns nil if the legacy cache directory isn't
|
||||
// present or isn't a directory, so that callers can more easily skip over
|
||||
// any backward compatibility behavior that applies only when the directory
|
||||
// is present.
|
||||
//
|
||||
// Callers must use the resulting object in a read-only mode only. Don't
|
||||
// install any new providers into this directory.
|
||||
func (m *Meta) providerLegacyCacheDir() *providercache.Dir {
|
||||
dir := filepath.Join(m.DataDir(), "plugins")
|
||||
if info, err := os.Stat(dir); err != nil || !info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue