github.com/hashicorp/terraform-plugin-sdk@v1.17.2/helper/resource/state_shim_test.go (about)

     1  package resource
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
     7  	"github.com/hashicorp/terraform-plugin-sdk/internal/addrs"
     8  	"github.com/hashicorp/terraform-plugin-sdk/internal/states"
     9  	"github.com/hashicorp/terraform-plugin-sdk/terraform"
    10  	"github.com/zclconf/go-cty/cty"
    11  )
    12  
    13  // TestStateShim is meant to be a fairly comprehensive test, checking for dependencies, root outputs,
    14  func TestStateShim(t *testing.T) {
    15  	state := states.NewState()
    16  
    17  	rootModule := state.RootModule()
    18  	if rootModule == nil {
    19  		t.Errorf("root module is nil; want valid object")
    20  	}
    21  
    22  	rootModule.SetOutputValue("bar", cty.ListVal([]cty.Value{cty.StringVal("bar"), cty.StringVal("value")}), false)
    23  	rootModule.SetOutputValue("secret", cty.StringVal("secret value"), true)
    24  	rootModule.SetResourceInstanceCurrent(
    25  		addrs.Resource{
    26  			Mode: addrs.ManagedResourceMode,
    27  			Type: "test_thing",
    28  			Name: "foo",
    29  		}.Instance(addrs.NoKey),
    30  		&states.ResourceInstanceObjectSrc{
    31  			Status:        states.ObjectReady,
    32  			AttrsFlat:     map[string]string{"id": "foo", "bazzle": "dazzle"},
    33  			SchemaVersion: 7,
    34  			Dependencies: []addrs.Referenceable{
    35  				addrs.ResourceInstance{
    36  					Resource: addrs.Resource{
    37  						Mode: 'M',
    38  						Type: "test_thing",
    39  						Name: "baz",
    40  					},
    41  				},
    42  			},
    43  		},
    44  		addrs.ProviderConfig{
    45  			Type: "test",
    46  		}.Absolute(addrs.RootModuleInstance),
    47  	)
    48  	rootModule.SetResourceInstanceCurrent(
    49  		addrs.Resource{
    50  			Mode: addrs.ManagedResourceMode,
    51  			Type: "test_thing",
    52  			Name: "baz",
    53  		}.Instance(addrs.NoKey),
    54  		&states.ResourceInstanceObjectSrc{
    55  			Status:       states.ObjectReady,
    56  			AttrsFlat:    map[string]string{"id": "baz", "bazzle": "dazzle"},
    57  			Dependencies: []addrs.Referenceable{},
    58  		},
    59  		addrs.ProviderConfig{
    60  			Type: "test",
    61  		}.Absolute(addrs.RootModuleInstance),
    62  	)
    63  
    64  	childInstance := addrs.RootModuleInstance.Child("child", addrs.NoKey)
    65  	childModule := state.EnsureModule(childInstance)
    66  	childModule.SetResourceInstanceCurrent(
    67  		addrs.Resource{
    68  			Mode: addrs.DataResourceMode,
    69  			Type: "test_data_thing",
    70  			Name: "foo",
    71  		}.Instance(addrs.NoKey),
    72  		&states.ResourceInstanceObjectSrc{
    73  			Status:       states.ObjectReady,
    74  			AttrsJSON:    []byte(`{"id": "bar", "fuzzle":"wuzzle"}`),
    75  			Dependencies: []addrs.Referenceable{},
    76  		},
    77  		addrs.ProviderConfig{
    78  			Type: "test",
    79  		}.Absolute(childInstance),
    80  	)
    81  	childModule.SetResourceInstanceCurrent(
    82  		addrs.Resource{
    83  			Mode: addrs.ManagedResourceMode,
    84  			Type: "test_thing",
    85  			Name: "baz",
    86  		}.Instance(addrs.NoKey),
    87  		&states.ResourceInstanceObjectSrc{
    88  			Status:    states.ObjectReady,
    89  			AttrsJSON: []byte(`{"id": "bar", "fizzle":"wizzle"}`),
    90  			Dependencies: []addrs.Referenceable{
    91  				addrs.ResourceInstance{
    92  					Resource: addrs.Resource{
    93  						Mode: 'D',
    94  						Type: "test_data_thing",
    95  						Name: "foo",
    96  					},
    97  				},
    98  			},
    99  		},
   100  		addrs.ProviderConfig{
   101  			Type: "test",
   102  		}.Absolute(childInstance),
   103  	)
   104  
   105  	childModule.SetResourceInstanceDeposed(
   106  		addrs.Resource{
   107  			Mode: addrs.ManagedResourceMode,
   108  			Type: "test_thing",
   109  			Name: "baz",
   110  		}.Instance(addrs.NoKey),
   111  		"00000001",
   112  		&states.ResourceInstanceObjectSrc{
   113  			Status:    states.ObjectReady,
   114  			AttrsFlat: map[string]string{"id": "old", "fizzle": "wizzle"},
   115  			Dependencies: []addrs.Referenceable{
   116  				addrs.ResourceInstance{
   117  					Resource: addrs.Resource{
   118  						Mode: 'D',
   119  						Type: "test_data_thing",
   120  						Name: "foo",
   121  					},
   122  				},
   123  			},
   124  		},
   125  		addrs.ProviderConfig{
   126  			Type: "test",
   127  		}.Absolute(childInstance),
   128  	)
   129  
   130  	childModule.SetResourceInstanceCurrent(
   131  		addrs.Resource{
   132  			Mode: addrs.ManagedResourceMode,
   133  			Type: "test_thing",
   134  			Name: "lots",
   135  		}.Instance(addrs.IntKey(0)),
   136  		&states.ResourceInstanceObjectSrc{
   137  			Status:       states.ObjectReady,
   138  			AttrsFlat:    map[string]string{"id": "0", "bazzle": "dazzle"},
   139  			Dependencies: []addrs.Referenceable{},
   140  		},
   141  		addrs.ProviderConfig{
   142  			Type: "test",
   143  		}.Absolute(childInstance),
   144  	)
   145  	childModule.SetResourceInstanceCurrent(
   146  		addrs.Resource{
   147  			Mode: addrs.ManagedResourceMode,
   148  			Type: "test_thing",
   149  			Name: "lots",
   150  		}.Instance(addrs.IntKey(1)),
   151  		&states.ResourceInstanceObjectSrc{
   152  			Status:       states.ObjectTainted,
   153  			AttrsFlat:    map[string]string{"id": "1", "bazzle": "dazzle"},
   154  			Dependencies: []addrs.Referenceable{},
   155  		},
   156  		addrs.ProviderConfig{
   157  			Type: "test",
   158  		}.Absolute(childInstance),
   159  	)
   160  
   161  	childModule.SetResourceInstanceCurrent(
   162  		addrs.Resource{
   163  			Mode: addrs.ManagedResourceMode,
   164  			Type: "test_thing",
   165  			Name: "single_count",
   166  		}.Instance(addrs.IntKey(0)),
   167  		&states.ResourceInstanceObjectSrc{
   168  			Status:       states.ObjectReady,
   169  			AttrsJSON:    []byte(`{"id": "single", "bazzle":"dazzle"}`),
   170  			Dependencies: []addrs.Referenceable{},
   171  		},
   172  		addrs.ProviderConfig{
   173  			Type: "test",
   174  		}.Absolute(childInstance),
   175  	)
   176  
   177  	expected := &terraform.State{
   178  		Version: 3,
   179  		Modules: []*terraform.ModuleState{
   180  			{
   181  				Path: []string{"root"},
   182  				Outputs: map[string]*terraform.OutputState{
   183  					"bar": {
   184  						Type:  "list",
   185  						Value: []interface{}{"bar", "value"},
   186  					},
   187  					"secret": {
   188  						Sensitive: true,
   189  						Type:      "string",
   190  						Value:     "secret value",
   191  					},
   192  				},
   193  				Resources: map[string]*terraform.ResourceState{
   194  					"test_thing.baz": {
   195  						Type:     "test_thing",
   196  						Provider: "provider.test",
   197  						Primary: &terraform.InstanceState{
   198  							ID: "baz",
   199  							Attributes: map[string]string{
   200  								"id":     "baz",
   201  								"bazzle": "dazzle",
   202  							},
   203  						},
   204  					},
   205  					"test_thing.foo": {
   206  						Type:     "test_thing",
   207  						Provider: "provider.test",
   208  						Primary: &terraform.InstanceState{
   209  							ID: "foo",
   210  							Attributes: map[string]string{
   211  								"id":     "foo",
   212  								"bazzle": "dazzle",
   213  							},
   214  							Meta: map[string]interface{}{
   215  								"schema_version": 7,
   216  							},
   217  						},
   218  						Dependencies: []string{"test_thing.baz"},
   219  					},
   220  				},
   221  			},
   222  			{
   223  				Path: []string{"root", "child"},
   224  				Resources: map[string]*terraform.ResourceState{
   225  					"test_thing.baz": {
   226  						Type:     "test_thing",
   227  						Provider: "module.child.provider.test",
   228  						Primary: &terraform.InstanceState{
   229  							ID: "bar",
   230  							Attributes: map[string]string{
   231  								"id":     "bar",
   232  								"fizzle": "wizzle",
   233  							},
   234  						},
   235  						Deposed: []*terraform.InstanceState{
   236  							{
   237  								ID: "old",
   238  								Attributes: map[string]string{
   239  									"id":     "old",
   240  									"fizzle": "wizzle",
   241  								},
   242  							},
   243  						},
   244  						Dependencies: []string{"data.test_data_thing.foo"},
   245  					},
   246  					"data.test_data_thing.foo": {
   247  						Type:     "test_data_thing",
   248  						Provider: "module.child.provider.test",
   249  						Primary: &terraform.InstanceState{
   250  							ID: "bar",
   251  							Attributes: map[string]string{
   252  								"id":     "bar",
   253  								"fuzzle": "wuzzle",
   254  							},
   255  						},
   256  					},
   257  					"test_thing.lots.0": {
   258  						Type:     "test_thing",
   259  						Provider: "module.child.provider.test",
   260  						Primary: &terraform.InstanceState{
   261  							ID: "0",
   262  							Attributes: map[string]string{
   263  								"id":     "0",
   264  								"bazzle": "dazzle",
   265  							},
   266  						},
   267  					},
   268  					"test_thing.lots.1": {
   269  						Type:     "test_thing",
   270  						Provider: "module.child.provider.test",
   271  						Primary: &terraform.InstanceState{
   272  							ID: "1",
   273  							Attributes: map[string]string{
   274  								"id":     "1",
   275  								"bazzle": "dazzle",
   276  							},
   277  							Tainted: true,
   278  						},
   279  					},
   280  					"test_thing.single_count": {
   281  						Type:     "test_thing",
   282  						Provider: "module.child.provider.test",
   283  						Primary: &terraform.InstanceState{
   284  							ID: "single",
   285  							Attributes: map[string]string{
   286  								"id":     "single",
   287  								"bazzle": "dazzle",
   288  							},
   289  						},
   290  					},
   291  				},
   292  			},
   293  		},
   294  	}
   295  
   296  	providers := map[string]terraform.ResourceProvider{
   297  		"test": &schema.Provider{
   298  			ResourcesMap: map[string]*schema.Resource{
   299  				"test_thing": {
   300  					Schema: map[string]*schema.Schema{
   301  						"id":     {Type: schema.TypeString, Computed: true},
   302  						"fizzle": {Type: schema.TypeString, Optional: true},
   303  						"bazzle": {Type: schema.TypeString, Optional: true},
   304  					},
   305  				},
   306  			},
   307  			DataSourcesMap: map[string]*schema.Resource{
   308  				"test_data_thing": {
   309  					Schema: map[string]*schema.Schema{
   310  						"id":     {Type: schema.TypeString, Computed: true},
   311  						"fuzzle": {Type: schema.TypeString, Optional: true},
   312  					},
   313  				},
   314  			},
   315  		},
   316  	}
   317  
   318  	shimmed, err := shimNewState(state, providers)
   319  	if err != nil {
   320  		t.Fatal(err)
   321  	}
   322  
   323  	if !expected.Equal(shimmed) {
   324  		t.Fatalf("wrong result state\ngot:\n%s\n\nwant:\n%s", expected, shimmed)
   325  	}
   326  }