github.com/lymingtonprecision/terraform@v0.9.9-0.20170613092852-62acef9611a9/terraform/context_refresh_test.go (about)

     1  package terraform
     2  
     3  import (
     4  	"reflect"
     5  	"sort"
     6  	"strings"
     7  	"sync"
     8  	"testing"
     9  )
    10  
    11  func TestContext2Refresh(t *testing.T) {
    12  	p := testProvider("aws")
    13  	m := testModule(t, "refresh-basic")
    14  	ctx := testContext2(t, &ContextOpts{
    15  		Module: m,
    16  		ProviderResolver: ResourceProviderResolverFixed(
    17  			map[string]ResourceProviderFactory{
    18  				"aws": testProviderFuncFixed(p),
    19  			},
    20  		),
    21  		State: &State{
    22  			Modules: []*ModuleState{
    23  				&ModuleState{
    24  					Path: rootModulePath,
    25  					Resources: map[string]*ResourceState{
    26  						"aws_instance.web": &ResourceState{
    27  							Type: "aws_instance",
    28  							Primary: &InstanceState{
    29  								ID: "foo",
    30  							},
    31  						},
    32  					},
    33  				},
    34  			},
    35  		},
    36  	})
    37  
    38  	p.RefreshFn = nil
    39  	p.RefreshReturn = &InstanceState{
    40  		ID: "foo",
    41  	}
    42  
    43  	s, err := ctx.Refresh()
    44  	mod := s.RootModule()
    45  	if err != nil {
    46  		t.Fatalf("err: %s", err)
    47  	}
    48  	if !p.RefreshCalled {
    49  		t.Fatal("refresh should be called")
    50  	}
    51  	if p.RefreshState.ID != "foo" {
    52  		t.Fatalf("bad: %#v", p.RefreshState)
    53  	}
    54  	if !reflect.DeepEqual(mod.Resources["aws_instance.web"].Primary, p.RefreshReturn) {
    55  		t.Fatalf("bad: %#v %#v", mod.Resources["aws_instance.web"], p.RefreshReturn)
    56  	}
    57  
    58  	for _, r := range mod.Resources {
    59  		if r.Type == "" {
    60  			t.Fatalf("no type: %#v", r)
    61  		}
    62  	}
    63  }
    64  
    65  func TestContext2Refresh_dataComputedModuleVar(t *testing.T) {
    66  	p := testProvider("aws")
    67  	m := testModule(t, "refresh-data-module-var")
    68  	ctx := testContext2(t, &ContextOpts{
    69  		Module: m,
    70  		ProviderResolver: ResourceProviderResolverFixed(
    71  			map[string]ResourceProviderFactory{
    72  				"aws": testProviderFuncFixed(p),
    73  			},
    74  		),
    75  	})
    76  
    77  	p.RefreshFn = nil
    78  	p.RefreshReturn = &InstanceState{
    79  		ID: "foo",
    80  	}
    81  
    82  	s, err := ctx.Refresh()
    83  	if err != nil {
    84  		t.Fatalf("err: %s", err)
    85  	}
    86  
    87  	checkStateString(t, s, `
    88  <no state>
    89  module.child:
    90    <no state>`)
    91  }
    92  
    93  func TestContext2Refresh_targeted(t *testing.T) {
    94  	p := testProvider("aws")
    95  	m := testModule(t, "refresh-targeted")
    96  	ctx := testContext2(t, &ContextOpts{
    97  		Module: m,
    98  		ProviderResolver: ResourceProviderResolverFixed(
    99  			map[string]ResourceProviderFactory{
   100  				"aws": testProviderFuncFixed(p),
   101  			},
   102  		),
   103  		State: &State{
   104  			Modules: []*ModuleState{
   105  				&ModuleState{
   106  					Path: rootModulePath,
   107  					Resources: map[string]*ResourceState{
   108  						"aws_vpc.metoo":      resourceState("aws_vpc", "vpc-abc123"),
   109  						"aws_instance.notme": resourceState("aws_instance", "i-bcd345"),
   110  						"aws_instance.me":    resourceState("aws_instance", "i-abc123"),
   111  						"aws_elb.meneither":  resourceState("aws_elb", "lb-abc123"),
   112  					},
   113  				},
   114  			},
   115  		},
   116  		Targets: []string{"aws_instance.me"},
   117  	})
   118  
   119  	refreshedResources := make([]string, 0, 2)
   120  	p.RefreshFn = func(i *InstanceInfo, is *InstanceState) (*InstanceState, error) {
   121  		refreshedResources = append(refreshedResources, i.Id)
   122  		return is, nil
   123  	}
   124  
   125  	_, err := ctx.Refresh()
   126  	if err != nil {
   127  		t.Fatalf("err: %s", err)
   128  	}
   129  
   130  	expected := []string{"aws_vpc.metoo", "aws_instance.me"}
   131  	if !reflect.DeepEqual(refreshedResources, expected) {
   132  		t.Fatalf("expected: %#v, got: %#v", expected, refreshedResources)
   133  	}
   134  }
   135  
   136  func TestContext2Refresh_targetedCount(t *testing.T) {
   137  	p := testProvider("aws")
   138  	m := testModule(t, "refresh-targeted-count")
   139  	ctx := testContext2(t, &ContextOpts{
   140  		Module: m,
   141  		ProviderResolver: ResourceProviderResolverFixed(
   142  			map[string]ResourceProviderFactory{
   143  				"aws": testProviderFuncFixed(p),
   144  			},
   145  		),
   146  		State: &State{
   147  			Modules: []*ModuleState{
   148  				&ModuleState{
   149  					Path: rootModulePath,
   150  					Resources: map[string]*ResourceState{
   151  						"aws_vpc.metoo":      resourceState("aws_vpc", "vpc-abc123"),
   152  						"aws_instance.notme": resourceState("aws_instance", "i-bcd345"),
   153  						"aws_instance.me.0":  resourceState("aws_instance", "i-abc123"),
   154  						"aws_instance.me.1":  resourceState("aws_instance", "i-cde567"),
   155  						"aws_instance.me.2":  resourceState("aws_instance", "i-cde789"),
   156  						"aws_elb.meneither":  resourceState("aws_elb", "lb-abc123"),
   157  					},
   158  				},
   159  			},
   160  		},
   161  		Targets: []string{"aws_instance.me"},
   162  	})
   163  
   164  	refreshedResources := make([]string, 0, 2)
   165  	p.RefreshFn = func(i *InstanceInfo, is *InstanceState) (*InstanceState, error) {
   166  		refreshedResources = append(refreshedResources, i.Id)
   167  		return is, nil
   168  	}
   169  
   170  	_, err := ctx.Refresh()
   171  	if err != nil {
   172  		t.Fatalf("err: %s", err)
   173  	}
   174  
   175  	// Target didn't specify index, so we should get all our instances
   176  	expected := []string{
   177  		"aws_vpc.metoo",
   178  		"aws_instance.me.0",
   179  		"aws_instance.me.1",
   180  		"aws_instance.me.2",
   181  	}
   182  	sort.Strings(expected)
   183  	sort.Strings(refreshedResources)
   184  	if !reflect.DeepEqual(refreshedResources, expected) {
   185  		t.Fatalf("expected: %#v, got: %#v", expected, refreshedResources)
   186  	}
   187  }
   188  
   189  func TestContext2Refresh_targetedCountIndex(t *testing.T) {
   190  	p := testProvider("aws")
   191  	m := testModule(t, "refresh-targeted-count")
   192  	ctx := testContext2(t, &ContextOpts{
   193  		Module: m,
   194  		ProviderResolver: ResourceProviderResolverFixed(
   195  			map[string]ResourceProviderFactory{
   196  				"aws": testProviderFuncFixed(p),
   197  			},
   198  		),
   199  		State: &State{
   200  			Modules: []*ModuleState{
   201  				&ModuleState{
   202  					Path: rootModulePath,
   203  					Resources: map[string]*ResourceState{
   204  						"aws_vpc.metoo":      resourceState("aws_vpc", "vpc-abc123"),
   205  						"aws_instance.notme": resourceState("aws_instance", "i-bcd345"),
   206  						"aws_instance.me.0":  resourceState("aws_instance", "i-abc123"),
   207  						"aws_instance.me.1":  resourceState("aws_instance", "i-cde567"),
   208  						"aws_instance.me.2":  resourceState("aws_instance", "i-cde789"),
   209  						"aws_elb.meneither":  resourceState("aws_elb", "lb-abc123"),
   210  					},
   211  				},
   212  			},
   213  		},
   214  		Targets: []string{"aws_instance.me[0]"},
   215  	})
   216  
   217  	refreshedResources := make([]string, 0, 2)
   218  	p.RefreshFn = func(i *InstanceInfo, is *InstanceState) (*InstanceState, error) {
   219  		refreshedResources = append(refreshedResources, i.Id)
   220  		return is, nil
   221  	}
   222  
   223  	_, err := ctx.Refresh()
   224  	if err != nil {
   225  		t.Fatalf("err: %s", err)
   226  	}
   227  
   228  	expected := []string{"aws_vpc.metoo", "aws_instance.me.0"}
   229  	if !reflect.DeepEqual(refreshedResources, expected) {
   230  		t.Fatalf("expected: %#v, got: %#v", expected, refreshedResources)
   231  	}
   232  }
   233  
   234  func TestContext2Refresh_moduleComputedVar(t *testing.T) {
   235  	p := testProvider("aws")
   236  	m := testModule(t, "refresh-module-computed-var")
   237  	ctx := testContext2(t, &ContextOpts{
   238  		Module: m,
   239  		ProviderResolver: ResourceProviderResolverFixed(
   240  			map[string]ResourceProviderFactory{
   241  				"aws": testProviderFuncFixed(p),
   242  			},
   243  		),
   244  	})
   245  
   246  	// This was failing (see GH-2188) at some point, so this test just
   247  	// verifies that the failure goes away.
   248  	if _, err := ctx.Refresh(); err != nil {
   249  		t.Fatalf("err: %s", err)
   250  	}
   251  }
   252  
   253  func TestContext2Refresh_delete(t *testing.T) {
   254  	p := testProvider("aws")
   255  	m := testModule(t, "refresh-basic")
   256  	ctx := testContext2(t, &ContextOpts{
   257  		Module: m,
   258  		ProviderResolver: ResourceProviderResolverFixed(
   259  			map[string]ResourceProviderFactory{
   260  				"aws": testProviderFuncFixed(p),
   261  			},
   262  		),
   263  		State: &State{
   264  			Modules: []*ModuleState{
   265  				&ModuleState{
   266  					Path: rootModulePath,
   267  					Resources: map[string]*ResourceState{
   268  						"aws_instance.web": &ResourceState{
   269  							Type: "aws_instance",
   270  							Primary: &InstanceState{
   271  								ID: "foo",
   272  							},
   273  						},
   274  					},
   275  				},
   276  			},
   277  		},
   278  	})
   279  
   280  	p.RefreshFn = nil
   281  	p.RefreshReturn = nil
   282  
   283  	s, err := ctx.Refresh()
   284  	if err != nil {
   285  		t.Fatalf("err: %s", err)
   286  	}
   287  
   288  	mod := s.RootModule()
   289  	if len(mod.Resources) > 0 {
   290  		t.Fatal("resources should be empty")
   291  	}
   292  }
   293  
   294  func TestContext2Refresh_ignoreUncreated(t *testing.T) {
   295  	p := testProvider("aws")
   296  	m := testModule(t, "refresh-basic")
   297  	ctx := testContext2(t, &ContextOpts{
   298  		Module: m,
   299  		ProviderResolver: ResourceProviderResolverFixed(
   300  			map[string]ResourceProviderFactory{
   301  				"aws": testProviderFuncFixed(p),
   302  			},
   303  		),
   304  		State: nil,
   305  	})
   306  
   307  	p.RefreshFn = nil
   308  	p.RefreshReturn = &InstanceState{
   309  		ID: "foo",
   310  	}
   311  
   312  	_, err := ctx.Refresh()
   313  	if err != nil {
   314  		t.Fatalf("err: %s", err)
   315  	}
   316  	if p.RefreshCalled {
   317  		t.Fatal("refresh should not be called")
   318  	}
   319  }
   320  
   321  func TestContext2Refresh_hook(t *testing.T) {
   322  	h := new(MockHook)
   323  	p := testProvider("aws")
   324  	m := testModule(t, "refresh-basic")
   325  	ctx := testContext2(t, &ContextOpts{
   326  		Module: m,
   327  		Hooks:  []Hook{h},
   328  		ProviderResolver: ResourceProviderResolverFixed(
   329  			map[string]ResourceProviderFactory{
   330  				"aws": testProviderFuncFixed(p),
   331  			},
   332  		),
   333  		State: &State{
   334  			Modules: []*ModuleState{
   335  				&ModuleState{
   336  					Path: rootModulePath,
   337  					Resources: map[string]*ResourceState{
   338  						"aws_instance.web": &ResourceState{
   339  							Type: "aws_instance",
   340  							Primary: &InstanceState{
   341  								ID: "foo",
   342  							},
   343  						},
   344  					},
   345  				},
   346  			},
   347  		},
   348  	})
   349  
   350  	if _, err := ctx.Refresh(); err != nil {
   351  		t.Fatalf("err: %s", err)
   352  	}
   353  	if !h.PreRefreshCalled {
   354  		t.Fatal("should be called")
   355  	}
   356  	if !h.PostRefreshCalled {
   357  		t.Fatal("should be called")
   358  	}
   359  }
   360  
   361  func TestContext2Refresh_modules(t *testing.T) {
   362  	p := testProvider("aws")
   363  	m := testModule(t, "refresh-modules")
   364  	state := &State{
   365  		Modules: []*ModuleState{
   366  			&ModuleState{
   367  				Path: rootModulePath,
   368  				Resources: map[string]*ResourceState{
   369  					"aws_instance.web": &ResourceState{
   370  						Type: "aws_instance",
   371  						Primary: &InstanceState{
   372  							ID:      "bar",
   373  							Tainted: true,
   374  						},
   375  					},
   376  				},
   377  			},
   378  
   379  			&ModuleState{
   380  				Path: []string{"root", "child"},
   381  				Resources: map[string]*ResourceState{
   382  					"aws_instance.web": &ResourceState{
   383  						Type: "aws_instance",
   384  						Primary: &InstanceState{
   385  							ID: "baz",
   386  						},
   387  					},
   388  				},
   389  			},
   390  		},
   391  	}
   392  	ctx := testContext2(t, &ContextOpts{
   393  		Module: m,
   394  		ProviderResolver: ResourceProviderResolverFixed(
   395  			map[string]ResourceProviderFactory{
   396  				"aws": testProviderFuncFixed(p),
   397  			},
   398  		),
   399  		State: state,
   400  	})
   401  
   402  	p.RefreshFn = func(info *InstanceInfo, s *InstanceState) (*InstanceState, error) {
   403  		if s.ID != "baz" {
   404  			return s, nil
   405  		}
   406  
   407  		s.ID = "new"
   408  		return s, nil
   409  	}
   410  
   411  	s, err := ctx.Refresh()
   412  	if err != nil {
   413  		t.Fatalf("err: %s", err)
   414  	}
   415  
   416  	actual := strings.TrimSpace(s.String())
   417  	expected := strings.TrimSpace(testContextRefreshModuleStr)
   418  	if actual != expected {
   419  		t.Fatalf("bad:\n\n%s\n\n%s", actual, expected)
   420  	}
   421  }
   422  
   423  func TestContext2Refresh_moduleInputComputedOutput(t *testing.T) {
   424  	m := testModule(t, "refresh-module-input-computed-output")
   425  	p := testProvider("aws")
   426  	p.DiffFn = testDiffFn
   427  	ctx := testContext2(t, &ContextOpts{
   428  		Module: m,
   429  		ProviderResolver: ResourceProviderResolverFixed(
   430  			map[string]ResourceProviderFactory{
   431  				"aws": testProviderFuncFixed(p),
   432  			},
   433  		),
   434  	})
   435  
   436  	if _, err := ctx.Refresh(); err != nil {
   437  		t.Fatalf("err: %s", err)
   438  	}
   439  }
   440  
   441  func TestContext2Refresh_moduleVarModule(t *testing.T) {
   442  	m := testModule(t, "refresh-module-var-module")
   443  	p := testProvider("aws")
   444  	p.DiffFn = testDiffFn
   445  	ctx := testContext2(t, &ContextOpts{
   446  		Module: m,
   447  		ProviderResolver: ResourceProviderResolverFixed(
   448  			map[string]ResourceProviderFactory{
   449  				"aws": testProviderFuncFixed(p),
   450  			},
   451  		),
   452  	})
   453  
   454  	if _, err := ctx.Refresh(); err != nil {
   455  		t.Fatalf("err: %s", err)
   456  	}
   457  }
   458  
   459  // GH-70
   460  func TestContext2Refresh_noState(t *testing.T) {
   461  	p := testProvider("aws")
   462  	m := testModule(t, "refresh-no-state")
   463  	ctx := testContext2(t, &ContextOpts{
   464  		Module: m,
   465  		ProviderResolver: ResourceProviderResolverFixed(
   466  			map[string]ResourceProviderFactory{
   467  				"aws": testProviderFuncFixed(p),
   468  			},
   469  		),
   470  	})
   471  
   472  	p.RefreshFn = nil
   473  	p.RefreshReturn = &InstanceState{
   474  		ID: "foo",
   475  	}
   476  
   477  	if _, err := ctx.Refresh(); err != nil {
   478  		t.Fatalf("err: %s", err)
   479  	}
   480  }
   481  
   482  func TestContext2Refresh_output(t *testing.T) {
   483  	p := testProvider("aws")
   484  	m := testModule(t, "refresh-output")
   485  	ctx := testContext2(t, &ContextOpts{
   486  		Module: m,
   487  		ProviderResolver: ResourceProviderResolverFixed(
   488  			map[string]ResourceProviderFactory{
   489  				"aws": testProviderFuncFixed(p),
   490  			},
   491  		),
   492  		State: &State{
   493  			Modules: []*ModuleState{
   494  				&ModuleState{
   495  					Path: rootModulePath,
   496  					Resources: map[string]*ResourceState{
   497  						"aws_instance.web": &ResourceState{
   498  							Type: "aws_instance",
   499  							Primary: &InstanceState{
   500  								ID: "foo",
   501  								Attributes: map[string]string{
   502  									"foo": "bar",
   503  								},
   504  							},
   505  						},
   506  					},
   507  
   508  					Outputs: map[string]*OutputState{
   509  						"foo": &OutputState{
   510  							Type:      "string",
   511  							Sensitive: false,
   512  							Value:     "foo",
   513  						},
   514  					},
   515  				},
   516  			},
   517  		},
   518  	})
   519  
   520  	p.RefreshFn = func(info *InstanceInfo, s *InstanceState) (*InstanceState, error) {
   521  		return s, nil
   522  	}
   523  
   524  	s, err := ctx.Refresh()
   525  	if err != nil {
   526  		t.Fatalf("err: %s", err)
   527  	}
   528  
   529  	actual := strings.TrimSpace(s.String())
   530  	expected := strings.TrimSpace(testContextRefreshOutputStr)
   531  	if actual != expected {
   532  		t.Fatalf("bad:\n\n%s\n\n%s", actual, expected)
   533  	}
   534  }
   535  
   536  func TestContext2Refresh_outputPartial(t *testing.T) {
   537  	p := testProvider("aws")
   538  	m := testModule(t, "refresh-output-partial")
   539  	ctx := testContext2(t, &ContextOpts{
   540  		Module: m,
   541  		ProviderResolver: ResourceProviderResolverFixed(
   542  			map[string]ResourceProviderFactory{
   543  				"aws": testProviderFuncFixed(p),
   544  			},
   545  		),
   546  		State: &State{
   547  			Modules: []*ModuleState{
   548  				&ModuleState{
   549  					Path: rootModulePath,
   550  					Resources: map[string]*ResourceState{
   551  						"aws_instance.foo": &ResourceState{
   552  							Type: "aws_instance",
   553  							Primary: &InstanceState{
   554  								ID: "foo",
   555  							},
   556  						},
   557  					},
   558  					Outputs: map[string]*OutputState{},
   559  				},
   560  			},
   561  		},
   562  	})
   563  
   564  	p.RefreshFn = nil
   565  	p.RefreshReturn = nil
   566  
   567  	s, err := ctx.Refresh()
   568  	if err != nil {
   569  		t.Fatalf("err: %s", err)
   570  	}
   571  
   572  	actual := strings.TrimSpace(s.String())
   573  	expected := strings.TrimSpace(testContextRefreshOutputPartialStr)
   574  	if actual != expected {
   575  		t.Fatalf("bad:\n\n%s\n\n%s", actual, expected)
   576  	}
   577  }
   578  
   579  func TestContext2Refresh_stateBasic(t *testing.T) {
   580  	p := testProvider("aws")
   581  	m := testModule(t, "refresh-basic")
   582  	state := &State{
   583  		Modules: []*ModuleState{
   584  			&ModuleState{
   585  				Path: rootModulePath,
   586  				Resources: map[string]*ResourceState{
   587  					"aws_instance.web": &ResourceState{
   588  						Type: "aws_instance",
   589  						Primary: &InstanceState{
   590  							ID: "bar",
   591  						},
   592  					},
   593  				},
   594  			},
   595  		},
   596  	}
   597  	ctx := testContext2(t, &ContextOpts{
   598  		Module: m,
   599  		ProviderResolver: ResourceProviderResolverFixed(
   600  			map[string]ResourceProviderFactory{
   601  				"aws": testProviderFuncFixed(p),
   602  			},
   603  		),
   604  		State: state,
   605  	})
   606  
   607  	p.RefreshFn = nil
   608  	p.RefreshReturn = &InstanceState{
   609  		ID: "foo",
   610  	}
   611  
   612  	s, err := ctx.Refresh()
   613  	if err != nil {
   614  		t.Fatalf("err: %s", err)
   615  	}
   616  	originalMod := state.RootModule()
   617  	mod := s.RootModule()
   618  	if !p.RefreshCalled {
   619  		t.Fatal("refresh should be called")
   620  	}
   621  	if !reflect.DeepEqual(p.RefreshState, originalMod.Resources["aws_instance.web"].Primary) {
   622  		t.Fatalf(
   623  			"bad:\n\n%#v\n\n%#v",
   624  			p.RefreshState,
   625  			originalMod.Resources["aws_instance.web"].Primary)
   626  	}
   627  	if !reflect.DeepEqual(mod.Resources["aws_instance.web"].Primary, p.RefreshReturn) {
   628  		t.Fatalf("bad: %#v", mod.Resources)
   629  	}
   630  }
   631  
   632  func TestContext2Refresh_dataOrphan(t *testing.T) {
   633  	p := testProvider("null")
   634  	state := &State{
   635  		Modules: []*ModuleState{
   636  			&ModuleState{
   637  				Path: rootModulePath,
   638  				Resources: map[string]*ResourceState{
   639  					"data.null_data_source.bar": &ResourceState{
   640  						Type: "null_data_source",
   641  						Primary: &InstanceState{
   642  							ID: "foo",
   643  						},
   644  					},
   645  				},
   646  			},
   647  		},
   648  	}
   649  	ctx := testContext2(t, &ContextOpts{
   650  		ProviderResolver: ResourceProviderResolverFixed(
   651  			map[string]ResourceProviderFactory{
   652  				"null": testProviderFuncFixed(p),
   653  			},
   654  		),
   655  		State: state,
   656  	})
   657  
   658  	s, err := ctx.Refresh()
   659  	if err != nil {
   660  		t.Fatalf("err: %s", err)
   661  	}
   662  
   663  	checkStateString(t, s, `<no state>`)
   664  }
   665  
   666  func TestContext2Refresh_dataState(t *testing.T) {
   667  	p := testProvider("null")
   668  	m := testModule(t, "refresh-data-resource-basic")
   669  	state := &State{
   670  		Modules: []*ModuleState{
   671  			&ModuleState{
   672  				Path: rootModulePath,
   673  				// Intentionally no resources since data resources are
   674  				// supposed to refresh themselves even if they didn't
   675  				// already exist.
   676  				Resources: map[string]*ResourceState{},
   677  			},
   678  		},
   679  	}
   680  	ctx := testContext2(t, &ContextOpts{
   681  		Module: m,
   682  		ProviderResolver: ResourceProviderResolverFixed(
   683  			map[string]ResourceProviderFactory{
   684  				"null": testProviderFuncFixed(p),
   685  			},
   686  		),
   687  		State: state,
   688  	})
   689  
   690  	p.ReadDataDiffFn = nil
   691  	p.ReadDataDiffReturn = &InstanceDiff{
   692  		Attributes: map[string]*ResourceAttrDiff{
   693  			"inputs.#": {
   694  				Old:  "0",
   695  				New:  "1",
   696  				Type: DiffAttrInput,
   697  			},
   698  			"inputs.test": {
   699  				Old:  "",
   700  				New:  "yes",
   701  				Type: DiffAttrInput,
   702  			},
   703  			"outputs.#": {
   704  				Old:         "",
   705  				New:         "",
   706  				NewComputed: true,
   707  				Type:        DiffAttrOutput,
   708  			},
   709  		},
   710  	}
   711  
   712  	p.ReadDataApplyFn = nil
   713  	p.ReadDataApplyReturn = &InstanceState{
   714  		ID: "-",
   715  	}
   716  
   717  	s, err := ctx.Refresh()
   718  	if err != nil {
   719  		t.Fatalf("err: %s", err)
   720  	}
   721  
   722  	if !p.ReadDataDiffCalled {
   723  		t.Fatal("ReadDataDiff should have been called")
   724  	}
   725  	if !p.ReadDataApplyCalled {
   726  		t.Fatal("ReadDataApply should have been called")
   727  	}
   728  
   729  	mod := s.RootModule()
   730  	if got := mod.Resources["data.null_data_source.testing"].Primary.ID; got != "-" {
   731  		t.Fatalf("resource id is %q; want %s", got, "-")
   732  	}
   733  	if !reflect.DeepEqual(mod.Resources["data.null_data_source.testing"].Primary, p.ReadDataApplyReturn) {
   734  		t.Fatalf("bad: %#v", mod.Resources)
   735  	}
   736  }
   737  
   738  func TestContext2Refresh_dataStateRefData(t *testing.T) {
   739  	p := testProvider("null")
   740  	m := testModule(t, "refresh-data-ref-data")
   741  	state := &State{
   742  		Modules: []*ModuleState{
   743  			&ModuleState{
   744  				Path: rootModulePath,
   745  				// Intentionally no resources since data resources are
   746  				// supposed to refresh themselves even if they didn't
   747  				// already exist.
   748  				Resources: map[string]*ResourceState{},
   749  			},
   750  		},
   751  	}
   752  	ctx := testContext2(t, &ContextOpts{
   753  		Module: m,
   754  		ProviderResolver: ResourceProviderResolverFixed(
   755  			map[string]ResourceProviderFactory{
   756  				"null": testProviderFuncFixed(p),
   757  			},
   758  		),
   759  		State: state,
   760  	})
   761  
   762  	p.ReadDataDiffFn = testDataDiffFn
   763  	p.ReadDataApplyFn = testDataApplyFn
   764  
   765  	s, err := ctx.Refresh()
   766  	if err != nil {
   767  		t.Fatalf("err: %s", err)
   768  	}
   769  
   770  	actual := strings.TrimSpace(s.String())
   771  	expected := strings.TrimSpace(testTerraformRefreshDataRefDataStr)
   772  	if actual != expected {
   773  		t.Fatalf("bad:\n\n%s\n\n%s", actual, expected)
   774  	}
   775  }
   776  
   777  func TestContext2Refresh_tainted(t *testing.T) {
   778  	p := testProvider("aws")
   779  	m := testModule(t, "refresh-basic")
   780  	state := &State{
   781  		Modules: []*ModuleState{
   782  			&ModuleState{
   783  				Path: rootModulePath,
   784  				Resources: map[string]*ResourceState{
   785  					"aws_instance.web": &ResourceState{
   786  						Type: "aws_instance",
   787  						Primary: &InstanceState{
   788  							ID:      "bar",
   789  							Tainted: true,
   790  						},
   791  					},
   792  				},
   793  			},
   794  		},
   795  	}
   796  	ctx := testContext2(t, &ContextOpts{
   797  		Module: m,
   798  		ProviderResolver: ResourceProviderResolverFixed(
   799  			map[string]ResourceProviderFactory{
   800  				"aws": testProviderFuncFixed(p),
   801  			},
   802  		),
   803  		State: state,
   804  	})
   805  
   806  	p.RefreshFn = nil
   807  	p.RefreshReturn = &InstanceState{
   808  		ID:      "foo",
   809  		Tainted: true,
   810  	}
   811  
   812  	s, err := ctx.Refresh()
   813  	if err != nil {
   814  		t.Fatalf("err: %s", err)
   815  	}
   816  	if !p.RefreshCalled {
   817  		t.Fatal("refresh should be called")
   818  	}
   819  
   820  	actual := strings.TrimSpace(s.String())
   821  	expected := strings.TrimSpace(testContextRefreshTaintedStr)
   822  	if actual != expected {
   823  		t.Fatalf("bad:\n\n%s\n\n%s", actual, expected)
   824  	}
   825  }
   826  
   827  // Doing a Refresh (or any operation really, but Refresh usually
   828  // happens first) with a config with an unknown provider should result in
   829  // an error. The key bug this found was that this wasn't happening if
   830  // Providers was _empty_.
   831  func TestContext2Refresh_unknownProvider(t *testing.T) {
   832  	m := testModule(t, "refresh-unknown-provider")
   833  	p := testProvider("aws")
   834  	p.ApplyFn = testApplyFn
   835  	p.DiffFn = testDiffFn
   836  
   837  	_, err := NewContext(&ContextOpts{
   838  		Module: m,
   839  		ProviderResolver: ResourceProviderResolverFixed(
   840  			map[string]ResourceProviderFactory{},
   841  		),
   842  		Shadow: true,
   843  		State: &State{
   844  			Modules: []*ModuleState{
   845  				&ModuleState{
   846  					Path: rootModulePath,
   847  					Resources: map[string]*ResourceState{
   848  						"aws_instance.web": &ResourceState{
   849  							Type: "aws_instance",
   850  							Primary: &InstanceState{
   851  								ID: "foo",
   852  							},
   853  						},
   854  					},
   855  				},
   856  			},
   857  		},
   858  	})
   859  
   860  	if err == nil {
   861  		t.Fatal("successfully created context; want error")
   862  	}
   863  
   864  	if !strings.Contains(err.Error(), "Can't satisfy provider requirements") {
   865  		t.Fatalf("wrong error: %s", err)
   866  	}
   867  }
   868  
   869  func TestContext2Refresh_vars(t *testing.T) {
   870  	p := testProvider("aws")
   871  	m := testModule(t, "refresh-vars")
   872  	ctx := testContext2(t, &ContextOpts{
   873  		Module: m,
   874  		ProviderResolver: ResourceProviderResolverFixed(
   875  			map[string]ResourceProviderFactory{
   876  				"aws": testProviderFuncFixed(p),
   877  			},
   878  		),
   879  		State: &State{
   880  
   881  			Modules: []*ModuleState{
   882  				&ModuleState{
   883  					Path: rootModulePath,
   884  					Resources: map[string]*ResourceState{
   885  						"aws_instance.web": &ResourceState{
   886  							Type: "aws_instance",
   887  							Primary: &InstanceState{
   888  								ID: "foo",
   889  							},
   890  						},
   891  					},
   892  				},
   893  			},
   894  		},
   895  	})
   896  
   897  	p.RefreshFn = nil
   898  	p.RefreshReturn = &InstanceState{
   899  		ID: "foo",
   900  	}
   901  
   902  	s, err := ctx.Refresh()
   903  	if err != nil {
   904  		t.Fatalf("err: %s", err)
   905  	}
   906  	mod := s.RootModule()
   907  	if !p.RefreshCalled {
   908  		t.Fatal("refresh should be called")
   909  	}
   910  	if p.RefreshState.ID != "foo" {
   911  		t.Fatalf("bad: %#v", p.RefreshState)
   912  	}
   913  	if !reflect.DeepEqual(mod.Resources["aws_instance.web"].Primary, p.RefreshReturn) {
   914  		t.Fatalf("bad: %#v", mod.Resources["aws_instance.web"])
   915  	}
   916  
   917  	for _, r := range mod.Resources {
   918  		if r.Type == "" {
   919  			t.Fatalf("no type: %#v", r)
   920  		}
   921  	}
   922  }
   923  
   924  func TestContext2Refresh_orphanModule(t *testing.T) {
   925  	p := testProvider("aws")
   926  	m := testModule(t, "refresh-module-orphan")
   927  
   928  	// Create a custom refresh function to track the order they were visited
   929  	var order []string
   930  	var orderLock sync.Mutex
   931  	p.RefreshFn = func(
   932  		info *InstanceInfo,
   933  		is *InstanceState) (*InstanceState, error) {
   934  		orderLock.Lock()
   935  		defer orderLock.Unlock()
   936  
   937  		order = append(order, is.ID)
   938  		return is, nil
   939  	}
   940  
   941  	state := &State{
   942  		Modules: []*ModuleState{
   943  			&ModuleState{
   944  				Path: rootModulePath,
   945  				Resources: map[string]*ResourceState{
   946  					"aws_instance.foo": &ResourceState{
   947  						Type: "aws_instance",
   948  						Primary: &InstanceState{
   949  							ID: "i-abc123",
   950  							Attributes: map[string]string{
   951  								"childid":      "i-bcd234",
   952  								"grandchildid": "i-cde345",
   953  							},
   954  						},
   955  						Dependencies: []string{
   956  							"module.child",
   957  							"module.child",
   958  						},
   959  					},
   960  				},
   961  			},
   962  			&ModuleState{
   963  				Path: append(rootModulePath, "child"),
   964  				Resources: map[string]*ResourceState{
   965  					"aws_instance.bar": &ResourceState{
   966  						Type: "aws_instance",
   967  						Primary: &InstanceState{
   968  							ID: "i-bcd234",
   969  							Attributes: map[string]string{
   970  								"grandchildid": "i-cde345",
   971  							},
   972  						},
   973  						Dependencies: []string{
   974  							"module.grandchild",
   975  						},
   976  					},
   977  				},
   978  				Outputs: map[string]*OutputState{
   979  					"id": &OutputState{
   980  						Value: "i-bcd234",
   981  						Type:  "string",
   982  					},
   983  					"grandchild_id": &OutputState{
   984  						Value: "i-cde345",
   985  						Type:  "string",
   986  					},
   987  				},
   988  			},
   989  			&ModuleState{
   990  				Path: append(rootModulePath, "child", "grandchild"),
   991  				Resources: map[string]*ResourceState{
   992  					"aws_instance.baz": &ResourceState{
   993  						Type: "aws_instance",
   994  						Primary: &InstanceState{
   995  							ID: "i-cde345",
   996  						},
   997  					},
   998  				},
   999  				Outputs: map[string]*OutputState{
  1000  					"id": &OutputState{
  1001  						Value: "i-cde345",
  1002  						Type:  "string",
  1003  					},
  1004  				},
  1005  			},
  1006  		},
  1007  	}
  1008  	ctx := testContext2(t, &ContextOpts{
  1009  		Module: m,
  1010  		ProviderResolver: ResourceProviderResolverFixed(
  1011  			map[string]ResourceProviderFactory{
  1012  				"aws": testProviderFuncFixed(p),
  1013  			},
  1014  		),
  1015  		State: state,
  1016  	})
  1017  
  1018  	testCheckDeadlock(t, func() {
  1019  		_, err := ctx.Refresh()
  1020  		if err != nil {
  1021  			t.Fatalf("err: %s", err)
  1022  		}
  1023  
  1024  		// TODO: handle order properly for orphaned modules / resources
  1025  		// expected := []string{"i-abc123", "i-bcd234", "i-cde345"}
  1026  		// if !reflect.DeepEqual(order, expected) {
  1027  		// 	t.Fatalf("expected: %#v, got: %#v", expected, order)
  1028  		// }
  1029  	})
  1030  }
  1031  
  1032  func TestContext2Validate(t *testing.T) {
  1033  	p := testProvider("aws")
  1034  	m := testModule(t, "validate-good")
  1035  	c := testContext2(t, &ContextOpts{
  1036  		Module: m,
  1037  		ProviderResolver: ResourceProviderResolverFixed(
  1038  			map[string]ResourceProviderFactory{
  1039  				"aws": testProviderFuncFixed(p),
  1040  			},
  1041  		),
  1042  	})
  1043  
  1044  	w, e := c.Validate()
  1045  	if len(w) > 0 {
  1046  		t.Fatalf("bad: %#v", w)
  1047  	}
  1048  	if len(e) > 0 {
  1049  		t.Fatalf("bad: %s", e)
  1050  	}
  1051  }