github.com/jaredpalmer/terraform@v1.1.0-alpha20210908.0.20210911170307-88705c943a03/internal/terraform/node_resource_destroy_deposed_test.go (about) 1 package terraform 2 3 import ( 4 "testing" 5 6 "github.com/hashicorp/terraform/internal/addrs" 7 "github.com/hashicorp/terraform/internal/configs/configschema" 8 "github.com/hashicorp/terraform/internal/plans" 9 "github.com/hashicorp/terraform/internal/providers" 10 "github.com/hashicorp/terraform/internal/states" 11 "github.com/zclconf/go-cty/cty" 12 ) 13 14 func TestNodePlanDeposedResourceInstanceObject_Execute(t *testing.T) { 15 deposedKey := states.NewDeposedKey() 16 state := states.NewState() 17 absResource := mustResourceInstanceAddr("test_instance.foo") 18 state.Module(addrs.RootModuleInstance).SetResourceInstanceDeposed( 19 absResource.Resource, 20 deposedKey, 21 &states.ResourceInstanceObjectSrc{ 22 Status: states.ObjectTainted, 23 AttrsJSON: []byte(`{"id":"bar"}`), 24 }, 25 mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`), 26 ) 27 28 p := testProvider("test") 29 p.UpgradeResourceStateResponse = &providers.UpgradeResourceStateResponse{ 30 UpgradedState: cty.ObjectVal(map[string]cty.Value{ 31 "id": cty.StringVal("bar"), 32 }), 33 } 34 ctx := &MockEvalContext{ 35 StateState: state.SyncWrapper(), 36 PrevRunStateState: state.DeepCopy().SyncWrapper(), 37 RefreshStateState: state.DeepCopy().SyncWrapper(), 38 ProviderProvider: p, 39 ProviderSchemaSchema: &ProviderSchema{ 40 ResourceTypes: map[string]*configschema.Block{ 41 "test_instance": { 42 Attributes: map[string]*configschema.Attribute{ 43 "id": { 44 Type: cty.String, 45 Computed: true, 46 }, 47 }, 48 }, 49 }, 50 }, 51 ChangesChanges: plans.NewChanges().SyncWrapper(), 52 } 53 54 node := NodePlanDeposedResourceInstanceObject{ 55 NodeAbstractResourceInstance: &NodeAbstractResourceInstance{ 56 Addr: absResource, 57 NodeAbstractResource: NodeAbstractResource{ 58 ResolvedProvider: mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`), 59 }, 60 }, 61 DeposedKey: deposedKey, 62 } 63 err := node.Execute(ctx, walkPlan) 64 if err != nil { 65 t.Fatalf("unexpected error: %s", err) 66 } 67 68 if !p.UpgradeResourceStateCalled { 69 t.Errorf("UpgradeResourceState wasn't called; should've been called to upgrade the previous run's object") 70 } 71 if !p.ReadResourceCalled { 72 t.Errorf("ReadResource wasn't called; should've been called to refresh the deposed object") 73 } 74 75 change := ctx.Changes().GetResourceInstanceChange(absResource, deposedKey) 76 if got, want := change.ChangeSrc.Action, plans.Delete; got != want { 77 t.Fatalf("wrong planned action\ngot: %s\nwant: %s", got, want) 78 } 79 } 80 81 func TestNodeDestroyDeposedResourceInstanceObject_Execute(t *testing.T) { 82 deposedKey := states.NewDeposedKey() 83 state := states.NewState() 84 absResource := mustResourceInstanceAddr("test_instance.foo") 85 state.Module(addrs.RootModuleInstance).SetResourceInstanceDeposed( 86 absResource.Resource, 87 deposedKey, 88 &states.ResourceInstanceObjectSrc{ 89 Status: states.ObjectTainted, 90 AttrsJSON: []byte(`{"id":"bar"}`), 91 }, 92 mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`), 93 ) 94 95 schema := &ProviderSchema{ 96 ResourceTypes: map[string]*configschema.Block{ 97 "test_instance": { 98 Attributes: map[string]*configschema.Attribute{ 99 "id": { 100 Type: cty.String, 101 Computed: true, 102 }, 103 }, 104 }, 105 }, 106 } 107 108 p := testProvider("test") 109 p.GetProviderSchemaResponse = getProviderSchemaResponseFromProviderSchema(schema) 110 111 p.UpgradeResourceStateResponse = &providers.UpgradeResourceStateResponse{ 112 UpgradedState: cty.ObjectVal(map[string]cty.Value{ 113 "id": cty.StringVal("bar"), 114 }), 115 } 116 ctx := &MockEvalContext{ 117 StateState: state.SyncWrapper(), 118 ProviderProvider: p, 119 ProviderSchemaSchema: schema, 120 ChangesChanges: plans.NewChanges().SyncWrapper(), 121 } 122 123 node := NodeDestroyDeposedResourceInstanceObject{ 124 NodeAbstractResourceInstance: &NodeAbstractResourceInstance{ 125 Addr: absResource, 126 NodeAbstractResource: NodeAbstractResource{ 127 ResolvedProvider: mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`), 128 }, 129 }, 130 DeposedKey: deposedKey, 131 } 132 err := node.Execute(ctx, walkApply) 133 134 if err != nil { 135 t.Fatalf("unexpected error: %s", err) 136 } 137 138 if !state.Empty() { 139 t.Fatalf("resources left in state after destroy") 140 } 141 } 142 143 func TestNodeDestroyDeposedResourceInstanceObject_WriteResourceInstanceState(t *testing.T) { 144 state := states.NewState() 145 ctx := new(MockEvalContext) 146 ctx.StateState = state.SyncWrapper() 147 ctx.PathPath = addrs.RootModuleInstance 148 mockProvider := mockProviderWithResourceTypeSchema("aws_instance", &configschema.Block{ 149 Attributes: map[string]*configschema.Attribute{ 150 "id": { 151 Type: cty.String, 152 Optional: true, 153 }, 154 }, 155 }) 156 ctx.ProviderProvider = mockProvider 157 ctx.ProviderSchemaSchema = mockProvider.ProviderSchema() 158 159 obj := &states.ResourceInstanceObject{ 160 Value: cty.ObjectVal(map[string]cty.Value{ 161 "id": cty.StringVal("i-abc123"), 162 }), 163 Status: states.ObjectReady, 164 } 165 node := &NodeDestroyDeposedResourceInstanceObject{ 166 NodeAbstractResourceInstance: &NodeAbstractResourceInstance{ 167 NodeAbstractResource: NodeAbstractResource{ 168 ResolvedProvider: mustProviderConfig(`provider["registry.terraform.io/hashicorp/aws"]`), 169 }, 170 Addr: mustResourceInstanceAddr("aws_instance.foo"), 171 }, 172 DeposedKey: states.NewDeposedKey(), 173 } 174 err := node.writeResourceInstanceState(ctx, obj) 175 if err != nil { 176 t.Fatalf("unexpected error: %s", err.Error()) 177 } 178 179 checkStateString(t, state, ` 180 aws_instance.foo: (1 deposed) 181 ID = <not created> 182 provider = provider["registry.terraform.io/hashicorp/aws"] 183 Deposed ID 1 = i-abc123 184 `) 185 } 186 187 func TestNodeDestroyDeposedResourceInstanceObject_ExecuteMissingState(t *testing.T) { 188 p := simpleMockProvider() 189 ctx := &MockEvalContext{ 190 StateState: states.NewState().SyncWrapper(), 191 ProviderProvider: simpleMockProvider(), 192 ProviderSchemaSchema: p.ProviderSchema(), 193 ChangesChanges: plans.NewChanges().SyncWrapper(), 194 } 195 196 node := NodeDestroyDeposedResourceInstanceObject{ 197 NodeAbstractResourceInstance: &NodeAbstractResourceInstance{ 198 Addr: mustResourceInstanceAddr("test_object.foo"), 199 NodeAbstractResource: NodeAbstractResource{ 200 ResolvedProvider: mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`), 201 }, 202 }, 203 DeposedKey: states.NewDeposedKey(), 204 } 205 err := node.Execute(ctx, walkApply) 206 207 if err == nil { 208 t.Fatal("expected error") 209 } 210 }