mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Fix data provider iteration destroy (#2270)
Signed-off-by: Christian Mesh <christianmesh1@gmail.com>
This commit is contained in:
parent
ffa43acfcd
commit
ece1bb4f49
@ -53,6 +53,8 @@ issues:
|
||||
- funlen
|
||||
- dupl
|
||||
- revive
|
||||
- gocognit
|
||||
- cyclop
|
||||
- path: (.+)_test.go
|
||||
text: "ST1003"
|
||||
- path: (.+)_test.go
|
||||
|
@ -4165,6 +4165,12 @@ locals {
|
||||
providers = { "primary": "eu-west-1", "secondary": "eu-west-2" }
|
||||
resources = ["primary"]
|
||||
}
|
||||
`
|
||||
localMissing := `
|
||||
locals {
|
||||
providers = { "primary": "eu-west-1"}
|
||||
resources = ["primary", "secondary"]
|
||||
}
|
||||
`
|
||||
providerConfig := `
|
||||
provider "test" {
|
||||
@ -4178,6 +4184,10 @@ resource "test_instance" "a" {
|
||||
for_each = toset(local.resources)
|
||||
provider = test.al[each.key]
|
||||
}
|
||||
data "test_data_source" "b" {
|
||||
for_each = toset(local.resources)
|
||||
provider = test.al[each.key]
|
||||
}
|
||||
`
|
||||
complete := testModuleInline(t, map[string]string{
|
||||
"locals.tofu": localComplete,
|
||||
@ -4193,11 +4203,18 @@ resource "test_instance" "a" {
|
||||
"locals.tofu": localPartial,
|
||||
"providers.tofu": providerConfig,
|
||||
})
|
||||
missingKey := testModuleInline(t, map[string]string{
|
||||
"locals.tofu": localMissing,
|
||||
"providers.tofu": providerConfig,
|
||||
"resources.tofu": resourceConfig,
|
||||
})
|
||||
empty := testModuleInline(t, nil)
|
||||
|
||||
provider := testProvider("test")
|
||||
provider.ReadDataSourceResponse = &providers.ReadDataSourceResponse{
|
||||
State: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.StringVal("data_source"),
|
||||
"id": cty.StringVal("data_source"),
|
||||
"foo": cty.StringVal("ok"),
|
||||
}),
|
||||
}
|
||||
provider.ConfigureProviderFn = func(req providers.ConfigureProviderRequest) providers.ConfigureProviderResponse {
|
||||
@ -4213,7 +4230,7 @@ resource "test_instance" "a" {
|
||||
addrs.NewDefaultProvider("test"): testProviderFuncFixed(provider),
|
||||
}
|
||||
|
||||
apply := func(t *testing.T, m *configs.Config, prevState *states.State) *states.State {
|
||||
apply := func(t *testing.T, m *configs.Config, prevState *states.State) (*states.State, tfdiags.Diagnostics) {
|
||||
t.Helper()
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: ps,
|
||||
@ -4221,17 +4238,13 @@ resource "test_instance" "a" {
|
||||
|
||||
plan, diags := ctx.Plan(context.Background(), m, prevState, DefaultPlanOpts)
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
newState, diags := ctx.Apply(context.Background(), plan, m)
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
return newState
|
||||
return ctx.Apply(context.Background(), plan, m)
|
||||
}
|
||||
|
||||
destroy := func(t *testing.T, m *configs.Config, prevState *states.State) *states.State {
|
||||
destroy := func(t *testing.T, m *configs.Config, prevState *states.State) (*states.State, tfdiags.Diagnostics) {
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: ps,
|
||||
})
|
||||
@ -4240,21 +4253,20 @@ resource "test_instance" "a" {
|
||||
Mode: plans.DestroyMode,
|
||||
})
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
newState, diags := ctx.Apply(context.Background(), plan, m)
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
return newState
|
||||
return ctx.Apply(context.Background(), plan, m)
|
||||
}
|
||||
|
||||
primaryResource := mustResourceInstanceAddr(`test_instance.a["primary"]`)
|
||||
secondaryResource := mustResourceInstanceAddr(`test_instance.a["secondary"]`)
|
||||
|
||||
t.Run("apply_destroy", func(t *testing.T) {
|
||||
state := apply(t, complete, states.NewState())
|
||||
state, diags := apply(t, complete, states.NewState())
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
|
||||
if state.ResourceInstance(primaryResource).ProviderKey != addrs.StringKey("primary") {
|
||||
t.Fatal("Wrong provider key")
|
||||
@ -4263,13 +4275,22 @@ resource "test_instance" "a" {
|
||||
t.Fatal("Wrong provider key")
|
||||
}
|
||||
|
||||
destroy(t, complete, state)
|
||||
_, diags = destroy(t, complete, state)
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("apply_removed", func(t *testing.T) {
|
||||
state := apply(t, complete, states.NewState())
|
||||
state, diags := apply(t, complete, states.NewState())
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
|
||||
state = apply(t, removed, state)
|
||||
state, diags = apply(t, removed, state)
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
|
||||
// Expect destroyed
|
||||
if state.ResourceInstance(primaryResource) != nil {
|
||||
@ -4281,9 +4302,15 @@ resource "test_instance" "a" {
|
||||
})
|
||||
|
||||
t.Run("apply_orphan_destroy", func(t *testing.T) {
|
||||
state := apply(t, complete, states.NewState())
|
||||
state, diags := apply(t, complete, states.NewState())
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
|
||||
state = apply(t, partial, state)
|
||||
state, diags = apply(t, partial, state)
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
|
||||
// Expect primary
|
||||
if state.ResourceInstance(primaryResource) == nil {
|
||||
@ -4294,7 +4321,46 @@ resource "test_instance" "a" {
|
||||
t.Fatal(secondaryResource.String())
|
||||
}
|
||||
|
||||
destroy(t, partial, state)
|
||||
_, diags = destroy(t, partial, state)
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("provider_key_removed_apply", func(t *testing.T) {
|
||||
state, diags := apply(t, complete, states.NewState())
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
|
||||
_, diags = apply(t, missingKey, state)
|
||||
if !diags.HasErrors() {
|
||||
t.Fatal("expected diags")
|
||||
}
|
||||
for _, diag := range diags {
|
||||
if diag.Description().Summary == "Provider instance not present" {
|
||||
return
|
||||
}
|
||||
}
|
||||
t.Fatal(diags.Err())
|
||||
})
|
||||
|
||||
t.Run("empty", func(t *testing.T) {
|
||||
state, diags := apply(t, complete, states.NewState())
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
|
||||
_, diags = apply(t, empty, state)
|
||||
if !diags.HasErrors() {
|
||||
t.Fatal("expected diags")
|
||||
}
|
||||
for _, diag := range diags {
|
||||
if diag.Description().Summary == "Provider configuration not present" {
|
||||
return
|
||||
}
|
||||
}
|
||||
t.Fatal(diags.Err())
|
||||
})
|
||||
}
|
||||
|
||||
@ -4310,6 +4376,12 @@ locals {
|
||||
providers = { "primary": "eu-west-1", "secondary": "eu-west-2" }
|
||||
mods = ["primary"]
|
||||
}
|
||||
`
|
||||
localMissing := `
|
||||
locals {
|
||||
providers = { "primary": "eu-west-1"}
|
||||
mods = ["primary", "secondary"]
|
||||
}
|
||||
`
|
||||
providerConfig := `
|
||||
provider "test" {
|
||||
@ -4330,6 +4402,8 @@ module "mod" {
|
||||
resourceConfig := `
|
||||
resource "test_instance" "a" {
|
||||
}
|
||||
data "test_data_source" "b" {
|
||||
}
|
||||
`
|
||||
complete := testModuleInline(t, map[string]string{
|
||||
"locals.tofu": localComplete,
|
||||
@ -4347,11 +4421,19 @@ resource "test_instance" "a" {
|
||||
"locals.tofu": localPartial,
|
||||
"providers.tofu": providerConfig,
|
||||
})
|
||||
missingKey := testModuleInline(t, map[string]string{
|
||||
"locals.tofu": localMissing,
|
||||
"providers.tofu": providerConfig,
|
||||
"modules.tofu": moduleCall,
|
||||
"mod/resources.tofu": resourceConfig,
|
||||
})
|
||||
empty := testModuleInline(t, nil)
|
||||
|
||||
provider := testProvider("test")
|
||||
provider.ReadDataSourceResponse = &providers.ReadDataSourceResponse{
|
||||
State: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.StringVal("data_source"),
|
||||
"id": cty.StringVal("data_source"),
|
||||
"foo": cty.StringVal("ok"),
|
||||
}),
|
||||
}
|
||||
provider.ConfigureProviderFn = func(req providers.ConfigureProviderRequest) providers.ConfigureProviderResponse {
|
||||
@ -4366,7 +4448,7 @@ resource "test_instance" "a" {
|
||||
addrs.NewDefaultProvider("test"): testProviderFuncFixed(provider),
|
||||
}
|
||||
|
||||
apply := func(t *testing.T, m *configs.Config, prevState *states.State) *states.State {
|
||||
apply := func(t *testing.T, m *configs.Config, prevState *states.State) (*states.State, tfdiags.Diagnostics) {
|
||||
t.Helper()
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: ps,
|
||||
@ -4374,17 +4456,13 @@ resource "test_instance" "a" {
|
||||
|
||||
plan, diags := ctx.Plan(context.Background(), m, prevState, DefaultPlanOpts)
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
newState, diags := ctx.Apply(context.Background(), plan, m)
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
return newState
|
||||
return ctx.Apply(context.Background(), plan, m)
|
||||
}
|
||||
|
||||
destroy := func(t *testing.T, m *configs.Config, prevState *states.State) *states.State {
|
||||
destroy := func(t *testing.T, m *configs.Config, prevState *states.State) (*states.State, tfdiags.Diagnostics) {
|
||||
ctx := testContext2(t, &ContextOpts{
|
||||
Providers: ps,
|
||||
})
|
||||
@ -4393,21 +4471,20 @@ resource "test_instance" "a" {
|
||||
Mode: plans.DestroyMode,
|
||||
})
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
return nil, diags
|
||||
}
|
||||
|
||||
newState, diags := ctx.Apply(context.Background(), plan, m)
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
return newState
|
||||
return ctx.Apply(context.Background(), plan, m)
|
||||
}
|
||||
|
||||
primaryResource := mustResourceInstanceAddr(`module.mod["primary"].test_instance.a`)
|
||||
secondaryResource := mustResourceInstanceAddr(`module.mod["secondary"].test_instance.a`)
|
||||
|
||||
t.Run("apply_destroy", func(t *testing.T) {
|
||||
state := apply(t, complete, states.NewState())
|
||||
state, diags := apply(t, complete, states.NewState())
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
|
||||
if state.ResourceInstance(primaryResource).ProviderKey != addrs.StringKey("primary") {
|
||||
t.Fatal("Wrong provider key")
|
||||
@ -4416,13 +4493,22 @@ resource "test_instance" "a" {
|
||||
t.Fatal("Wrong provider key")
|
||||
}
|
||||
|
||||
destroy(t, complete, state)
|
||||
_, diags = destroy(t, complete, state)
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("apply_removed", func(t *testing.T) {
|
||||
state := apply(t, complete, states.NewState())
|
||||
state, diags := apply(t, complete, states.NewState())
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
|
||||
state = apply(t, removed, state)
|
||||
state, diags = apply(t, removed, state)
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
|
||||
// Expect destroyed
|
||||
if state.ResourceInstance(primaryResource) != nil {
|
||||
@ -4434,9 +4520,15 @@ resource "test_instance" "a" {
|
||||
})
|
||||
|
||||
t.Run("apply_orphan_destroy", func(t *testing.T) {
|
||||
state := apply(t, complete, states.NewState())
|
||||
state, diags := apply(t, complete, states.NewState())
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
|
||||
state = apply(t, partial, state)
|
||||
state, diags = apply(t, partial, state)
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
|
||||
// Expect primary
|
||||
if state.ResourceInstance(primaryResource) == nil {
|
||||
@ -4447,7 +4539,46 @@ resource "test_instance" "a" {
|
||||
t.Fatal(secondaryResource.String())
|
||||
}
|
||||
|
||||
destroy(t, partial, state)
|
||||
_, diags = destroy(t, partial, state)
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("provider_key_removed_apply", func(t *testing.T) {
|
||||
state, diags := apply(t, complete, states.NewState())
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
|
||||
_, diags = apply(t, missingKey, state)
|
||||
if !diags.HasErrors() {
|
||||
t.Fatal("expected diags")
|
||||
}
|
||||
for _, diag := range diags {
|
||||
if diag.Description().Summary == "Provider instance not present" {
|
||||
return
|
||||
}
|
||||
}
|
||||
t.Fatal(diags.Err())
|
||||
})
|
||||
|
||||
t.Run("empty", func(t *testing.T) {
|
||||
state, diags := apply(t, complete, states.NewState())
|
||||
if diags.HasErrors() {
|
||||
t.Fatal(diags.Err())
|
||||
}
|
||||
|
||||
_, diags = apply(t, empty, state)
|
||||
if !diags.HasErrors() {
|
||||
t.Fatal("expected diags")
|
||||
}
|
||||
for _, diag := range diags {
|
||||
if diag.Description().Summary == "Provider configuration not present" {
|
||||
return
|
||||
}
|
||||
}
|
||||
t.Fatal(diags)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,11 @@ func (n *NodePlanDestroyableResourceInstance) DestroyAddr() *addrs.AbsResourceIn
|
||||
func (n *NodePlanDestroyableResourceInstance) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
|
||||
addr := n.ResourceInstanceAddr()
|
||||
|
||||
diags = diags.Append(n.resolveProvider(ctx, false))
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
}
|
||||
|
||||
switch addr.Resource.Resource.Mode {
|
||||
case addrs.ManagedResourceMode:
|
||||
return n.managedResourceExecute(ctx, op)
|
||||
@ -60,11 +65,6 @@ func (n *NodePlanDestroyableResourceInstance) Execute(ctx EvalContext, op walkOp
|
||||
func (n *NodePlanDestroyableResourceInstance) managedResourceExecute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
|
||||
addr := n.ResourceInstanceAddr()
|
||||
|
||||
diags = diags.Append(n.resolveProvider(ctx, false))
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
}
|
||||
|
||||
// Declare a bunch of variables that are used for state during
|
||||
// evaluation. These are written to by address in the EvalNodes we
|
||||
// declare below.
|
||||
|
Loading…
Reference in New Issue
Block a user