diff --git a/internal/command/e2etest/provider_plugin_test.go b/internal/command/e2etest/provider_plugin_test.go index 8b3aa3af7d83..49fa793dc1ad 100644 --- a/internal/command/e2etest/provider_plugin_test.go +++ b/internal/command/e2etest/provider_plugin_test.go @@ -72,6 +72,16 @@ func TestProviderProtocols(t *testing.T) { } if !strings.Contains(stdout, "Apply complete! Resources: 2 added, 0 changed, 0 destroyed.") { - t.Fatalf("wrong output:\n%s", stdout) + t.Fatalf("wrong output:\nstdout:%s\nstderr%s", stdout, stderr) + } + + /// DESTROY + stdout, stderr, err = tf.Run("destroy", "-auto-approve") + if err != nil { + t.Fatalf("unexpected apply error: %s\nstderr:\n%s", err, stderr) + } + + if !strings.Contains(stdout, "Resources: 2 destroyed") { + t.Fatalf("wrong destroy output\nstdout:%s\nstderr:%s", stdout, stderr) } } diff --git a/internal/grpcwrap/provider.go b/internal/grpcwrap/provider.go index 4671606c266f..590faf1d7cf3 100644 --- a/internal/grpcwrap/provider.go +++ b/internal/grpcwrap/provider.go @@ -59,6 +59,10 @@ func (p *provider) GetSchema(_ context.Context, req *tfplugin5.GetProviderSchema } } + resp.Capabilities = &tfplugin5.GetProviderSchema_Capabilities{ + PlanDestroy: p.schema.Capabilities.PlanDestroy, + } + // include any diagnostics from the original GetSchema call resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, p.schema.Diagnostics) diff --git a/internal/grpcwrap/provider6.go b/internal/grpcwrap/provider6.go index dd82e0956c9c..61c3e55ed2c8 100644 --- a/internal/grpcwrap/provider6.go +++ b/internal/grpcwrap/provider6.go @@ -59,6 +59,10 @@ func (p *provider6) GetProviderSchema(_ context.Context, req *tfplugin6.GetProvi } } + resp.Capabilities = &tfplugin6.GetProviderSchema_Capabilities{ + PlanDestroy: p.schema.Capabilities.PlanDestroy, + } + // include any diagnostics from the original GetSchema call resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, p.schema.Diagnostics) diff --git a/internal/provider-simple-v6/provider.go b/internal/provider-simple-v6/provider.go index e8768099e545..325ebc1a3113 100644 --- a/internal/provider-simple-v6/provider.go +++ b/internal/provider-simple-v6/provider.go @@ -3,6 +3,7 @@ package simple import ( "errors" + "fmt" "time" "github.com/hashicorp/terraform/internal/configs/configschema" @@ -42,6 +43,9 @@ func Provider() providers.Interface { DataSources: map[string]providers.Schema{ "simple_resource": simpleResource, }, + Capabilities: providers.Capabilities{ + PlanDestroy: true, + }, }, } } @@ -88,7 +92,10 @@ func (s simple) PlanResourceChange(req providers.PlanResourceChangeRequest) (res if req.ProposedNewState.IsNull() { // destroy op resp.PlannedState = req.ProposedNewState - resp.PlannedPrivate = req.PriorPrivate + + // signal that this resource was properly planned for destruction, + // verifying that the schema capabilities with PlanDestroy took effect. + resp.PlannedPrivate = []byte("destroy planned") return resp } @@ -104,6 +111,11 @@ func (s simple) PlanResourceChange(req providers.PlanResourceChangeRequest) (res func (s simple) ApplyResourceChange(req providers.ApplyResourceChangeRequest) (resp providers.ApplyResourceChangeResponse) { if req.PlannedState.IsNull() { + // make sure this was transferred from the plan action + if string(req.PlannedPrivate) != "destroy planned" { + resp.Diagnostics = resp.Diagnostics.Append(fmt.Errorf("resource not planned for destroy, private data %q", req.PlannedPrivate)) + } + resp.NewState = req.PlannedState return resp } diff --git a/internal/provider-simple/provider.go b/internal/provider-simple/provider.go index e8768099e545..4a81f12252eb 100644 --- a/internal/provider-simple/provider.go +++ b/internal/provider-simple/provider.go @@ -42,6 +42,9 @@ func Provider() providers.Interface { DataSources: map[string]providers.Schema{ "simple_resource": simpleResource, }, + Capabilities: providers.Capabilities{ + PlanDestroy: true, + }, }, } }