core: Better error message for prematurely-removed provider config

This error message appears in a situation that is often confusing for
users, since the connection between resources and their providers in the
state is not something we draw attention to in the user experience of
Terraform.

This new error message tries to be a bit clearer about what the user must
do to resolve it. It's still not perfect since it doesn't cover the
variant of this problem where an entire module containing a provider block
and resources has been removed at the same time, but since there isn't
an easily-summarizable way to continue in that state this will need to
do for the moment, until we find a way to file off that rough edge in
the workflow.
This commit is contained in:
Martin Atkins 2018-09-27 14:10:51 -07:00
parent 4a62315d35
commit 76fca28faa
1 changed files with 12 additions and 8 deletions

View File

@ -4,11 +4,11 @@ import (
"fmt" "fmt"
"log" "log"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/hcl2/hcl" "github.com/hashicorp/hcl2/hcl"
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/configs"
"github.com/hashicorp/terraform/dag" "github.com/hashicorp/terraform/dag"
"github.com/hashicorp/terraform/tfdiags"
) )
func TransformProviders(providers []string, concrete ConcreteProviderNodeFunc, config *configs.Config) GraphTransformer { func TransformProviders(providers []string, concrete ConcreteProviderNodeFunc, config *configs.Config) GraphTransformer {
@ -84,7 +84,7 @@ func (t *ProviderTransformer) Transform(g *Graph) error {
// the graph, and then create graph edges from provider to provider user // the graph, and then create graph edges from provider to provider user
// so that the providers will get initialized first. // so that the providers will get initialized first.
var err error var diags tfdiags.Diagnostics
// To start, we'll collect the _requested_ provider addresses for each // To start, we'll collect the _requested_ provider addresses for each
// node, which we'll then resolve (handling provider inheritence, etc) in // node, which we'll then resolve (handling provider inheritence, etc) in
@ -131,8 +131,8 @@ func (t *ProviderTransformer) Transform(g *Graph) error {
_, ok := v.(GraphNodeSubPath) _, ok := v.(GraphNodeSubPath)
if !ok && target == nil { if !ok && target == nil {
// No target and no path to traverse up grom // No target and no path to traverse up from
err = multierror.Append(err, fmt.Errorf("%s: provider %s couldn't be found", dag.VertexName(v), p)) diags = diags.Append(fmt.Errorf("%s: provider %s couldn't be found", dag.VertexName(v), p))
continue continue
} }
@ -171,9 +171,13 @@ func (t *ProviderTransformer) Transform(g *Graph) error {
} }
if target == nil { if target == nil {
err = multierror.Append(err, fmt.Errorf( diags = diags.Append(tfdiags.Sourceless(
"%s: configuration for %s is not present; a provider configuration block is required for all operations", tfdiags.Error,
dag.VertexName(v), p, "Provider configuration not present",
fmt.Sprintf(
"To work with %s its original provider configuration at %s is required, but it has been removed. This occurs when a provider configuration is removed while objects created by that provider still exist in the state. Re-add the provider configuration to destroy %s, after which you can remove the provider configuration again.",
dag.VertexName(v), p, dag.VertexName(v),
),
)) ))
break break
} }
@ -193,7 +197,7 @@ func (t *ProviderTransformer) Transform(g *Graph) error {
} }
} }
return err return diags.Err()
} }
// CloseProviderTransformer is a GraphTransformer that adds nodes to the // CloseProviderTransformer is a GraphTransformer that adds nodes to the