From 6cc3e1d0bd635cdae92b3e0055c19d86dfa7a222 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 20 Feb 2019 14:18:37 -0500 Subject: [PATCH] move init error to where it is generated The init error was output deep in the backend by detecting a special ResourceProviderError and formatted directly to the CLI. Create some Diagnostics closer to where the problem is detected, and passed that back through the normal diagnostic flow. While the output isn't as nice yet, this restores the helpful error message and makes the code easier to maintain. Better formatting can be handled later. --- backend/local/backend.go | 23 ----------------------- terraform/context.go | 10 ++++++---- terraform/resource_provider.go | 30 +++++++++++++++++++++++++++--- 3 files changed, 33 insertions(+), 30 deletions(-) diff --git a/backend/local/backend.go b/backend/local/backend.go index eb2053b23d..8a40503623 100644 --- a/backend/local/backend.go +++ b/backend/local/backend.go @@ -9,7 +9,6 @@ import ( "os" "path/filepath" "sort" - "strings" "sync" "github.com/hashicorp/terraform/backend" @@ -594,25 +593,3 @@ func (b *Local) stateWorkspaceDir() string { return DefaultWorkspaceDir } - -func (b *Local) pluginInitRequired(providerErr *terraform.ResourceProviderError) { - b.CLI.Output(b.Colorize().Color(fmt.Sprintf( - strings.TrimSpace(errPluginInit)+"\n", - providerErr))) -} - -// this relies on multierror to format the plugin errors below the copy -const errPluginInit = ` -[reset][bold][yellow]Plugin reinitialization required. Please run "terraform init".[reset] -[yellow]Reason: Could not satisfy plugin requirements. - -Plugins are external binaries that Terraform uses to access and manipulate -resources. The configuration provided requires plugins which can't be located, -don't satisfy the version constraints, or are otherwise incompatible. - -[reset][red]%s - -[reset][yellow]Terraform automatically discovers provider requirements from your -configuration, including providers used in child modules. To see the -requirements and constraints from each module, run "terraform providers". -` diff --git a/terraform/context.go b/terraform/context.go index 14e3863a6e..afdba99c1c 100644 --- a/terraform/context.go +++ b/terraform/context.go @@ -172,16 +172,18 @@ func NewContext(opts *ContextOpts) (*Context, tfdiags.Diagnostics) { // Bind available provider plugins to the constraints in config var providerFactories map[string]providers.Factory if opts.ProviderResolver != nil { - var err error deps := ConfigTreeDependencies(opts.Config, state) reqd := deps.AllPluginRequirements() if opts.ProviderSHA256s != nil && !opts.SkipProviderVerify { reqd.LockExecutables(opts.ProviderSHA256s) } log.Printf("[TRACE] terraform.NewContext: resolving provider version selections") - providerFactories, err = resourceProviderFactories(opts.ProviderResolver, reqd) - if err != nil { - diags = diags.Append(err) + + var providerDiags tfdiags.Diagnostics + providerFactories, providerDiags = resourceProviderFactories(opts.ProviderResolver, reqd) + diags = diags.Append(providerDiags) + + if diags.HasErrors() { return nil, diags } } else { diff --git a/terraform/resource_provider.go b/terraform/resource_provider.go index e666fb6d21..17f93e10de 100644 --- a/terraform/resource_provider.go +++ b/terraform/resource_provider.go @@ -3,6 +3,8 @@ package terraform import ( "fmt" + "github.com/hashicorp/terraform/tfdiags" + multierror "github.com/hashicorp/go-multierror" "github.com/hashicorp/terraform/plugin/discovery" "github.com/hashicorp/terraform/providers" @@ -296,13 +298,35 @@ func ProviderHasDataSource(p ResourceProvider, n string) bool { // This should be called only with configurations that have passed calls // to config.Validate(), which ensures that all of the given version // constraints are valid. It will panic if any invalid constraints are present. -func resourceProviderFactories(resolver providers.Resolver, reqd discovery.PluginRequirements) (map[string]providers.Factory, error) { +func resourceProviderFactories(resolver providers.Resolver, reqd discovery.PluginRequirements) (map[string]providers.Factory, tfdiags.Diagnostics) { + var diags tfdiags.Diagnostics ret, errs := resolver.ResolveProviders(reqd) if errs != nil { - return nil, &ResourceProviderError{ - Errors: errs, + diags = diags.Append( + tfdiags.Sourceless(tfdiags.Error, + "Could not satisfy plugin requirements", + errPluginInit, + ), + ) + + for _, err := range errs { + diags = diags.Append(err) } + + return nil, diags } return ret, nil } + +const errPluginInit = ` +Plugin reinitialization required. Please run "terraform init". + +Plugins are external binaries that Terraform uses to access and manipulate +resources. The configuration provided requires plugins which can't be located, +don't satisfy the version constraints, or are otherwise incompatible. + +Terraform automatically discovers provider requirements from your +configuration, including providers used in child modules. To see the +requirements and constraints from each module, run "terraform providers". +`