test data source destroy with no provider

This commit is contained in:
James Bardin 2021-03-08 15:33:07 -05:00
parent 58b085f0dc
commit e6ab48addf
1 changed files with 108 additions and 0 deletions

View File

@ -1,11 +1,14 @@
package terraform package terraform
import ( import (
"errors"
"fmt"
"testing" "testing"
"github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/providers"
"github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states"
"github.com/zclconf/go-cty/cty"
) )
// Test that the PreApply hook is called with the correct deposed key // Test that the PreApply hook is called with the correct deposed key
@ -69,3 +72,108 @@ func TestContext2Apply_createBeforeDestroy_deposedKeyPreApply(t *testing.T) {
t.Errorf("expected gen to be %q, but was %q", deposedKey, gen) t.Errorf("expected gen to be %q, but was %q", deposedKey, gen)
} }
} }
func TestContext2Apply_destroyWithDataSourceExpansion(t *testing.T) {
// While managed resources store their destroy-time dependencies, data
// sources do not. This means that if a provider were only included in a
// destroy graph because of data sources, it could have dependencies which
// are not correctly ordered. Here we verify that the provider is not
// included in the destroy operation, and all dependency evaluations
// succeed.
m := testModuleInline(t, map[string]string{
"main.tf": `
module "mod" {
source = "./mod"
}
provider "other" {
foo = module.mod.data
}
# this should not require the provider be present during destroy
data "other_data_source" "a" {
}
`,
"mod/main.tf": `
data "test_data_source" "a" {
count = 1
}
data "test_data_source" "b" {
count = data.test_data_source.a[0].foo == "ok" ? 1 : 0
}
output "data" {
value = data.test_data_source.a[0].foo == "ok" ? data.test_data_source.b[0].foo : "nope"
}
`,
})
testP := testProvider("test")
otherP := testProvider("other")
readData := func(req providers.ReadDataSourceRequest) providers.ReadDataSourceResponse {
return providers.ReadDataSourceResponse{
State: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("data_source"),
"foo": cty.StringVal("ok"),
}),
}
}
testP.ReadDataSourceFn = readData
otherP.ReadDataSourceFn = readData
ps := map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(testP),
addrs.NewDefaultProvider("other"): testProviderFuncFixed(otherP),
}
otherP.ConfigureProviderFn = func(req providers.ConfigureProviderRequest) (resp providers.ConfigureProviderResponse) {
foo := req.Config.GetAttr("foo")
if foo.IsNull() || foo.AsString() != "ok" {
resp.Diagnostics = resp.Diagnostics.Append(fmt.Errorf("incorrect config val: %#v\n", foo))
}
return resp
}
ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: ps,
})
_, diags := ctx.Plan()
if diags.HasErrors() {
t.Fatal(diags.Err())
}
_, diags = ctx.Apply()
if diags.HasErrors() {
t.Fatal(diags.Err())
}
// now destroy the whole thing
ctx = testContext2(t, &ContextOpts{
Config: m,
Providers: ps,
Destroy: true,
})
_, diags = ctx.Plan()
if diags.HasErrors() {
t.Fatal(diags.Err())
}
otherP.ConfigureProviderFn = func(req providers.ConfigureProviderRequest) (resp providers.ConfigureProviderResponse) {
// should not be used to destroy data sources
resp.Diagnostics = resp.Diagnostics.Append(errors.New("provider should not be used"))
return resp
}
_, diags = ctx.Apply()
if diags.HasErrors() {
t.Fatal(diags.Err())
}
}