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

     1  package terraform
     2  
     3  import (
     4  	"reflect"
     5  	"regexp"
     6  	"sort"
     7  	"strings"
     8  	"sync"
     9  	"testing"
    10  
    11  	"github.com/google/go-cmp/cmp"
    12  	"github.com/zclconf/go-cty/cty"
    13  
    14  	"github.com/hashicorp/terraform-plugin-sdk/internal/addrs"
    15  	"github.com/hashicorp/terraform-plugin-sdk/internal/configs/configschema"
    16  	"github.com/hashicorp/terraform-plugin-sdk/internal/configs/hcl2shim"
    17  	"github.com/hashicorp/terraform-plugin-sdk/internal/providers"
    18  	"github.com/hashicorp/terraform-plugin-sdk/internal/states"
    19  )
    20  
    21  func TestContext2Refresh(t *testing.T) {
    22  	p := testProvider("aws")
    23  	m := testModule(t, "refresh-basic")
    24  
    25  	startingState := MustShimLegacyState(&State{
    26  		Modules: []*ModuleState{
    27  			{
    28  				Path: rootModulePath,
    29  				Resources: map[string]*ResourceState{
    30  					"aws_instance.web": {
    31  						Type: "aws_instance",
    32  						Primary: &InstanceState{
    33  							ID: "foo",
    34  							Attributes: map[string]string{
    35  								"id":  "foo",
    36  								"foo": "bar",
    37  							},
    38  						},
    39  					},
    40  				},
    41  			},
    42  		},
    43  	})
    44  
    45  	ctx := testContext2(t, &ContextOpts{
    46  		Config: m,
    47  		ProviderResolver: providers.ResolverFixed(
    48  			map[string]providers.Factory{
    49  				"aws": testProviderFuncFixed(p),
    50  			},
    51  		),
    52  		State: startingState,
    53  	})
    54  
    55  	schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
    56  	ty := schema.ImpliedType()
    57  	readState, err := hcl2shim.HCL2ValueFromFlatmap(map[string]string{"id": "foo", "foo": "baz"}, ty)
    58  	if err != nil {
    59  		t.Fatal(err)
    60  	}
    61  
    62  	p.ReadResourceFn = nil
    63  	p.ReadResourceResponse = providers.ReadResourceResponse{
    64  		NewState: readState,
    65  	}
    66  
    67  	s, diags := ctx.Refresh()
    68  	if diags.HasErrors() {
    69  		t.Fatal(diags.Err())
    70  	}
    71  
    72  	if !p.ReadResourceCalled {
    73  		t.Fatal("ReadResource should be called")
    74  	}
    75  
    76  	mod := s.RootModule()
    77  	fromState, err := mod.Resources["aws_instance.web"].Instances[addrs.NoKey].Current.Decode(ty)
    78  	if err != nil {
    79  		t.Fatal(err)
    80  	}
    81  
    82  	newState, err := schema.CoerceValue(fromState.Value)
    83  	if err != nil {
    84  		t.Fatal(err)
    85  	}
    86  
    87  	if !cmp.Equal(readState, newState, valueComparer) {
    88  		t.Fatal(cmp.Diff(readState, newState, valueComparer, equateEmpty))
    89  	}
    90  }
    91  
    92  func TestContext2Refresh_dynamicAttr(t *testing.T) {
    93  	m := testModule(t, "refresh-dynamic")
    94  
    95  	startingState := states.BuildState(func(ss *states.SyncState) {
    96  		ss.SetResourceInstanceCurrent(
    97  			addrs.Resource{
    98  				Mode: addrs.ManagedResourceMode,
    99  				Type: "test_instance",
   100  				Name: "foo",
   101  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
   102  			&states.ResourceInstanceObjectSrc{
   103  				Status:    states.ObjectReady,
   104  				AttrsJSON: []byte(`{"dynamic":{"type":"string","value":"hello"}}`),
   105  			},
   106  			addrs.ProviderConfig{
   107  				Type: "test",
   108  			}.Absolute(addrs.RootModuleInstance),
   109  		)
   110  	})
   111  
   112  	readStateVal := cty.ObjectVal(map[string]cty.Value{
   113  		"dynamic": cty.EmptyTupleVal,
   114  	})
   115  
   116  	p := testProvider("test")
   117  	p.GetSchemaReturn = &ProviderSchema{
   118  		ResourceTypes: map[string]*configschema.Block{
   119  			"test_instance": {
   120  				Attributes: map[string]*configschema.Attribute{
   121  					"dynamic": {Type: cty.DynamicPseudoType, Optional: true},
   122  				},
   123  			},
   124  		},
   125  	}
   126  	p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse {
   127  		return providers.ReadResourceResponse{
   128  			NewState: readStateVal,
   129  		}
   130  	}
   131  
   132  	ctx := testContext2(t, &ContextOpts{
   133  		Config: m,
   134  		ProviderResolver: providers.ResolverFixed(
   135  			map[string]providers.Factory{
   136  				"test": testProviderFuncFixed(p),
   137  			},
   138  		),
   139  		State: startingState,
   140  	})
   141  
   142  	schema := p.GetSchemaReturn.ResourceTypes["test_instance"]
   143  	ty := schema.ImpliedType()
   144  
   145  	s, diags := ctx.Refresh()
   146  	if diags.HasErrors() {
   147  		t.Fatal(diags.Err())
   148  	}
   149  
   150  	if !p.ReadResourceCalled {
   151  		t.Fatal("ReadResource should be called")
   152  	}
   153  
   154  	mod := s.RootModule()
   155  	newState, err := mod.Resources["test_instance.foo"].Instances[addrs.NoKey].Current.Decode(ty)
   156  	if err != nil {
   157  		t.Fatal(err)
   158  	}
   159  
   160  	if !cmp.Equal(readStateVal, newState.Value, valueComparer) {
   161  		t.Error(cmp.Diff(newState.Value, readStateVal, valueComparer, equateEmpty))
   162  	}
   163  }
   164  
   165  func TestContext2Refresh_dataComputedModuleVar(t *testing.T) {
   166  	p := testProvider("aws")
   167  	m := testModule(t, "refresh-data-module-var")
   168  	ctx := testContext2(t, &ContextOpts{
   169  		Config: m,
   170  		ProviderResolver: providers.ResolverFixed(
   171  			map[string]providers.Factory{
   172  				"aws": testProviderFuncFixed(p),
   173  			},
   174  		),
   175  	})
   176  
   177  	p.ReadResourceFn = nil
   178  	p.ReadResourceResponse = providers.ReadResourceResponse{
   179  		NewState: cty.ObjectVal(map[string]cty.Value{
   180  			"id": cty.StringVal("foo"),
   181  		}),
   182  	}
   183  
   184  	p.GetSchemaReturn = &ProviderSchema{
   185  		Provider: &configschema.Block{},
   186  		ResourceTypes: map[string]*configschema.Block{
   187  			"aws_instance": {
   188  				Attributes: map[string]*configschema.Attribute{
   189  					"foo": {
   190  						Type:     cty.String,
   191  						Optional: true,
   192  					},
   193  					"id": {
   194  						Type:     cty.String,
   195  						Computed: true,
   196  					},
   197  				},
   198  			},
   199  		},
   200  		DataSources: map[string]*configschema.Block{
   201  			"aws_data_source": {
   202  				Attributes: map[string]*configschema.Attribute{
   203  					"id": {
   204  						Type:     cty.String,
   205  						Optional: true,
   206  					},
   207  				},
   208  			},
   209  		},
   210  	}
   211  
   212  	s, diags := ctx.Refresh()
   213  	if diags.HasErrors() {
   214  		t.Fatalf("refresh errors: %s", diags.Err())
   215  	}
   216  
   217  	checkStateString(t, s, `
   218  <no state>
   219  `)
   220  }
   221  
   222  func TestContext2Refresh_targeted(t *testing.T) {
   223  	p := testProvider("aws")
   224  	p.GetSchemaReturn = &ProviderSchema{
   225  		Provider: &configschema.Block{},
   226  		ResourceTypes: map[string]*configschema.Block{
   227  			"aws_elb": {
   228  				Attributes: map[string]*configschema.Attribute{
   229  					"instances": {
   230  						Type:     cty.Set(cty.String),
   231  						Optional: true,
   232  					},
   233  				},
   234  			},
   235  			"aws_instance": {
   236  				Attributes: map[string]*configschema.Attribute{
   237  					"id": {
   238  						Type:     cty.String,
   239  						Computed: true,
   240  					},
   241  					"vpc_id": {
   242  						Type:     cty.String,
   243  						Optional: true,
   244  					},
   245  				},
   246  			},
   247  			"aws_vpc": {
   248  				Attributes: map[string]*configschema.Attribute{
   249  					"id": {
   250  						Type:     cty.String,
   251  						Computed: true,
   252  					},
   253  				},
   254  			},
   255  		},
   256  	}
   257  
   258  	m := testModule(t, "refresh-targeted")
   259  	ctx := testContext2(t, &ContextOpts{
   260  		Config: m,
   261  		ProviderResolver: providers.ResolverFixed(
   262  			map[string]providers.Factory{
   263  				"aws": testProviderFuncFixed(p),
   264  			},
   265  		),
   266  		State: MustShimLegacyState(&State{
   267  			Modules: []*ModuleState{
   268  				{
   269  					Path: rootModulePath,
   270  					Resources: map[string]*ResourceState{
   271  						"aws_vpc.metoo":      resourceState("aws_vpc", "vpc-abc123"),
   272  						"aws_instance.notme": resourceState("aws_instance", "i-bcd345"),
   273  						"aws_instance.me":    resourceState("aws_instance", "i-abc123"),
   274  						"aws_elb.meneither":  resourceState("aws_elb", "lb-abc123"),
   275  					},
   276  				},
   277  			},
   278  		}),
   279  		Targets: []addrs.Targetable{
   280  			addrs.RootModuleInstance.Resource(
   281  				addrs.ManagedResourceMode, "aws_instance", "me",
   282  			),
   283  		},
   284  	})
   285  
   286  	refreshedResources := make([]string, 0, 2)
   287  	p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse {
   288  		refreshedResources = append(refreshedResources, req.PriorState.GetAttr("id").AsString())
   289  		return providers.ReadResourceResponse{
   290  			NewState: req.PriorState,
   291  		}
   292  	}
   293  
   294  	_, diags := ctx.Refresh()
   295  	if diags.HasErrors() {
   296  		t.Fatalf("refresh errors: %s", diags.Err())
   297  	}
   298  
   299  	expected := []string{"vpc-abc123", "i-abc123"}
   300  	if !reflect.DeepEqual(refreshedResources, expected) {
   301  		t.Fatalf("expected: %#v, got: %#v", expected, refreshedResources)
   302  	}
   303  }
   304  
   305  func TestContext2Refresh_targetedCount(t *testing.T) {
   306  	p := testProvider("aws")
   307  	p.GetSchemaReturn = &ProviderSchema{
   308  		Provider: &configschema.Block{},
   309  		ResourceTypes: map[string]*configschema.Block{
   310  			"aws_elb": {
   311  				Attributes: map[string]*configschema.Attribute{
   312  					"instances": {
   313  						Type:     cty.Set(cty.String),
   314  						Optional: true,
   315  					},
   316  				},
   317  			},
   318  			"aws_instance": {
   319  				Attributes: map[string]*configschema.Attribute{
   320  					"id": {
   321  						Type:     cty.String,
   322  						Computed: true,
   323  					},
   324  					"vpc_id": {
   325  						Type:     cty.String,
   326  						Optional: true,
   327  					},
   328  				},
   329  			},
   330  			"aws_vpc": {
   331  				Attributes: map[string]*configschema.Attribute{
   332  					"id": {
   333  						Type:     cty.String,
   334  						Computed: true,
   335  					},
   336  				},
   337  			},
   338  		},
   339  	}
   340  
   341  	m := testModule(t, "refresh-targeted-count")
   342  	ctx := testContext2(t, &ContextOpts{
   343  		Config: m,
   344  		ProviderResolver: providers.ResolverFixed(
   345  			map[string]providers.Factory{
   346  				"aws": testProviderFuncFixed(p),
   347  			},
   348  		),
   349  		State: MustShimLegacyState(&State{
   350  			Modules: []*ModuleState{
   351  				{
   352  					Path: rootModulePath,
   353  					Resources: map[string]*ResourceState{
   354  						"aws_vpc.metoo":      resourceState("aws_vpc", "vpc-abc123"),
   355  						"aws_instance.notme": resourceState("aws_instance", "i-bcd345"),
   356  						"aws_instance.me.0":  resourceState("aws_instance", "i-abc123"),
   357  						"aws_instance.me.1":  resourceState("aws_instance", "i-cde567"),
   358  						"aws_instance.me.2":  resourceState("aws_instance", "i-cde789"),
   359  						"aws_elb.meneither":  resourceState("aws_elb", "lb-abc123"),
   360  					},
   361  				},
   362  			},
   363  		}),
   364  		Targets: []addrs.Targetable{
   365  			addrs.RootModuleInstance.Resource(
   366  				addrs.ManagedResourceMode, "aws_instance", "me",
   367  			),
   368  		},
   369  	})
   370  
   371  	refreshedResources := make([]string, 0, 2)
   372  	p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse {
   373  		refreshedResources = append(refreshedResources, req.PriorState.GetAttr("id").AsString())
   374  		return providers.ReadResourceResponse{
   375  			NewState: req.PriorState,
   376  		}
   377  	}
   378  
   379  	_, diags := ctx.Refresh()
   380  	if diags.HasErrors() {
   381  		t.Fatalf("refresh errors: %s", diags.Err())
   382  	}
   383  
   384  	// Target didn't specify index, so we should get all our instances
   385  	expected := []string{
   386  		"vpc-abc123",
   387  		"i-abc123",
   388  		"i-cde567",
   389  		"i-cde789",
   390  	}
   391  	sort.Strings(expected)
   392  	sort.Strings(refreshedResources)
   393  	if !reflect.DeepEqual(refreshedResources, expected) {
   394  		t.Fatalf("wrong result\ngot:  %#v\nwant: %#v", refreshedResources, expected)
   395  	}
   396  }
   397  
   398  func TestContext2Refresh_targetedCountIndex(t *testing.T) {
   399  	p := testProvider("aws")
   400  	p.GetSchemaReturn = &ProviderSchema{
   401  		Provider: &configschema.Block{},
   402  		ResourceTypes: map[string]*configschema.Block{
   403  			"aws_elb": {
   404  				Attributes: map[string]*configschema.Attribute{
   405  					"instances": {
   406  						Type:     cty.Set(cty.String),
   407  						Optional: true,
   408  					},
   409  				},
   410  			},
   411  			"aws_instance": {
   412  				Attributes: map[string]*configschema.Attribute{
   413  					"id": {
   414  						Type:     cty.String,
   415  						Computed: true,
   416  					},
   417  					"vpc_id": {
   418  						Type:     cty.String,
   419  						Optional: true,
   420  					},
   421  				},
   422  			},
   423  			"aws_vpc": {
   424  				Attributes: map[string]*configschema.Attribute{
   425  					"id": {
   426  						Type:     cty.String,
   427  						Computed: true,
   428  					},
   429  				},
   430  			},
   431  		},
   432  	}
   433  
   434  	m := testModule(t, "refresh-targeted-count")
   435  	ctx := testContext2(t, &ContextOpts{
   436  		Config: m,
   437  		ProviderResolver: providers.ResolverFixed(
   438  			map[string]providers.Factory{
   439  				"aws": testProviderFuncFixed(p),
   440  			},
   441  		),
   442  		State: MustShimLegacyState(&State{
   443  			Modules: []*ModuleState{
   444  				{
   445  					Path: rootModulePath,
   446  					Resources: map[string]*ResourceState{
   447  						"aws_vpc.metoo":      resourceState("aws_vpc", "vpc-abc123"),
   448  						"aws_instance.notme": resourceState("aws_instance", "i-bcd345"),
   449  						"aws_instance.me.0":  resourceState("aws_instance", "i-abc123"),
   450  						"aws_instance.me.1":  resourceState("aws_instance", "i-cde567"),
   451  						"aws_instance.me.2":  resourceState("aws_instance", "i-cde789"),
   452  						"aws_elb.meneither":  resourceState("aws_elb", "lb-abc123"),
   453  					},
   454  				},
   455  			},
   456  		}),
   457  		Targets: []addrs.Targetable{
   458  			addrs.RootModuleInstance.ResourceInstance(
   459  				addrs.ManagedResourceMode, "aws_instance", "me", addrs.IntKey(0),
   460  			),
   461  		},
   462  	})
   463  
   464  	refreshedResources := make([]string, 0, 2)
   465  	p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse {
   466  		refreshedResources = append(refreshedResources, req.PriorState.GetAttr("id").AsString())
   467  		return providers.ReadResourceResponse{
   468  			NewState: req.PriorState,
   469  		}
   470  	}
   471  
   472  	_, diags := ctx.Refresh()
   473  	if diags.HasErrors() {
   474  		t.Fatalf("refresh errors: %s", diags.Err())
   475  	}
   476  
   477  	expected := []string{"vpc-abc123", "i-abc123"}
   478  	if !reflect.DeepEqual(refreshedResources, expected) {
   479  		t.Fatalf("wrong result\ngot:  %#v\nwant: %#v", refreshedResources, expected)
   480  	}
   481  }
   482  
   483  func TestContext2Refresh_moduleComputedVar(t *testing.T) {
   484  	p := testProvider("aws")
   485  	p.GetSchemaReturn = &ProviderSchema{
   486  		Provider: &configschema.Block{},
   487  		ResourceTypes: map[string]*configschema.Block{
   488  			"aws_instance": {
   489  				Attributes: map[string]*configschema.Attribute{
   490  					"id": {
   491  						Type:     cty.String,
   492  						Computed: true,
   493  					},
   494  					"value": {
   495  						Type:     cty.String,
   496  						Optional: true,
   497  					},
   498  				},
   499  			},
   500  		},
   501  	}
   502  
   503  	m := testModule(t, "refresh-module-computed-var")
   504  	ctx := testContext2(t, &ContextOpts{
   505  		Config: m,
   506  		ProviderResolver: providers.ResolverFixed(
   507  			map[string]providers.Factory{
   508  				"aws": testProviderFuncFixed(p),
   509  			},
   510  		),
   511  	})
   512  
   513  	// This was failing (see GH-2188) at some point, so this test just
   514  	// verifies that the failure goes away.
   515  	if _, diags := ctx.Refresh(); diags.HasErrors() {
   516  		t.Fatalf("refresh errs: %s", diags.Err())
   517  	}
   518  }
   519  
   520  func TestContext2Refresh_delete(t *testing.T) {
   521  	p := testProvider("aws")
   522  	m := testModule(t, "refresh-basic")
   523  	ctx := testContext2(t, &ContextOpts{
   524  		Config: m,
   525  		ProviderResolver: providers.ResolverFixed(
   526  			map[string]providers.Factory{
   527  				"aws": testProviderFuncFixed(p),
   528  			},
   529  		),
   530  		State: MustShimLegacyState(&State{
   531  			Modules: []*ModuleState{
   532  				{
   533  					Path: rootModulePath,
   534  					Resources: map[string]*ResourceState{
   535  						"aws_instance.web": {
   536  							Type: "aws_instance",
   537  							Primary: &InstanceState{
   538  								ID: "foo",
   539  							},
   540  						},
   541  					},
   542  				},
   543  			},
   544  		}),
   545  	})
   546  
   547  	p.ReadResourceFn = nil
   548  	p.ReadResourceResponse = providers.ReadResourceResponse{
   549  		NewState: cty.NullVal(p.GetSchemaReturn.ResourceTypes["aws_instance"].ImpliedType()),
   550  	}
   551  
   552  	s, diags := ctx.Refresh()
   553  	if diags.HasErrors() {
   554  		t.Fatalf("refresh errors: %s", diags.Err())
   555  	}
   556  
   557  	mod := s.RootModule()
   558  	if len(mod.Resources) > 0 {
   559  		t.Fatal("resources should be empty")
   560  	}
   561  }
   562  
   563  func TestContext2Refresh_ignoreUncreated(t *testing.T) {
   564  	p := testProvider("aws")
   565  	m := testModule(t, "refresh-basic")
   566  	ctx := testContext2(t, &ContextOpts{
   567  		Config: m,
   568  		ProviderResolver: providers.ResolverFixed(
   569  			map[string]providers.Factory{
   570  				"aws": testProviderFuncFixed(p),
   571  			},
   572  		),
   573  		State: nil,
   574  	})
   575  
   576  	p.ReadResourceFn = nil
   577  	p.ReadResourceResponse = providers.ReadResourceResponse{
   578  		NewState: cty.ObjectVal(map[string]cty.Value{
   579  			"id": cty.StringVal("foo"),
   580  		}),
   581  	}
   582  
   583  	_, diags := ctx.Refresh()
   584  	if diags.HasErrors() {
   585  		t.Fatalf("refresh errors: %s", diags.Err())
   586  	}
   587  	if p.ReadResourceCalled {
   588  		t.Fatal("refresh should not be called")
   589  	}
   590  }
   591  
   592  func TestContext2Refresh_hook(t *testing.T) {
   593  	h := new(MockHook)
   594  	p := testProvider("aws")
   595  	m := testModule(t, "refresh-basic")
   596  	ctx := testContext2(t, &ContextOpts{
   597  		Config: m,
   598  		Hooks:  []Hook{h},
   599  		ProviderResolver: providers.ResolverFixed(
   600  			map[string]providers.Factory{
   601  				"aws": testProviderFuncFixed(p),
   602  			},
   603  		),
   604  		State: MustShimLegacyState(&State{
   605  			Modules: []*ModuleState{
   606  				{
   607  					Path: rootModulePath,
   608  					Resources: map[string]*ResourceState{
   609  						"aws_instance.web": {
   610  							Type: "aws_instance",
   611  							Primary: &InstanceState{
   612  								ID: "foo",
   613  							},
   614  						},
   615  					},
   616  				},
   617  			},
   618  		}),
   619  	})
   620  
   621  	if _, diags := ctx.Refresh(); diags.HasErrors() {
   622  		t.Fatalf("refresh errs: %s", diags.Err())
   623  	}
   624  	if !h.PreRefreshCalled {
   625  		t.Fatal("should be called")
   626  	}
   627  	if !h.PostRefreshCalled {
   628  		t.Fatal("should be called")
   629  	}
   630  }
   631  
   632  func TestContext2Refresh_modules(t *testing.T) {
   633  	p := testProvider("aws")
   634  	m := testModule(t, "refresh-modules")
   635  	state := MustShimLegacyState(&State{
   636  		Modules: []*ModuleState{
   637  			{
   638  				Path: rootModulePath,
   639  				Resources: map[string]*ResourceState{
   640  					"aws_instance.web": {
   641  						Type: "aws_instance",
   642  						Primary: &InstanceState{
   643  							ID:      "bar",
   644  							Tainted: true,
   645  						},
   646  					},
   647  				},
   648  			},
   649  
   650  			{
   651  				Path: []string{"root", "child"},
   652  				Resources: map[string]*ResourceState{
   653  					"aws_instance.web": {
   654  						Type: "aws_instance",
   655  						Primary: &InstanceState{
   656  							ID: "baz",
   657  						},
   658  					},
   659  				},
   660  			},
   661  		},
   662  	})
   663  	ctx := testContext2(t, &ContextOpts{
   664  		Config: m,
   665  		ProviderResolver: providers.ResolverFixed(
   666  			map[string]providers.Factory{
   667  				"aws": testProviderFuncFixed(p),
   668  			},
   669  		),
   670  		State: state,
   671  	})
   672  
   673  	p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse {
   674  		if !req.PriorState.GetAttr("id").RawEquals(cty.StringVal("baz")) {
   675  			return providers.ReadResourceResponse{
   676  				NewState: req.PriorState,
   677  			}
   678  		}
   679  
   680  		new, _ := cty.Transform(req.PriorState, func(path cty.Path, v cty.Value) (cty.Value, error) {
   681  			if len(path) == 1 && path[0].(cty.GetAttrStep).Name == "id" {
   682  				return cty.StringVal("new"), nil
   683  			}
   684  			return v, nil
   685  		})
   686  		return providers.ReadResourceResponse{
   687  			NewState: new,
   688  		}
   689  	}
   690  
   691  	s, diags := ctx.Refresh()
   692  	if diags.HasErrors() {
   693  		t.Fatalf("refresh errors: %s", diags.Err())
   694  	}
   695  
   696  	actual := strings.TrimSpace(s.String())
   697  	expected := strings.TrimSpace(testContextRefreshModuleStr)
   698  	if actual != expected {
   699  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
   700  	}
   701  }
   702  
   703  func TestContext2Refresh_moduleInputComputedOutput(t *testing.T) {
   704  	m := testModule(t, "refresh-module-input-computed-output")
   705  	p := testProvider("aws")
   706  	p.DiffFn = testDiffFn
   707  	p.GetSchemaReturn = &ProviderSchema{
   708  		Provider: &configschema.Block{},
   709  		ResourceTypes: map[string]*configschema.Block{
   710  			"aws_instance": {
   711  				Attributes: map[string]*configschema.Attribute{
   712  					"foo": {
   713  						Type:     cty.String,
   714  						Optional: true,
   715  					},
   716  					"compute": {
   717  						Type:     cty.String,
   718  						Optional: true,
   719  					},
   720  				},
   721  			},
   722  		},
   723  	}
   724  
   725  	ctx := testContext2(t, &ContextOpts{
   726  		Config: m,
   727  		ProviderResolver: providers.ResolverFixed(
   728  			map[string]providers.Factory{
   729  				"aws": testProviderFuncFixed(p),
   730  			},
   731  		),
   732  	})
   733  
   734  	if _, diags := ctx.Refresh(); diags.HasErrors() {
   735  		t.Fatalf("refresh errs: %s", diags.Err())
   736  	}
   737  }
   738  
   739  func TestContext2Refresh_moduleVarModule(t *testing.T) {
   740  	m := testModule(t, "refresh-module-var-module")
   741  	p := testProvider("aws")
   742  	p.DiffFn = testDiffFn
   743  	ctx := testContext2(t, &ContextOpts{
   744  		Config: m,
   745  		ProviderResolver: providers.ResolverFixed(
   746  			map[string]providers.Factory{
   747  				"aws": testProviderFuncFixed(p),
   748  			},
   749  		),
   750  	})
   751  
   752  	if _, diags := ctx.Refresh(); diags.HasErrors() {
   753  		t.Fatalf("refresh errs: %s", diags.Err())
   754  	}
   755  }
   756  
   757  // GH-70
   758  func TestContext2Refresh_noState(t *testing.T) {
   759  	p := testProvider("aws")
   760  	m := testModule(t, "refresh-no-state")
   761  	ctx := testContext2(t, &ContextOpts{
   762  		Config: m,
   763  		ProviderResolver: providers.ResolverFixed(
   764  			map[string]providers.Factory{
   765  				"aws": testProviderFuncFixed(p),
   766  			},
   767  		),
   768  	})
   769  
   770  	p.ReadResourceFn = nil
   771  	p.ReadResourceResponse = providers.ReadResourceResponse{
   772  		NewState: cty.ObjectVal(map[string]cty.Value{
   773  			"id": cty.StringVal("foo"),
   774  		}),
   775  	}
   776  
   777  	if _, diags := ctx.Refresh(); diags.HasErrors() {
   778  		t.Fatalf("refresh errs: %s", diags.Err())
   779  	}
   780  }
   781  
   782  func TestContext2Refresh_output(t *testing.T) {
   783  	p := testProvider("aws")
   784  	p.GetSchemaReturn = &ProviderSchema{
   785  		Provider: &configschema.Block{},
   786  		ResourceTypes: map[string]*configschema.Block{
   787  			"aws_instance": {
   788  				Attributes: map[string]*configschema.Attribute{
   789  					"id": {
   790  						Type:     cty.String,
   791  						Computed: true,
   792  					},
   793  					"foo": {
   794  						Type:     cty.String,
   795  						Computed: true,
   796  					},
   797  				},
   798  			},
   799  		},
   800  	}
   801  
   802  	m := testModule(t, "refresh-output")
   803  	ctx := testContext2(t, &ContextOpts{
   804  		Config: m,
   805  		ProviderResolver: providers.ResolverFixed(
   806  			map[string]providers.Factory{
   807  				"aws": testProviderFuncFixed(p),
   808  			},
   809  		),
   810  		State: MustShimLegacyState(&State{
   811  			Modules: []*ModuleState{
   812  				{
   813  					Path: rootModulePath,
   814  					Resources: map[string]*ResourceState{
   815  						"aws_instance.web": {
   816  							Type: "aws_instance",
   817  							Primary: &InstanceState{
   818  								ID: "foo",
   819  								Attributes: map[string]string{
   820  									"id":  "foo",
   821  									"foo": "bar",
   822  								},
   823  							},
   824  						},
   825  					},
   826  
   827  					Outputs: map[string]*OutputState{
   828  						"foo": {
   829  							Type:      "string",
   830  							Sensitive: false,
   831  							Value:     "foo",
   832  						},
   833  					},
   834  				},
   835  			},
   836  		}),
   837  	})
   838  
   839  	s, diags := ctx.Refresh()
   840  	if diags.HasErrors() {
   841  		t.Fatalf("refresh errors: %s", diags.Err())
   842  	}
   843  
   844  	actual := strings.TrimSpace(s.String())
   845  	expected := strings.TrimSpace(testContextRefreshOutputStr)
   846  	if actual != expected {
   847  		t.Fatalf("wrong result\n\ngot:\n%q\n\nwant:\n%q", actual, expected)
   848  	}
   849  }
   850  
   851  func TestContext2Refresh_outputPartial(t *testing.T) {
   852  	p := testProvider("aws")
   853  	m := testModule(t, "refresh-output-partial")
   854  
   855  	// Refresh creates a partial plan for any instances that don't have
   856  	// remote objects yet, to get stub values for interpolation. Therefore
   857  	// we need to make DiffFn available to let that complete.
   858  	p.DiffFn = testDiffFn
   859  
   860  	p.GetSchemaReturn = &ProviderSchema{
   861  		Provider: &configschema.Block{},
   862  		ResourceTypes: map[string]*configschema.Block{
   863  			"aws_instance": {
   864  				Attributes: map[string]*configschema.Attribute{
   865  					"foo": {
   866  						Type:     cty.String,
   867  						Computed: true,
   868  					},
   869  				},
   870  			},
   871  		},
   872  	}
   873  
   874  	p.ReadResourceFn = nil
   875  	p.ReadResourceResponse = providers.ReadResourceResponse{
   876  		NewState: cty.NullVal(p.GetSchemaReturn.ResourceTypes["aws_instance"].ImpliedType()),
   877  	}
   878  
   879  	ctx := testContext2(t, &ContextOpts{
   880  		Config: m,
   881  		ProviderResolver: providers.ResolverFixed(
   882  			map[string]providers.Factory{
   883  				"aws": testProviderFuncFixed(p),
   884  			},
   885  		),
   886  		State: MustShimLegacyState(&State{
   887  			Modules: []*ModuleState{
   888  				{
   889  					Path: rootModulePath,
   890  					Resources: map[string]*ResourceState{
   891  						"aws_instance.foo": {
   892  							Type: "aws_instance",
   893  							Primary: &InstanceState{
   894  								ID: "foo",
   895  							},
   896  						},
   897  					},
   898  					Outputs: map[string]*OutputState{},
   899  				},
   900  			},
   901  		}),
   902  	})
   903  
   904  	s, diags := ctx.Refresh()
   905  	if diags.HasErrors() {
   906  		t.Fatalf("refresh errors: %s", diags.Err())
   907  	}
   908  
   909  	actual := strings.TrimSpace(s.String())
   910  	expected := strings.TrimSpace(testContextRefreshOutputPartialStr)
   911  	if actual != expected {
   912  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
   913  	}
   914  }
   915  
   916  func TestContext2Refresh_stateBasic(t *testing.T) {
   917  	p := testProvider("aws")
   918  	m := testModule(t, "refresh-basic")
   919  	state := MustShimLegacyState(&State{
   920  		Modules: []*ModuleState{
   921  			{
   922  				Path: rootModulePath,
   923  				Resources: map[string]*ResourceState{
   924  					"aws_instance.web": {
   925  						Type: "aws_instance",
   926  						Primary: &InstanceState{
   927  							ID: "bar",
   928  						},
   929  					},
   930  				},
   931  			},
   932  		},
   933  	})
   934  	ctx := testContext2(t, &ContextOpts{
   935  		Config: m,
   936  		ProviderResolver: providers.ResolverFixed(
   937  			map[string]providers.Factory{
   938  				"aws": testProviderFuncFixed(p),
   939  			},
   940  		),
   941  		State: state,
   942  	})
   943  
   944  	schema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
   945  	ty := schema.ImpliedType()
   946  
   947  	readStateVal, err := schema.CoerceValue(cty.ObjectVal(map[string]cty.Value{
   948  		"id": cty.StringVal("foo"),
   949  	}))
   950  	if err != nil {
   951  		t.Fatal(err)
   952  	}
   953  
   954  	p.ReadResourceFn = nil
   955  	p.ReadResourceResponse = providers.ReadResourceResponse{
   956  		NewState: readStateVal,
   957  	}
   958  
   959  	s, diags := ctx.Refresh()
   960  	if diags.HasErrors() {
   961  		t.Fatalf("refresh errors: %s", diags.Err())
   962  	}
   963  
   964  	if !p.ReadResourceCalled {
   965  		t.Fatal("read resource should be called")
   966  	}
   967  
   968  	mod := s.RootModule()
   969  	newState, err := mod.Resources["aws_instance.web"].Instances[addrs.NoKey].Current.Decode(ty)
   970  	if err != nil {
   971  		t.Fatal(err)
   972  	}
   973  
   974  	if !cmp.Equal(readStateVal, newState.Value, valueComparer, equateEmpty) {
   975  		t.Fatal(cmp.Diff(readStateVal, newState.Value, valueComparer, equateEmpty))
   976  	}
   977  }
   978  
   979  func TestContext2Refresh_dataCount(t *testing.T) {
   980  	p := testProvider("test")
   981  	m := testModule(t, "refresh-data-count")
   982  
   983  	// This test is verifying that a data resource count can refer to a
   984  	// resource attribute that can't be known yet during refresh (because
   985  	// the resource in question isn't in the state at all). In that case,
   986  	// we skip the data resource during refresh and process it during the
   987  	// subsequent plan step instead.
   988  	//
   989  	// Normally it's an error for "count" to be computed, but during the
   990  	// refresh step we allow it because we _expect_ to be working with an
   991  	// incomplete picture of the world sometimes, particularly when we're
   992  	// creating object for the first time against an empty state.
   993  	//
   994  	// For more information, see:
   995  	//    https://github.com/hashicorp/terraform-plugin-sdk/issues/21047
   996  
   997  	p.GetSchemaReturn = &ProviderSchema{
   998  		ResourceTypes: map[string]*configschema.Block{
   999  			"test": {
  1000  				Attributes: map[string]*configschema.Attribute{
  1001  					"things": {Type: cty.List(cty.String), Optional: true},
  1002  				},
  1003  			},
  1004  		},
  1005  		DataSources: map[string]*configschema.Block{
  1006  			"test": {},
  1007  		},
  1008  	}
  1009  
  1010  	ctx := testContext2(t, &ContextOpts{
  1011  		ProviderResolver: providers.ResolverFixed(
  1012  			map[string]providers.Factory{
  1013  				"test": testProviderFuncFixed(p),
  1014  			},
  1015  		),
  1016  		Config: m,
  1017  	})
  1018  
  1019  	s, diags := ctx.Refresh()
  1020  	if p.ReadResourceCalled {
  1021  		// The managed resource doesn't exist in the state yet, so there's
  1022  		// nothing to refresh.
  1023  		t.Errorf("ReadResource was called, but should not have been")
  1024  	}
  1025  	if p.ReadDataSourceCalled {
  1026  		// The data resource should've been skipped because its count cannot
  1027  		// be determined yet.
  1028  		t.Errorf("ReadDataSource was called, but should not have been")
  1029  	}
  1030  
  1031  	if diags.HasErrors() {
  1032  		t.Fatalf("refresh errors: %s", diags.Err())
  1033  	}
  1034  
  1035  	checkStateString(t, s, `<no state>`)
  1036  }
  1037  
  1038  func TestContext2Refresh_dataOrphan(t *testing.T) {
  1039  	p := testProvider("null")
  1040  	state := MustShimLegacyState(&State{
  1041  		Modules: []*ModuleState{
  1042  			{
  1043  				Path: rootModulePath,
  1044  				Resources: map[string]*ResourceState{
  1045  					"data.null_data_source.bar": {
  1046  						Type: "null_data_source",
  1047  						Primary: &InstanceState{
  1048  							ID: "foo",
  1049  						},
  1050  						Provider: "provider.null",
  1051  					},
  1052  				},
  1053  			},
  1054  		},
  1055  	})
  1056  	ctx := testContext2(t, &ContextOpts{
  1057  		ProviderResolver: providers.ResolverFixed(
  1058  			map[string]providers.Factory{
  1059  				"null": testProviderFuncFixed(p),
  1060  			},
  1061  		),
  1062  		State: state,
  1063  	})
  1064  
  1065  	s, diags := ctx.Refresh()
  1066  	if diags.HasErrors() {
  1067  		t.Fatalf("refresh errors: %s", diags.Err())
  1068  	}
  1069  
  1070  	checkStateString(t, s, `<no state>`)
  1071  }
  1072  
  1073  func TestContext2Refresh_dataState(t *testing.T) {
  1074  	m := testModule(t, "refresh-data-resource-basic")
  1075  
  1076  	state := MustShimLegacyState(&State{
  1077  		Modules: []*ModuleState{
  1078  			{
  1079  				Path: rootModulePath,
  1080  				// Intentionally no resources since data resources are
  1081  				// supposed to refresh themselves even if they didn't
  1082  				// already exist.
  1083  				Resources: map[string]*ResourceState{},
  1084  			},
  1085  		},
  1086  	})
  1087  
  1088  	schema := &configschema.Block{
  1089  		Attributes: map[string]*configschema.Attribute{
  1090  			"inputs": {
  1091  				Type:     cty.Map(cty.String),
  1092  				Optional: true,
  1093  			},
  1094  		},
  1095  	}
  1096  
  1097  	p := testProvider("null")
  1098  	p.GetSchemaReturn = &ProviderSchema{
  1099  		Provider: &configschema.Block{},
  1100  		DataSources: map[string]*configschema.Block{
  1101  			"null_data_source": schema,
  1102  		},
  1103  	}
  1104  
  1105  	ctx := testContext2(t, &ContextOpts{
  1106  		Config: m,
  1107  		ProviderResolver: providers.ResolverFixed(
  1108  			map[string]providers.Factory{
  1109  				"null": testProviderFuncFixed(p),
  1110  			},
  1111  		),
  1112  		State: state,
  1113  	})
  1114  
  1115  	var readStateVal cty.Value
  1116  
  1117  	p.ReadDataSourceFn = func(req providers.ReadDataSourceRequest) providers.ReadDataSourceResponse {
  1118  		m := req.Config.AsValueMap()
  1119  		m["inputs"] = cty.MapVal(map[string]cty.Value{"test": cty.StringVal("yes")})
  1120  		readStateVal = cty.ObjectVal(m)
  1121  
  1122  		return providers.ReadDataSourceResponse{
  1123  			State: readStateVal,
  1124  		}
  1125  
  1126  		// FIXME: should the "outputs" value here be added to the reutnred state?
  1127  		// Attributes: map[string]*ResourceAttrDiff{
  1128  		// 	"inputs.#": {
  1129  		// 		Old:  "0",
  1130  		// 		New:  "1",
  1131  		// 		Type: DiffAttrInput,
  1132  		// 	},
  1133  		// 	"inputs.test": {
  1134  		// 		Old:  "",
  1135  		// 		New:  "yes",
  1136  		// 		Type: DiffAttrInput,
  1137  		// 	},
  1138  		// 	"outputs.#": {
  1139  		// 		Old:         "",
  1140  		// 		New:         "",
  1141  		// 		NewComputed: true,
  1142  		// 		Type:        DiffAttrOutput,
  1143  		// 	},
  1144  		// },
  1145  	}
  1146  
  1147  	s, diags := ctx.Refresh()
  1148  	if diags.HasErrors() {
  1149  		t.Fatalf("refresh errors: %s", diags.Err())
  1150  	}
  1151  
  1152  	if !p.ReadDataSourceCalled {
  1153  		t.Fatal("ReadDataSource should have been called")
  1154  	}
  1155  
  1156  	// mod := s.RootModule()
  1157  	// if got := mod.Resources["data.null_data_source.testing"].Primary.ID; got != "-" {
  1158  	// 	t.Fatalf("resource id is %q; want %s", got, "-")
  1159  	// }
  1160  	// if !reflect.DeepEqual(mod.Resources["data.null_data_source.testing"].Primary, p.ReadDataApplyReturn) {
  1161  	// 	t.Fatalf("bad: %#v", mod.Resources)
  1162  	// }
  1163  
  1164  	mod := s.RootModule()
  1165  
  1166  	newState, err := mod.Resources["data.null_data_source.testing"].Instances[addrs.NoKey].Current.Decode(schema.ImpliedType())
  1167  	if err != nil {
  1168  		t.Fatal(err)
  1169  	}
  1170  
  1171  	if !cmp.Equal(readStateVal, newState.Value, valueComparer, equateEmpty) {
  1172  		t.Fatal(cmp.Diff(readStateVal, newState.Value, valueComparer, equateEmpty))
  1173  	}
  1174  }
  1175  
  1176  func TestContext2Refresh_dataStateRefData(t *testing.T) {
  1177  	p := testProvider("null")
  1178  	p.GetSchemaReturn = &ProviderSchema{
  1179  		Provider: &configschema.Block{},
  1180  		DataSources: map[string]*configschema.Block{
  1181  			"null_data_source": {
  1182  				Attributes: map[string]*configschema.Attribute{
  1183  					"id": {
  1184  						Type:     cty.String,
  1185  						Computed: true,
  1186  					},
  1187  					"foo": {
  1188  						Type:     cty.String,
  1189  						Optional: true,
  1190  					},
  1191  					"bar": {
  1192  						Type:     cty.String,
  1193  						Optional: true,
  1194  					},
  1195  				},
  1196  			},
  1197  		},
  1198  	}
  1199  
  1200  	m := testModule(t, "refresh-data-ref-data")
  1201  	state := MustShimLegacyState(&State{
  1202  		Modules: []*ModuleState{
  1203  			{
  1204  				Path: rootModulePath,
  1205  				// Intentionally no resources since data resources are
  1206  				// supposed to refresh themselves even if they didn't
  1207  				// already exist.
  1208  				Resources: map[string]*ResourceState{},
  1209  			},
  1210  		},
  1211  	})
  1212  	ctx := testContext2(t, &ContextOpts{
  1213  		Config: m,
  1214  		ProviderResolver: providers.ResolverFixed(
  1215  			map[string]providers.Factory{
  1216  				"null": testProviderFuncFixed(p),
  1217  			},
  1218  		),
  1219  		State: state,
  1220  	})
  1221  
  1222  	p.ReadDataSourceFn = func(req providers.ReadDataSourceRequest) providers.ReadDataSourceResponse {
  1223  		// add the required id
  1224  		m := req.Config.AsValueMap()
  1225  		m["id"] = cty.StringVal("foo")
  1226  
  1227  		return providers.ReadDataSourceResponse{
  1228  			State: cty.ObjectVal(m),
  1229  		}
  1230  	}
  1231  
  1232  	s, diags := ctx.Refresh()
  1233  	if diags.HasErrors() {
  1234  		t.Fatalf("refresh errors: %s", diags.Err())
  1235  	}
  1236  
  1237  	actual := strings.TrimSpace(s.String())
  1238  	expected := strings.TrimSpace(testTerraformRefreshDataRefDataStr)
  1239  	if actual != expected {
  1240  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  1241  	}
  1242  }
  1243  
  1244  func TestContext2Refresh_tainted(t *testing.T) {
  1245  	p := testProvider("aws")
  1246  	m := testModule(t, "refresh-basic")
  1247  	state := MustShimLegacyState(&State{
  1248  		Modules: []*ModuleState{
  1249  			{
  1250  				Path: rootModulePath,
  1251  				Resources: map[string]*ResourceState{
  1252  					"aws_instance.web": {
  1253  						Type: "aws_instance",
  1254  						Primary: &InstanceState{
  1255  							ID:      "bar",
  1256  							Tainted: true,
  1257  						},
  1258  					},
  1259  				},
  1260  			},
  1261  		},
  1262  	})
  1263  	ctx := testContext2(t, &ContextOpts{
  1264  		Config: m,
  1265  		ProviderResolver: providers.ResolverFixed(
  1266  			map[string]providers.Factory{
  1267  				"aws": testProviderFuncFixed(p),
  1268  			},
  1269  		),
  1270  		State: state,
  1271  	})
  1272  	p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse {
  1273  		// add the required id
  1274  		m := req.PriorState.AsValueMap()
  1275  		m["id"] = cty.StringVal("foo")
  1276  
  1277  		return providers.ReadResourceResponse{
  1278  			NewState: cty.ObjectVal(m),
  1279  		}
  1280  	}
  1281  
  1282  	s, diags := ctx.Refresh()
  1283  	if diags.HasErrors() {
  1284  		t.Fatalf("refresh errors: %s", diags.Err())
  1285  	}
  1286  	if !p.ReadResourceCalled {
  1287  		t.Fatal("ReadResource was not called; should have been")
  1288  	}
  1289  
  1290  	actual := strings.TrimSpace(s.String())
  1291  	expected := strings.TrimSpace(testContextRefreshTaintedStr)
  1292  	if actual != expected {
  1293  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  1294  	}
  1295  }
  1296  
  1297  // Doing a Refresh (or any operation really, but Refresh usually
  1298  // happens first) with a config with an unknown provider should result in
  1299  // an error. The key bug this found was that this wasn't happening if
  1300  // Providers was _empty_.
  1301  func TestContext2Refresh_unknownProvider(t *testing.T) {
  1302  	m := testModule(t, "refresh-unknown-provider")
  1303  	p := testProvider("aws")
  1304  	p.ApplyFn = testApplyFn
  1305  	p.DiffFn = testDiffFn
  1306  
  1307  	_, diags := NewContext(&ContextOpts{
  1308  		Config: m,
  1309  		ProviderResolver: providers.ResolverFixed(
  1310  			map[string]providers.Factory{},
  1311  		),
  1312  		State: MustShimLegacyState(&State{
  1313  			Modules: []*ModuleState{
  1314  				{
  1315  					Path: rootModulePath,
  1316  					Resources: map[string]*ResourceState{
  1317  						"aws_instance.web": {
  1318  							Type: "aws_instance",
  1319  							Primary: &InstanceState{
  1320  								ID: "foo",
  1321  							},
  1322  						},
  1323  					},
  1324  				},
  1325  			},
  1326  		}),
  1327  	})
  1328  
  1329  	if !diags.HasErrors() {
  1330  		t.Fatal("successfully created context; want error")
  1331  	}
  1332  
  1333  	if !regexp.MustCompile(`provider ".+" is not available`).MatchString(diags.Err().Error()) {
  1334  		t.Fatalf("wrong error: %s", diags.Err())
  1335  	}
  1336  }
  1337  
  1338  func TestContext2Refresh_vars(t *testing.T) {
  1339  	p := testProvider("aws")
  1340  
  1341  	schema := &configschema.Block{
  1342  		Attributes: map[string]*configschema.Attribute{
  1343  			"ami": {
  1344  				Type:     cty.String,
  1345  				Optional: true,
  1346  			},
  1347  			"id": {
  1348  				Type:     cty.String,
  1349  				Computed: true,
  1350  			},
  1351  		},
  1352  	}
  1353  
  1354  	p.GetSchemaReturn = &ProviderSchema{
  1355  		Provider:      &configschema.Block{},
  1356  		ResourceTypes: map[string]*configschema.Block{"aws_instance": schema},
  1357  	}
  1358  
  1359  	m := testModule(t, "refresh-vars")
  1360  	ctx := testContext2(t, &ContextOpts{
  1361  		Config: m,
  1362  		ProviderResolver: providers.ResolverFixed(
  1363  			map[string]providers.Factory{
  1364  				"aws": testProviderFuncFixed(p),
  1365  			},
  1366  		),
  1367  		State: MustShimLegacyState(&State{
  1368  
  1369  			Modules: []*ModuleState{
  1370  				{
  1371  					Path: rootModulePath,
  1372  					Resources: map[string]*ResourceState{
  1373  						"aws_instance.web": {
  1374  							Type: "aws_instance",
  1375  							Primary: &InstanceState{
  1376  								ID: "foo",
  1377  							},
  1378  						},
  1379  					},
  1380  				},
  1381  			},
  1382  		}),
  1383  	})
  1384  
  1385  	readStateVal, err := schema.CoerceValue(cty.ObjectVal(map[string]cty.Value{
  1386  		"id": cty.StringVal("foo"),
  1387  	}))
  1388  	if err != nil {
  1389  		t.Fatal(err)
  1390  	}
  1391  
  1392  	p.ReadResourceFn = nil
  1393  	p.ReadResourceResponse = providers.ReadResourceResponse{
  1394  		NewState: readStateVal,
  1395  	}
  1396  
  1397  	p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
  1398  		return providers.PlanResourceChangeResponse{
  1399  			PlannedState: req.ProposedNewState,
  1400  		}
  1401  	}
  1402  
  1403  	s, diags := ctx.Refresh()
  1404  	if diags.HasErrors() {
  1405  		t.Fatalf("refresh errors: %s", diags.Err())
  1406  	}
  1407  
  1408  	if !p.ReadResourceCalled {
  1409  		t.Fatal("read resource should be called")
  1410  	}
  1411  
  1412  	mod := s.RootModule()
  1413  
  1414  	newState, err := mod.Resources["aws_instance.web"].Instances[addrs.NoKey].Current.Decode(schema.ImpliedType())
  1415  	if err != nil {
  1416  		t.Fatal(err)
  1417  	}
  1418  
  1419  	if !cmp.Equal(readStateVal, newState.Value, valueComparer, equateEmpty) {
  1420  		t.Fatal(cmp.Diff(readStateVal, newState.Value, valueComparer, equateEmpty))
  1421  	}
  1422  
  1423  	for _, r := range mod.Resources {
  1424  		if r.Addr.Type == "" {
  1425  			t.Fatalf("no type: %#v", r)
  1426  		}
  1427  	}
  1428  }
  1429  
  1430  func TestContext2Refresh_orphanModule(t *testing.T) {
  1431  	p := testProvider("aws")
  1432  	m := testModule(t, "refresh-module-orphan")
  1433  
  1434  	// Create a custom refresh function to track the order they were visited
  1435  	var order []string
  1436  	var orderLock sync.Mutex
  1437  	p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse {
  1438  		orderLock.Lock()
  1439  		defer orderLock.Unlock()
  1440  
  1441  		order = append(order, req.PriorState.GetAttr("id").AsString())
  1442  		return providers.ReadResourceResponse{
  1443  			NewState: req.PriorState,
  1444  		}
  1445  	}
  1446  
  1447  	state := MustShimLegacyState(&State{
  1448  		Modules: []*ModuleState{
  1449  			{
  1450  				Path: rootModulePath,
  1451  				Resources: map[string]*ResourceState{
  1452  					"aws_instance.foo": {
  1453  						Type: "aws_instance",
  1454  						Primary: &InstanceState{
  1455  							ID: "i-abc123",
  1456  							Attributes: map[string]string{
  1457  								"id":           "i-abc123",
  1458  								"childid":      "i-bcd234",
  1459  								"grandchildid": "i-cde345",
  1460  							},
  1461  						},
  1462  						Dependencies: []string{
  1463  							"module.child",
  1464  							"module.child",
  1465  						},
  1466  						Provider: "provider.aws",
  1467  					},
  1468  				},
  1469  			},
  1470  			{
  1471  				Path: append(rootModulePath, "child"),
  1472  				Resources: map[string]*ResourceState{
  1473  					"aws_instance.bar": {
  1474  						Type: "aws_instance",
  1475  						Primary: &InstanceState{
  1476  							ID: "i-bcd234",
  1477  							Attributes: map[string]string{
  1478  								"id":           "i-bcd234",
  1479  								"grandchildid": "i-cde345",
  1480  							},
  1481  						},
  1482  						Dependencies: []string{
  1483  							"module.grandchild",
  1484  						},
  1485  						Provider: "provider.aws",
  1486  					},
  1487  				},
  1488  				Outputs: map[string]*OutputState{
  1489  					"id": {
  1490  						Value: "i-bcd234",
  1491  						Type:  "string",
  1492  					},
  1493  					"grandchild_id": {
  1494  						Value: "i-cde345",
  1495  						Type:  "string",
  1496  					},
  1497  				},
  1498  			},
  1499  			{
  1500  				Path: append(rootModulePath, "child", "grandchild"),
  1501  				Resources: map[string]*ResourceState{
  1502  					"aws_instance.baz": {
  1503  						Type: "aws_instance",
  1504  						Primary: &InstanceState{
  1505  							ID: "i-cde345",
  1506  							Attributes: map[string]string{
  1507  								"id": "i-cde345",
  1508  							},
  1509  						},
  1510  						Provider: "provider.aws",
  1511  					},
  1512  				},
  1513  				Outputs: map[string]*OutputState{
  1514  					"id": {
  1515  						Value: "i-cde345",
  1516  						Type:  "string",
  1517  					},
  1518  				},
  1519  			},
  1520  		},
  1521  	})
  1522  	ctx := testContext2(t, &ContextOpts{
  1523  		Config: m,
  1524  		ProviderResolver: providers.ResolverFixed(
  1525  			map[string]providers.Factory{
  1526  				"aws": testProviderFuncFixed(p),
  1527  			},
  1528  		),
  1529  		State: state,
  1530  	})
  1531  
  1532  	testCheckDeadlock(t, func() {
  1533  		_, err := ctx.Refresh()
  1534  		if err != nil {
  1535  			t.Fatalf("err: %s", err)
  1536  		}
  1537  
  1538  		// TODO: handle order properly for orphaned modules / resources
  1539  		// expected := []string{"i-abc123", "i-bcd234", "i-cde345"}
  1540  		// if !reflect.DeepEqual(order, expected) {
  1541  		// 	t.Fatalf("expected: %#v, got: %#v", expected, order)
  1542  		// }
  1543  	})
  1544  }
  1545  
  1546  func TestContext2Validate(t *testing.T) {
  1547  	p := testProvider("aws")
  1548  	p.GetSchemaReturn = &ProviderSchema{
  1549  		Provider: &configschema.Block{},
  1550  		ResourceTypes: map[string]*configschema.Block{
  1551  			"aws_instance": {
  1552  				Attributes: map[string]*configschema.Attribute{
  1553  					"foo": {
  1554  						Type:     cty.String,
  1555  						Optional: true,
  1556  					},
  1557  					"num": {
  1558  						Type:     cty.String,
  1559  						Optional: true,
  1560  					},
  1561  				},
  1562  			},
  1563  		},
  1564  	}
  1565  
  1566  	m := testModule(t, "validate-good")
  1567  	c := testContext2(t, &ContextOpts{
  1568  		Config: m,
  1569  		ProviderResolver: providers.ResolverFixed(
  1570  			map[string]providers.Factory{
  1571  				"aws": testProviderFuncFixed(p),
  1572  			},
  1573  		),
  1574  	})
  1575  
  1576  	diags := c.Validate()
  1577  	if len(diags) != 0 {
  1578  		t.Fatalf("unexpected error: %#v", diags.ErrWithWarnings())
  1579  	}
  1580  }
  1581  
  1582  // TestContext2Refresh_noDiffHookOnScaleOut tests to make sure that
  1583  // pre/post-diff hooks are not called when running EvalDiff on scale-out nodes
  1584  // (nodes with no state). The effect here is to make sure that the diffs -
  1585  // which only exist for interpolation of parallel resources or data sources -
  1586  // do not end up being counted in the UI.
  1587  func TestContext2Refresh_noDiffHookOnScaleOut(t *testing.T) {
  1588  	h := new(MockHook)
  1589  	p := testProvider("aws")
  1590  	m := testModule(t, "refresh-resource-scale-inout")
  1591  
  1592  	// Refresh creates a partial plan for any instances that don't have
  1593  	// remote objects yet, to get stub values for interpolation. Therefore
  1594  	// we need to make DiffFn available to let that complete.
  1595  	p.DiffFn = testDiffFn
  1596  
  1597  	state := MustShimLegacyState(&State{
  1598  		Modules: []*ModuleState{
  1599  			{
  1600  				Path: rootModulePath,
  1601  				Resources: map[string]*ResourceState{
  1602  					"aws_instance.foo.0": {
  1603  						Type: "aws_instance",
  1604  						Deposed: []*InstanceState{
  1605  							{
  1606  								ID: "foo",
  1607  								Attributes: map[string]string{
  1608  									"id": "foo",
  1609  								},
  1610  							},
  1611  						},
  1612  					},
  1613  					"aws_instance.foo.1": {
  1614  						Type: "aws_instance",
  1615  						Deposed: []*InstanceState{
  1616  							{
  1617  								ID: "bar",
  1618  								Attributes: map[string]string{
  1619  									"id": "foo",
  1620  								},
  1621  							},
  1622  						},
  1623  					},
  1624  				},
  1625  			},
  1626  		},
  1627  	})
  1628  
  1629  	ctx := testContext2(t, &ContextOpts{
  1630  		Config: m,
  1631  		Hooks:  []Hook{h},
  1632  		ProviderResolver: providers.ResolverFixed(
  1633  			map[string]providers.Factory{
  1634  				"aws": testProviderFuncFixed(p),
  1635  			},
  1636  		),
  1637  		State: state,
  1638  	})
  1639  
  1640  	_, diags := ctx.Refresh()
  1641  	if diags.HasErrors() {
  1642  		t.Fatalf("refresh errors: %s", diags.Err())
  1643  	}
  1644  	if h.PreDiffCalled {
  1645  		t.Fatal("PreDiff should not have been called")
  1646  	}
  1647  	if h.PostDiffCalled {
  1648  		t.Fatal("PostDiff should not have been called")
  1649  	}
  1650  }
  1651  
  1652  func TestContext2Refresh_updateProviderInState(t *testing.T) {
  1653  	m := testModule(t, "update-resource-provider")
  1654  	p := testProvider("aws")
  1655  	p.DiffFn = testDiffFn
  1656  	p.ApplyFn = testApplyFn
  1657  
  1658  	s := MustShimLegacyState(&State{
  1659  		Modules: []*ModuleState{
  1660  			{
  1661  				Path: rootModulePath,
  1662  				Resources: map[string]*ResourceState{
  1663  					"aws_instance.bar": {
  1664  						Type: "aws_instance",
  1665  						Primary: &InstanceState{
  1666  							ID: "foo",
  1667  							Attributes: map[string]string{
  1668  								"id": "foo",
  1669  							},
  1670  						},
  1671  						Provider: "provider.aws.baz",
  1672  					},
  1673  				},
  1674  			},
  1675  		},
  1676  	})
  1677  
  1678  	ctx := testContext2(t, &ContextOpts{
  1679  		Config: m,
  1680  		ProviderResolver: providers.ResolverFixed(
  1681  			map[string]providers.Factory{
  1682  				"aws": testProviderFuncFixed(p),
  1683  			},
  1684  		),
  1685  		State: s,
  1686  	})
  1687  
  1688  	expected := strings.TrimSpace(`
  1689  aws_instance.bar:
  1690    ID = foo
  1691    provider = provider.aws.foo`)
  1692  
  1693  	state, diags := ctx.Refresh()
  1694  	if diags.HasErrors() {
  1695  		t.Fatal(diags.Err())
  1696  	}
  1697  
  1698  	actual := state.String()
  1699  	if actual != expected {
  1700  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  1701  	}
  1702  }
  1703  
  1704  func TestContext2Refresh_schemaUpgradeFlatmap(t *testing.T) {
  1705  	m := testModule(t, "empty")
  1706  	p := testProvider("test")
  1707  	p.GetSchemaReturn = &ProviderSchema{
  1708  		ResourceTypes: map[string]*configschema.Block{
  1709  			"test_thing": {
  1710  				Attributes: map[string]*configschema.Attribute{
  1711  					"name": { // imagining we renamed this from "id"
  1712  						Type:     cty.String,
  1713  						Optional: true,
  1714  					},
  1715  				},
  1716  			},
  1717  		},
  1718  		ResourceTypeSchemaVersions: map[string]uint64{
  1719  			"test_thing": 5,
  1720  		},
  1721  	}
  1722  	p.UpgradeResourceStateResponse = providers.UpgradeResourceStateResponse{
  1723  		UpgradedState: cty.ObjectVal(map[string]cty.Value{
  1724  			"name": cty.StringVal("foo"),
  1725  		}),
  1726  	}
  1727  
  1728  	s := states.BuildState(func(s *states.SyncState) {
  1729  		s.SetResourceInstanceCurrent(
  1730  			addrs.Resource{
  1731  				Mode: addrs.ManagedResourceMode,
  1732  				Type: "test_thing",
  1733  				Name: "bar",
  1734  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
  1735  			&states.ResourceInstanceObjectSrc{
  1736  				Status:        states.ObjectReady,
  1737  				SchemaVersion: 3,
  1738  				AttrsFlat: map[string]string{
  1739  					"id": "foo",
  1740  				},
  1741  			},
  1742  			addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance),
  1743  		)
  1744  	})
  1745  
  1746  	ctx := testContext2(t, &ContextOpts{
  1747  		Config: m,
  1748  		ProviderResolver: providers.ResolverFixed(
  1749  			map[string]providers.Factory{
  1750  				"test": testProviderFuncFixed(p),
  1751  			},
  1752  		),
  1753  		State: s,
  1754  	})
  1755  
  1756  	state, diags := ctx.Refresh()
  1757  	if diags.HasErrors() {
  1758  		t.Fatal(diags.Err())
  1759  	}
  1760  
  1761  	{
  1762  		got := p.UpgradeResourceStateRequest
  1763  		want := providers.UpgradeResourceStateRequest{
  1764  			TypeName: "test_thing",
  1765  			Version:  3,
  1766  			RawStateFlatmap: map[string]string{
  1767  				"id": "foo",
  1768  			},
  1769  		}
  1770  		if !cmp.Equal(got, want) {
  1771  			t.Errorf("wrong upgrade request\n%s", cmp.Diff(want, got))
  1772  		}
  1773  	}
  1774  
  1775  	{
  1776  		got := state.String()
  1777  		want := strings.TrimSpace(`
  1778  test_thing.bar:
  1779    ID = 
  1780    provider = provider.test
  1781    name = foo
  1782  `)
  1783  		if got != want {
  1784  			t.Fatalf("wrong result state\ngot:\n%s\n\nwant:\n%s", got, want)
  1785  		}
  1786  	}
  1787  }
  1788  
  1789  func TestContext2Refresh_schemaUpgradeJSON(t *testing.T) {
  1790  	m := testModule(t, "empty")
  1791  	p := testProvider("test")
  1792  	p.GetSchemaReturn = &ProviderSchema{
  1793  		ResourceTypes: map[string]*configschema.Block{
  1794  			"test_thing": {
  1795  				Attributes: map[string]*configschema.Attribute{
  1796  					"name": { // imagining we renamed this from "id"
  1797  						Type:     cty.String,
  1798  						Optional: true,
  1799  					},
  1800  				},
  1801  			},
  1802  		},
  1803  		ResourceTypeSchemaVersions: map[string]uint64{
  1804  			"test_thing": 5,
  1805  		},
  1806  	}
  1807  	p.UpgradeResourceStateResponse = providers.UpgradeResourceStateResponse{
  1808  		UpgradedState: cty.ObjectVal(map[string]cty.Value{
  1809  			"name": cty.StringVal("foo"),
  1810  		}),
  1811  	}
  1812  
  1813  	s := states.BuildState(func(s *states.SyncState) {
  1814  		s.SetResourceInstanceCurrent(
  1815  			addrs.Resource{
  1816  				Mode: addrs.ManagedResourceMode,
  1817  				Type: "test_thing",
  1818  				Name: "bar",
  1819  			}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
  1820  			&states.ResourceInstanceObjectSrc{
  1821  				Status:        states.ObjectReady,
  1822  				SchemaVersion: 3,
  1823  				AttrsJSON:     []byte(`{"id":"foo"}`),
  1824  			},
  1825  			addrs.ProviderConfig{Type: "test"}.Absolute(addrs.RootModuleInstance),
  1826  		)
  1827  	})
  1828  
  1829  	ctx := testContext2(t, &ContextOpts{
  1830  		Config: m,
  1831  		ProviderResolver: providers.ResolverFixed(
  1832  			map[string]providers.Factory{
  1833  				"test": testProviderFuncFixed(p),
  1834  			},
  1835  		),
  1836  		State: s,
  1837  	})
  1838  
  1839  	state, diags := ctx.Refresh()
  1840  	if diags.HasErrors() {
  1841  		t.Fatal(diags.Err())
  1842  	}
  1843  
  1844  	{
  1845  		got := p.UpgradeResourceStateRequest
  1846  		want := providers.UpgradeResourceStateRequest{
  1847  			TypeName:     "test_thing",
  1848  			Version:      3,
  1849  			RawStateJSON: []byte(`{"id":"foo"}`),
  1850  		}
  1851  		if !cmp.Equal(got, want) {
  1852  			t.Errorf("wrong upgrade request\n%s", cmp.Diff(want, got))
  1853  		}
  1854  	}
  1855  
  1856  	{
  1857  		got := state.String()
  1858  		want := strings.TrimSpace(`
  1859  test_thing.bar:
  1860    ID = 
  1861    provider = provider.test
  1862    name = foo
  1863  `)
  1864  		if got != want {
  1865  			t.Fatalf("wrong result state\ngot:\n%s\n\nwant:\n%s", got, want)
  1866  		}
  1867  	}
  1868  }
  1869  
  1870  func TestContext2Refresh_dataValidation(t *testing.T) {
  1871  	m := testModuleInline(t, map[string]string{
  1872  		"main.tf": `
  1873  data "aws_data_source" "foo" {
  1874    foo = "bar"
  1875  }
  1876  `,
  1877  	})
  1878  
  1879  	p := testProvider("aws")
  1880  	p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) {
  1881  		resp.PlannedState = req.ProposedNewState
  1882  		return
  1883  	}
  1884  	p.ReadDataSourceFn = func(req providers.ReadDataSourceRequest) (resp providers.ReadDataSourceResponse) {
  1885  		resp.State = req.Config
  1886  		return
  1887  	}
  1888  
  1889  	ctx := testContext2(t, &ContextOpts{
  1890  		Config: m,
  1891  		ProviderResolver: providers.ResolverFixed(
  1892  			map[string]providers.Factory{
  1893  				"aws": testProviderFuncFixed(p),
  1894  			},
  1895  		),
  1896  	})
  1897  
  1898  	_, diags := ctx.Refresh()
  1899  	if diags.HasErrors() {
  1900  		// Should get this error:
  1901  		// Unsupported attribute: This object does not have an attribute named "missing"
  1902  		t.Fatal(diags.Err())
  1903  	}
  1904  
  1905  	if !p.ValidateDataSourceConfigCalled {
  1906  		t.Fatal("ValidateDataSourceConfig not called during plan")
  1907  	}
  1908  }
  1909  
  1910  func TestContext2Refresh_dataResourceDependsOn(t *testing.T) {
  1911  	m := testModule(t, "plan-data-depends-on")
  1912  	p := testProvider("test")
  1913  	p.GetSchemaReturn = &ProviderSchema{
  1914  		ResourceTypes: map[string]*configschema.Block{
  1915  			"test_resource": {
  1916  				Attributes: map[string]*configschema.Attribute{
  1917  					"id":  {Type: cty.String, Computed: true},
  1918  					"foo": {Type: cty.String, Optional: true},
  1919  				},
  1920  			},
  1921  		},
  1922  		DataSources: map[string]*configschema.Block{
  1923  			"test_data": {
  1924  				Attributes: map[string]*configschema.Attribute{
  1925  					"compute": {Type: cty.String, Computed: true},
  1926  				},
  1927  			},
  1928  		},
  1929  	}
  1930  	p.DiffFn = testDiffFn
  1931  
  1932  	s := MustShimLegacyState(&State{
  1933  		Modules: []*ModuleState{
  1934  			{
  1935  				Path: rootModulePath,
  1936  				Resources: map[string]*ResourceState{
  1937  					"test_resource.a": {
  1938  						Type:     "test_resource",
  1939  						Provider: "provider.test",
  1940  						Primary: &InstanceState{
  1941  							ID: "a",
  1942  							Attributes: map[string]string{
  1943  								"id": "a",
  1944  							},
  1945  						},
  1946  					},
  1947  				},
  1948  			},
  1949  		},
  1950  	})
  1951  
  1952  	ctx := testContext2(t, &ContextOpts{
  1953  		Config: m,
  1954  		ProviderResolver: providers.ResolverFixed(
  1955  			map[string]providers.Factory{
  1956  				"test": testProviderFuncFixed(p),
  1957  			},
  1958  		),
  1959  		State: s,
  1960  	})
  1961  
  1962  	_, diags := ctx.Refresh()
  1963  	if diags.HasErrors() {
  1964  		t.Fatalf("unexpected errors: %s", diags.Err())
  1965  	}
  1966  }