github.com/opentofu/opentofu@v1.7.1/internal/tofu/transform_import_state_test.go (about)

     1  // Copyright (c) The OpenTofu Authors
     2  // SPDX-License-Identifier: MPL-2.0
     3  // Copyright (c) 2023 HashiCorp, Inc.
     4  // SPDX-License-Identifier: MPL-2.0
     5  
     6  package tofu
     7  
     8  import (
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/opentofu/opentofu/internal/addrs"
    13  	"github.com/opentofu/opentofu/internal/configs/configschema"
    14  	"github.com/opentofu/opentofu/internal/providers"
    15  	"github.com/opentofu/opentofu/internal/states"
    16  	"github.com/zclconf/go-cty/cty"
    17  )
    18  
    19  func TestGraphNodeImportStateExecute(t *testing.T) {
    20  	state := states.NewState()
    21  	provider := testProvider("aws")
    22  	provider.ImportResourceStateResponse = &providers.ImportResourceStateResponse{
    23  		ImportedResources: []providers.ImportedResource{
    24  			{
    25  				TypeName: "aws_instance",
    26  				State: cty.ObjectVal(map[string]cty.Value{
    27  					"id": cty.StringVal("bar"),
    28  				}),
    29  			},
    30  		},
    31  	}
    32  	provider.ConfigureProvider(providers.ConfigureProviderRequest{})
    33  
    34  	ctx := &MockEvalContext{
    35  		StateState:       state.SyncWrapper(),
    36  		ProviderProvider: provider,
    37  	}
    38  
    39  	// Import a new aws_instance.foo, this time with ID=bar. The original
    40  	// aws_instance.foo object should be removed from state and replaced with
    41  	// the new.
    42  	node := graphNodeImportState{
    43  		Addr: addrs.Resource{
    44  			Mode: addrs.ManagedResourceMode,
    45  			Type: "aws_instance",
    46  			Name: "foo",
    47  		}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
    48  		ID: "bar",
    49  		ResolvedProvider: addrs.AbsProviderConfig{
    50  			Provider: addrs.NewDefaultProvider("aws"),
    51  			Module:   addrs.RootModule,
    52  		},
    53  	}
    54  
    55  	diags := node.Execute(ctx, walkImport)
    56  	if diags.HasErrors() {
    57  		t.Fatalf("Unexpected error: %s", diags.Err())
    58  	}
    59  
    60  	if len(node.states) != 1 {
    61  		t.Fatalf("Wrong result! Expected one imported resource, got %d", len(node.states))
    62  	}
    63  	// Verify the ID for good measure
    64  	id := node.states[0].State.GetAttr("id")
    65  	if !id.RawEquals(cty.StringVal("bar")) {
    66  		t.Fatalf("Wrong result! Expected id \"bar\", got %q", id.AsString())
    67  	}
    68  }
    69  
    70  func TestGraphNodeImportStateSubExecute(t *testing.T) {
    71  	state := states.NewState()
    72  	provider := testProvider("aws")
    73  	provider.ConfigureProvider(providers.ConfigureProviderRequest{})
    74  	ctx := &MockEvalContext{
    75  		StateState:       state.SyncWrapper(),
    76  		ProviderProvider: provider,
    77  		ProviderSchemaSchema: providers.ProviderSchema{
    78  			ResourceTypes: map[string]providers.Schema{
    79  				"aws_instance": {
    80  					Block: &configschema.Block{
    81  						Attributes: map[string]*configschema.Attribute{
    82  							"id": {
    83  								Type:     cty.String,
    84  								Computed: true,
    85  							},
    86  						},
    87  					},
    88  				},
    89  			},
    90  		},
    91  	}
    92  
    93  	importedResource := providers.ImportedResource{
    94  		TypeName: "aws_instance",
    95  		State:    cty.ObjectVal(map[string]cty.Value{"id": cty.StringVal("bar")}),
    96  	}
    97  
    98  	node := graphNodeImportStateSub{
    99  		TargetAddr: addrs.Resource{
   100  			Mode: addrs.ManagedResourceMode,
   101  			Type: "aws_instance",
   102  			Name: "foo",
   103  		}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   104  		State: importedResource,
   105  		ResolvedProvider: addrs.AbsProviderConfig{
   106  			Provider: addrs.NewDefaultProvider("aws"),
   107  			Module:   addrs.RootModule,
   108  		},
   109  	}
   110  	diags := node.Execute(ctx, walkImport)
   111  	if diags.HasErrors() {
   112  		t.Fatalf("Unexpected error: %s", diags.Err())
   113  	}
   114  
   115  	// check for resource in state
   116  	actual := strings.TrimSpace(state.String())
   117  	expected := `aws_instance.foo:
   118    ID = bar
   119    provider = provider["registry.opentofu.org/hashicorp/aws"]`
   120  	if actual != expected {
   121  		t.Fatalf("bad state after import: \n%s", actual)
   122  	}
   123  }
   124  
   125  func TestGraphNodeImportStateSubExecuteNull(t *testing.T) {
   126  	state := states.NewState()
   127  	provider := testProvider("aws")
   128  	provider.ReadResourceFn = func(req providers.ReadResourceRequest) (resp providers.ReadResourceResponse) {
   129  		// return null indicating that the requested resource does not exist
   130  		resp.NewState = cty.NullVal(cty.Object(map[string]cty.Type{
   131  			"id": cty.String,
   132  		}))
   133  		return resp
   134  	}
   135  
   136  	ctx := &MockEvalContext{
   137  		StateState:       state.SyncWrapper(),
   138  		ProviderProvider: provider,
   139  		ProviderSchemaSchema: providers.ProviderSchema{
   140  			ResourceTypes: map[string]providers.Schema{
   141  				"aws_instance": {
   142  					Block: &configschema.Block{
   143  						Attributes: map[string]*configschema.Attribute{
   144  							"id": {
   145  								Type:     cty.String,
   146  								Computed: true,
   147  							},
   148  						},
   149  					},
   150  				},
   151  			},
   152  		},
   153  	}
   154  
   155  	importedResource := providers.ImportedResource{
   156  		TypeName: "aws_instance",
   157  		State:    cty.ObjectVal(map[string]cty.Value{"id": cty.StringVal("bar")}),
   158  	}
   159  
   160  	node := graphNodeImportStateSub{
   161  		TargetAddr: addrs.Resource{
   162  			Mode: addrs.ManagedResourceMode,
   163  			Type: "aws_instance",
   164  			Name: "foo",
   165  		}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   166  		State: importedResource,
   167  		ResolvedProvider: addrs.AbsProviderConfig{
   168  			Provider: addrs.NewDefaultProvider("aws"),
   169  			Module:   addrs.RootModule,
   170  		},
   171  	}
   172  	diags := node.Execute(ctx, walkImport)
   173  	if !diags.HasErrors() {
   174  		t.Fatal("expected error for non-existent resource")
   175  	}
   176  }