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  }