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

     1  package terraform
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/zclconf/go-cty/cty"
    10  
    11  	"github.com/hashicorp/terraform-plugin-sdk/internal/addrs"
    12  	"github.com/hashicorp/terraform-plugin-sdk/internal/configs/configschema"
    13  	"github.com/hashicorp/terraform-plugin-sdk/internal/providers"
    14  	"github.com/hashicorp/terraform-plugin-sdk/internal/provisioners"
    15  	"github.com/hashicorp/terraform-plugin-sdk/internal/states"
    16  	"github.com/hashicorp/terraform-plugin-sdk/internal/tfdiags"
    17  )
    18  
    19  func TestContext2Validate_badCount(t *testing.T) {
    20  	p := testProvider("aws")
    21  	p.GetSchemaReturn = &ProviderSchema{
    22  		ResourceTypes: map[string]*configschema.Block{
    23  			"aws_instance": {
    24  				Attributes: map[string]*configschema.Attribute{},
    25  			},
    26  		},
    27  	}
    28  
    29  	m := testModule(t, "validate-bad-count")
    30  	c := testContext2(t, &ContextOpts{
    31  		Config: m,
    32  		ProviderResolver: providers.ResolverFixed(
    33  			map[string]providers.Factory{
    34  				"aws": testProviderFuncFixed(p),
    35  			},
    36  		),
    37  	})
    38  
    39  	diags := c.Validate()
    40  	if !diags.HasErrors() {
    41  		t.Fatalf("succeeded; want error")
    42  	}
    43  }
    44  
    45  func TestContext2Validate_badVar(t *testing.T) {
    46  	p := testProvider("aws")
    47  	p.GetSchemaReturn = &ProviderSchema{
    48  		ResourceTypes: map[string]*configschema.Block{
    49  			"aws_instance": {
    50  				Attributes: map[string]*configschema.Attribute{
    51  					"foo": {Type: cty.String, Optional: true},
    52  					"num": {Type: cty.String, Optional: true},
    53  				},
    54  			},
    55  		},
    56  	}
    57  
    58  	m := testModule(t, "validate-bad-var")
    59  	c := testContext2(t, &ContextOpts{
    60  		Config: m,
    61  		ProviderResolver: providers.ResolverFixed(
    62  			map[string]providers.Factory{
    63  				"aws": testProviderFuncFixed(p),
    64  			},
    65  		),
    66  	})
    67  
    68  	diags := c.Validate()
    69  	if !diags.HasErrors() {
    70  		t.Fatalf("succeeded; want error")
    71  	}
    72  }
    73  
    74  func TestContext2Validate_varMapOverrideOld(t *testing.T) {
    75  	m := testModule(t, "validate-module-pc-vars")
    76  	p := testProvider("aws")
    77  	p.GetSchemaReturn = &ProviderSchema{
    78  		Provider: &configschema.Block{
    79  			Attributes: map[string]*configschema.Attribute{
    80  				"foo": {Type: cty.String, Optional: true},
    81  			},
    82  		},
    83  		ResourceTypes: map[string]*configschema.Block{
    84  			"aws_instance": {
    85  				Attributes: map[string]*configschema.Attribute{},
    86  			},
    87  		},
    88  	}
    89  
    90  	c := testContext2(t, &ContextOpts{
    91  		Config: m,
    92  		ProviderResolver: providers.ResolverFixed(
    93  			map[string]providers.Factory{
    94  				"aws": testProviderFuncFixed(p),
    95  			},
    96  		),
    97  		Variables: InputValues{
    98  			"foo.foo": &InputValue{
    99  				Value:      cty.StringVal("bar"),
   100  				SourceType: ValueFromCaller,
   101  			},
   102  		},
   103  	})
   104  
   105  	diags := c.Validate()
   106  	if !diags.HasErrors() {
   107  		t.Fatalf("succeeded; want error")
   108  	}
   109  }
   110  
   111  func TestContext2Validate_varNoDefaultExplicitType(t *testing.T) {
   112  	m := testModule(t, "validate-var-no-default-explicit-type")
   113  	c := testContext2(t, &ContextOpts{
   114  		Config: m,
   115  	})
   116  
   117  	diags := c.Validate()
   118  	if !diags.HasErrors() {
   119  		t.Fatalf("succeeded; want error")
   120  	}
   121  }
   122  
   123  func TestContext2Validate_computedVar(t *testing.T) {
   124  	p := testProvider("aws")
   125  	p.GetSchemaReturn = &ProviderSchema{
   126  		Provider: &configschema.Block{
   127  			Attributes: map[string]*configschema.Attribute{
   128  				"value": {Type: cty.String, Optional: true},
   129  			},
   130  		},
   131  		ResourceTypes: map[string]*configschema.Block{
   132  			"aws_instance": {
   133  				Attributes: map[string]*configschema.Attribute{},
   134  			},
   135  		},
   136  	}
   137  	pt := testProvider("test")
   138  	pt.GetSchemaReturn = &ProviderSchema{
   139  		ResourceTypes: map[string]*configschema.Block{
   140  			"test_instance": {
   141  				Attributes: map[string]*configschema.Attribute{
   142  					"value": {Type: cty.String, Optional: true},
   143  				},
   144  			},
   145  		},
   146  	}
   147  
   148  	m := testModule(t, "validate-computed-var")
   149  	c := testContext2(t, &ContextOpts{
   150  		Config: m,
   151  		ProviderResolver: providers.ResolverFixed(
   152  			map[string]providers.Factory{
   153  				"aws":  testProviderFuncFixed(p),
   154  				"test": testProviderFuncFixed(pt),
   155  			},
   156  		),
   157  	})
   158  
   159  	p.ValidateFn = func(c *ResourceConfig) ([]string, []error) {
   160  		if !c.IsComputed("value") {
   161  			return nil, []error{fmt.Errorf("value isn't computed")}
   162  		}
   163  
   164  		return nil, c.CheckSet([]string{"value"})
   165  	}
   166  
   167  	p.ConfigureFn = func(c *ResourceConfig) error {
   168  		return fmt.Errorf("Configure should not be called for provider")
   169  	}
   170  
   171  	diags := c.Validate()
   172  	if diags.HasErrors() {
   173  		t.Fatalf("unexpected error: %s", diags.Err())
   174  	}
   175  }
   176  
   177  func TestContext2Validate_computedInFunction(t *testing.T) {
   178  	p := testProvider("aws")
   179  	p.GetSchemaReturn = &ProviderSchema{
   180  		ResourceTypes: map[string]*configschema.Block{
   181  			"aws_instance": {
   182  				Attributes: map[string]*configschema.Attribute{
   183  					"attr": {Type: cty.Number, Optional: true},
   184  				},
   185  			},
   186  		},
   187  		DataSources: map[string]*configschema.Block{
   188  			"aws_data_source": {
   189  				Attributes: map[string]*configschema.Attribute{
   190  					"optional_attr": {Type: cty.String, Optional: true},
   191  					"computed":      {Type: cty.String, Computed: true},
   192  				},
   193  			},
   194  		},
   195  	}
   196  
   197  	m := testModule(t, "validate-computed-in-function")
   198  	c := testContext2(t, &ContextOpts{
   199  		Config: m,
   200  		ProviderResolver: providers.ResolverFixed(
   201  			map[string]providers.Factory{
   202  				"aws": testProviderFuncFixed(p),
   203  			},
   204  		),
   205  	})
   206  
   207  	diags := c.Validate()
   208  	if diags.HasErrors() {
   209  		t.Fatalf("unexpected error: %s", diags.Err())
   210  	}
   211  }
   212  
   213  // Test that validate allows through computed counts. We do this and allow
   214  // them to fail during "plan" since we can't know if the computed values
   215  // can be realized during a plan.
   216  func TestContext2Validate_countComputed(t *testing.T) {
   217  	p := testProvider("aws")
   218  	p.GetSchemaReturn = &ProviderSchema{
   219  		ResourceTypes: map[string]*configschema.Block{
   220  			"aws_instance": {
   221  				Attributes: map[string]*configschema.Attribute{},
   222  			},
   223  		},
   224  		DataSources: map[string]*configschema.Block{
   225  			"aws_data_source": {
   226  				Attributes: map[string]*configschema.Attribute{
   227  					"compute": {Type: cty.String, Optional: true},
   228  					"value":   {Type: cty.String, Computed: true},
   229  				},
   230  			},
   231  		},
   232  	}
   233  
   234  	m := testModule(t, "validate-count-computed")
   235  	c := testContext2(t, &ContextOpts{
   236  		Config: m,
   237  		ProviderResolver: providers.ResolverFixed(
   238  			map[string]providers.Factory{
   239  				"aws": testProviderFuncFixed(p),
   240  			},
   241  		),
   242  	})
   243  
   244  	diags := c.Validate()
   245  	if diags.HasErrors() {
   246  		t.Fatalf("unexpected error: %s", diags.Err())
   247  	}
   248  }
   249  
   250  func TestContext2Validate_countNegative(t *testing.T) {
   251  	p := testProvider("aws")
   252  	p.GetSchemaReturn = &ProviderSchema{
   253  		ResourceTypes: map[string]*configschema.Block{
   254  			"aws_instance": {
   255  				Attributes: map[string]*configschema.Attribute{},
   256  			},
   257  		},
   258  	}
   259  
   260  	m := testModule(t, "validate-count-negative")
   261  	c := testContext2(t, &ContextOpts{
   262  		Config: m,
   263  		ProviderResolver: providers.ResolverFixed(
   264  			map[string]providers.Factory{
   265  				"aws": testProviderFuncFixed(p),
   266  			},
   267  		),
   268  	})
   269  
   270  	diags := c.Validate()
   271  	if !diags.HasErrors() {
   272  		t.Fatalf("succeeded; want error")
   273  	}
   274  }
   275  
   276  func TestContext2Validate_countVariable(t *testing.T) {
   277  	p := testProvider("aws")
   278  	p.GetSchemaReturn = &ProviderSchema{
   279  		ResourceTypes: map[string]*configschema.Block{
   280  			"aws_instance": {
   281  				Attributes: map[string]*configschema.Attribute{
   282  					"foo": {Type: cty.String, Optional: true},
   283  				},
   284  			},
   285  		},
   286  	}
   287  
   288  	m := testModule(t, "apply-count-variable")
   289  	c := testContext2(t, &ContextOpts{
   290  		Config: m,
   291  		ProviderResolver: providers.ResolverFixed(
   292  			map[string]providers.Factory{
   293  				"aws": testProviderFuncFixed(p),
   294  			},
   295  		),
   296  	})
   297  
   298  	diags := c.Validate()
   299  	if diags.HasErrors() {
   300  		t.Fatalf("unexpected error: %s", diags.Err())
   301  	}
   302  }
   303  
   304  func TestContext2Validate_countVariableNoDefault(t *testing.T) {
   305  	p := testProvider("aws")
   306  	m := testModule(t, "validate-count-variable")
   307  	p.GetSchemaReturn = &ProviderSchema{
   308  		ResourceTypes: map[string]*configschema.Block{
   309  			"aws_instance": {
   310  				Attributes: map[string]*configschema.Attribute{
   311  					"foo": {Type: cty.String, Optional: true},
   312  				},
   313  			},
   314  		},
   315  	}
   316  
   317  	c := testContext2(t, &ContextOpts{
   318  		Config: m,
   319  		ProviderResolver: providers.ResolverFixed(
   320  			map[string]providers.Factory{
   321  				"aws": testProviderFuncFixed(p),
   322  			},
   323  		),
   324  	})
   325  
   326  	diags := c.Validate()
   327  	if !diags.HasErrors() {
   328  		t.Fatalf("succeeded; want error")
   329  	}
   330  }
   331  
   332  func TestContext2Validate_moduleBadOutput(t *testing.T) {
   333  	p := testProvider("aws")
   334  	p.GetSchemaReturn = &ProviderSchema{
   335  		ResourceTypes: map[string]*configschema.Block{
   336  			"aws_instance": {
   337  				Attributes: map[string]*configschema.Attribute{
   338  					"foo": {Type: cty.String, Optional: true},
   339  				},
   340  			},
   341  		},
   342  	}
   343  
   344  	m := testModule(t, "validate-bad-module-output")
   345  	c := testContext2(t, &ContextOpts{
   346  		Config: m,
   347  		ProviderResolver: providers.ResolverFixed(
   348  			map[string]providers.Factory{
   349  				"aws": testProviderFuncFixed(p),
   350  			},
   351  		),
   352  	})
   353  
   354  	diags := c.Validate()
   355  	if !diags.HasErrors() {
   356  		t.Fatalf("succeeded; want error")
   357  	}
   358  }
   359  
   360  func TestContext2Validate_moduleGood(t *testing.T) {
   361  	p := testProvider("aws")
   362  	p.GetSchemaReturn = &ProviderSchema{
   363  		ResourceTypes: map[string]*configschema.Block{
   364  			"aws_instance": {
   365  				Attributes: map[string]*configschema.Attribute{
   366  					"foo": {Type: cty.String, Optional: true},
   367  				},
   368  			},
   369  		},
   370  	}
   371  
   372  	m := testModule(t, "validate-good-module")
   373  	c := testContext2(t, &ContextOpts{
   374  		Config: m,
   375  		ProviderResolver: providers.ResolverFixed(
   376  			map[string]providers.Factory{
   377  				"aws": testProviderFuncFixed(p),
   378  			},
   379  		),
   380  	})
   381  
   382  	diags := c.Validate()
   383  	if diags.HasErrors() {
   384  		t.Fatalf("unexpected error: %s", diags.Err())
   385  	}
   386  }
   387  
   388  func TestContext2Validate_moduleBadResource(t *testing.T) {
   389  	m := testModule(t, "validate-module-bad-rc")
   390  	p := testProvider("aws")
   391  	p.GetSchemaReturn = &ProviderSchema{
   392  		ResourceTypes: map[string]*configschema.Block{
   393  			"aws_instance": {
   394  				Attributes: map[string]*configschema.Attribute{},
   395  			},
   396  		},
   397  	}
   398  
   399  	c := testContext2(t, &ContextOpts{
   400  		Config: m,
   401  		ProviderResolver: providers.ResolverFixed(
   402  			map[string]providers.Factory{
   403  				"aws": testProviderFuncFixed(p),
   404  			},
   405  		),
   406  	})
   407  
   408  	p.ValidateResourceTypeConfigResponse = providers.ValidateResourceTypeConfigResponse{
   409  		Diagnostics: tfdiags.Diagnostics{}.Append(fmt.Errorf("bad")),
   410  	}
   411  
   412  	diags := c.Validate()
   413  	if !diags.HasErrors() {
   414  		t.Fatalf("succeeded; want error")
   415  	}
   416  }
   417  
   418  func TestContext2Validate_moduleDepsShouldNotCycle(t *testing.T) {
   419  	m := testModule(t, "validate-module-deps-cycle")
   420  	p := testProvider("aws")
   421  	p.GetSchemaReturn = &ProviderSchema{
   422  		ResourceTypes: map[string]*configschema.Block{
   423  			"aws_instance": {
   424  				Attributes: map[string]*configschema.Attribute{
   425  					"id": {Type: cty.String, Optional: true},
   426  				},
   427  			},
   428  		},
   429  	}
   430  
   431  	ctx := testContext2(t, &ContextOpts{
   432  		Config: m,
   433  		ProviderResolver: providers.ResolverFixed(
   434  			map[string]providers.Factory{
   435  				"aws": testProviderFuncFixed(p),
   436  			},
   437  		),
   438  	})
   439  
   440  	diags := ctx.Validate()
   441  	if diags.HasErrors() {
   442  		t.Fatalf("unexpected error: %s", diags.Err())
   443  	}
   444  }
   445  
   446  func TestContext2Validate_moduleProviderVar(t *testing.T) {
   447  	m := testModule(t, "validate-module-pc-vars")
   448  	p := testProvider("aws")
   449  	p.GetSchemaReturn = &ProviderSchema{
   450  		Provider: &configschema.Block{
   451  			Attributes: map[string]*configschema.Attribute{
   452  				"foo": {Type: cty.String, Optional: true},
   453  			},
   454  		},
   455  		ResourceTypes: map[string]*configschema.Block{
   456  			"aws_instance": {
   457  				Attributes: map[string]*configschema.Attribute{
   458  					"foo": {Type: cty.String, Optional: true},
   459  				},
   460  			},
   461  		},
   462  	}
   463  
   464  	c := testContext2(t, &ContextOpts{
   465  		Config: m,
   466  		ProviderResolver: providers.ResolverFixed(
   467  			map[string]providers.Factory{
   468  				"aws": testProviderFuncFixed(p),
   469  			},
   470  		),
   471  		Variables: InputValues{
   472  			"provider_var": &InputValue{
   473  				Value:      cty.StringVal("bar"),
   474  				SourceType: ValueFromCaller,
   475  			},
   476  		},
   477  	})
   478  
   479  	p.ValidateFn = func(c *ResourceConfig) ([]string, []error) {
   480  		return nil, c.CheckSet([]string{"foo"})
   481  	}
   482  
   483  	diags := c.Validate()
   484  	if diags.HasErrors() {
   485  		t.Fatalf("unexpected error: %s", diags.Err())
   486  	}
   487  }
   488  
   489  func TestContext2Validate_moduleProviderInheritUnused(t *testing.T) {
   490  	m := testModule(t, "validate-module-pc-inherit-unused")
   491  	p := testProvider("aws")
   492  	p.GetSchemaReturn = &ProviderSchema{
   493  		Provider: &configschema.Block{
   494  			Attributes: map[string]*configschema.Attribute{
   495  				"foo": {Type: cty.String, Optional: true},
   496  			},
   497  		},
   498  		ResourceTypes: map[string]*configschema.Block{
   499  			"aws_instance": {
   500  				Attributes: map[string]*configschema.Attribute{
   501  					"foo": {Type: cty.String, Optional: true},
   502  				},
   503  			},
   504  		},
   505  	}
   506  
   507  	c := testContext2(t, &ContextOpts{
   508  		Config: m,
   509  		ProviderResolver: providers.ResolverFixed(
   510  			map[string]providers.Factory{
   511  				"aws": testProviderFuncFixed(p),
   512  			},
   513  		),
   514  	})
   515  
   516  	p.ValidateFn = func(c *ResourceConfig) ([]string, []error) {
   517  		return nil, c.CheckSet([]string{"foo"})
   518  	}
   519  
   520  	diags := c.Validate()
   521  	if diags.HasErrors() {
   522  		t.Fatalf("unexpected error: %s", diags.Err())
   523  	}
   524  }
   525  
   526  func TestContext2Validate_orphans(t *testing.T) {
   527  	p := testProvider("aws")
   528  	p.GetSchemaReturn = &ProviderSchema{
   529  		ResourceTypes: map[string]*configschema.Block{
   530  			"aws_instance": {
   531  				Attributes: map[string]*configschema.Attribute{
   532  					"foo": {Type: cty.String, Optional: true},
   533  					"num": {Type: cty.String, Optional: true},
   534  				},
   535  			},
   536  		},
   537  	}
   538  
   539  	m := testModule(t, "validate-good")
   540  	state := MustShimLegacyState(&State{
   541  		Modules: []*ModuleState{
   542  			{
   543  				Path: rootModulePath,
   544  				Resources: map[string]*ResourceState{
   545  					"aws_instance.web": {
   546  						Type: "aws_instance",
   547  						Primary: &InstanceState{
   548  							ID: "bar",
   549  						},
   550  					},
   551  				},
   552  			},
   553  		},
   554  	})
   555  	c := testContext2(t, &ContextOpts{
   556  		Config: m,
   557  		ProviderResolver: providers.ResolverFixed(
   558  			map[string]providers.Factory{
   559  				"aws": testProviderFuncFixed(p),
   560  			},
   561  		),
   562  		State: state,
   563  	})
   564  
   565  	p.ValidateResourceTypeConfigFn = func(req providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse {
   566  		var diags tfdiags.Diagnostics
   567  		if req.Config.GetAttr("foo").IsNull() {
   568  			diags.Append(errors.New("foo is not set"))
   569  		}
   570  		return providers.ValidateResourceTypeConfigResponse{
   571  			Diagnostics: diags,
   572  		}
   573  	}
   574  
   575  	diags := c.Validate()
   576  	if diags.HasErrors() {
   577  		t.Fatalf("unexpected error: %s", diags.Err())
   578  	}
   579  }
   580  
   581  func TestContext2Validate_providerConfig_bad(t *testing.T) {
   582  	m := testModule(t, "validate-bad-pc")
   583  	p := testProvider("aws")
   584  	p.GetSchemaReturn = &ProviderSchema{
   585  		Provider: &configschema.Block{
   586  			Attributes: map[string]*configschema.Attribute{
   587  				"foo": {Type: cty.String, Optional: true},
   588  			},
   589  		},
   590  		ResourceTypes: map[string]*configschema.Block{
   591  			"aws_instance": {
   592  				Attributes: map[string]*configschema.Attribute{},
   593  			},
   594  		},
   595  	}
   596  
   597  	c := testContext2(t, &ContextOpts{
   598  		Config: m,
   599  		ProviderResolver: providers.ResolverFixed(
   600  			map[string]providers.Factory{
   601  				"aws": testProviderFuncFixed(p),
   602  			},
   603  		),
   604  	})
   605  
   606  	p.PrepareProviderConfigResponse = providers.PrepareProviderConfigResponse{
   607  		Diagnostics: tfdiags.Diagnostics{}.Append(fmt.Errorf("bad")),
   608  	}
   609  
   610  	diags := c.Validate()
   611  	if len(diags) != 1 {
   612  		t.Fatalf("wrong number of diagnostics %d; want %d", len(diags), 1)
   613  	}
   614  	if !strings.Contains(diags.Err().Error(), "bad") {
   615  		t.Fatalf("bad: %s", diags.Err().Error())
   616  	}
   617  }
   618  
   619  func TestContext2Validate_providerConfig_badEmpty(t *testing.T) {
   620  	m := testModule(t, "validate-bad-pc-empty")
   621  	p := testProvider("aws")
   622  	p.GetSchemaReturn = &ProviderSchema{
   623  		Provider: &configschema.Block{
   624  			Attributes: map[string]*configschema.Attribute{
   625  				"foo": {Type: cty.String, Optional: true},
   626  			},
   627  		},
   628  		ResourceTypes: map[string]*configschema.Block{
   629  			"aws_instance": {
   630  				Attributes: map[string]*configschema.Attribute{},
   631  			},
   632  		},
   633  	}
   634  
   635  	c := testContext2(t, &ContextOpts{
   636  		Config: m,
   637  		ProviderResolver: providers.ResolverFixed(
   638  			map[string]providers.Factory{
   639  				"aws": testProviderFuncFixed(p),
   640  			},
   641  		),
   642  	})
   643  
   644  	p.PrepareProviderConfigResponse = providers.PrepareProviderConfigResponse{
   645  		Diagnostics: tfdiags.Diagnostics{}.Append(fmt.Errorf("bad")),
   646  	}
   647  
   648  	diags := c.Validate()
   649  	if !diags.HasErrors() {
   650  		t.Fatalf("succeeded; want error")
   651  	}
   652  }
   653  
   654  func TestContext2Validate_providerConfig_good(t *testing.T) {
   655  	m := testModule(t, "validate-bad-pc")
   656  	p := testProvider("aws")
   657  	p.GetSchemaReturn = &ProviderSchema{
   658  		Provider: &configschema.Block{
   659  			Attributes: map[string]*configschema.Attribute{
   660  				"foo": {Type: cty.String, Optional: true},
   661  			},
   662  		},
   663  		ResourceTypes: map[string]*configschema.Block{
   664  			"aws_instance": {
   665  				Attributes: map[string]*configschema.Attribute{},
   666  			},
   667  		},
   668  	}
   669  
   670  	c := testContext2(t, &ContextOpts{
   671  		Config: m,
   672  		ProviderResolver: providers.ResolverFixed(
   673  			map[string]providers.Factory{
   674  				"aws": testProviderFuncFixed(p),
   675  			},
   676  		),
   677  	})
   678  
   679  	diags := c.Validate()
   680  	if diags.HasErrors() {
   681  		t.Fatalf("unexpected error: %s", diags.Err())
   682  	}
   683  }
   684  
   685  func TestContext2Validate_provisionerConfig_bad(t *testing.T) {
   686  	m := testModule(t, "validate-bad-prov-conf")
   687  	p := testProvider("aws")
   688  	p.GetSchemaReturn = &ProviderSchema{
   689  		ResourceTypes: map[string]*configschema.Block{
   690  			"aws_instance": {
   691  				Attributes: map[string]*configschema.Attribute{
   692  					"foo": {Type: cty.String, Optional: true},
   693  				},
   694  			},
   695  		},
   696  	}
   697  
   698  	pr := simpleMockProvisioner()
   699  
   700  	c := testContext2(t, &ContextOpts{
   701  		Config: m,
   702  		ProviderResolver: providers.ResolverFixed(
   703  			map[string]providers.Factory{
   704  				"aws": testProviderFuncFixed(p),
   705  			},
   706  		),
   707  		Provisioners: map[string]ProvisionerFactory{
   708  			"shell": testProvisionerFuncFixed(pr),
   709  		},
   710  	})
   711  
   712  	p.PrepareProviderConfigResponse = providers.PrepareProviderConfigResponse{
   713  		Diagnostics: tfdiags.Diagnostics{}.Append(fmt.Errorf("bad")),
   714  	}
   715  
   716  	diags := c.Validate()
   717  	if !diags.HasErrors() {
   718  		t.Fatalf("succeeded; want error")
   719  	}
   720  }
   721  
   722  func TestContext2Validate_badResourceConnection(t *testing.T) {
   723  	m := testModule(t, "validate-bad-resource-connection")
   724  	p := testProvider("aws")
   725  	p.GetSchemaReturn = &ProviderSchema{
   726  		ResourceTypes: map[string]*configschema.Block{
   727  			"aws_instance": {
   728  				Attributes: map[string]*configschema.Attribute{
   729  					"foo": {Type: cty.String, Optional: true},
   730  				},
   731  			},
   732  		},
   733  	}
   734  
   735  	pr := simpleMockProvisioner()
   736  
   737  	c := testContext2(t, &ContextOpts{
   738  		Config: m,
   739  		ProviderResolver: providers.ResolverFixed(
   740  			map[string]providers.Factory{
   741  				"aws": testProviderFuncFixed(p),
   742  			},
   743  		),
   744  		Provisioners: map[string]ProvisionerFactory{
   745  			"shell": testProvisionerFuncFixed(pr),
   746  		},
   747  	})
   748  
   749  	diags := c.Validate()
   750  	t.Log(diags.Err())
   751  	if !diags.HasErrors() {
   752  		t.Fatalf("succeeded; want error")
   753  	}
   754  }
   755  
   756  func TestContext2Validate_badProvisionerConnection(t *testing.T) {
   757  	m := testModule(t, "validate-bad-prov-connection")
   758  	p := testProvider("aws")
   759  	p.GetSchemaReturn = &ProviderSchema{
   760  		ResourceTypes: map[string]*configschema.Block{
   761  			"aws_instance": {
   762  				Attributes: map[string]*configschema.Attribute{
   763  					"foo": {Type: cty.String, Optional: true},
   764  				},
   765  			},
   766  		},
   767  	}
   768  
   769  	pr := simpleMockProvisioner()
   770  
   771  	c := testContext2(t, &ContextOpts{
   772  		Config: m,
   773  		ProviderResolver: providers.ResolverFixed(
   774  			map[string]providers.Factory{
   775  				"aws": testProviderFuncFixed(p),
   776  			},
   777  		),
   778  		Provisioners: map[string]ProvisionerFactory{
   779  			"shell": testProvisionerFuncFixed(pr),
   780  		},
   781  	})
   782  
   783  	diags := c.Validate()
   784  	t.Log(diags.Err())
   785  	if !diags.HasErrors() {
   786  		t.Fatalf("succeeded; want error")
   787  	}
   788  }
   789  
   790  func TestContext2Validate_provisionerConfig_good(t *testing.T) {
   791  	m := testModule(t, "validate-bad-prov-conf")
   792  	p := testProvider("aws")
   793  	p.GetSchemaReturn = &ProviderSchema{
   794  		Provider: &configschema.Block{
   795  			Attributes: map[string]*configschema.Attribute{
   796  				"foo": {Type: cty.String, Optional: true},
   797  			},
   798  		},
   799  		ResourceTypes: map[string]*configschema.Block{
   800  			"aws_instance": {
   801  				Attributes: map[string]*configschema.Attribute{
   802  					"foo": {Type: cty.String, Optional: true},
   803  				},
   804  			},
   805  		},
   806  	}
   807  
   808  	pr := simpleMockProvisioner()
   809  	pr.ValidateProvisionerConfigFn = func(req provisioners.ValidateProvisionerConfigRequest) provisioners.ValidateProvisionerConfigResponse {
   810  		var diags tfdiags.Diagnostics
   811  		if req.Config.GetAttr("test_string").IsNull() {
   812  			diags.Append(errors.New("test_string is not set"))
   813  		}
   814  		return provisioners.ValidateProvisionerConfigResponse{
   815  			Diagnostics: diags,
   816  		}
   817  	}
   818  
   819  	c := testContext2(t, &ContextOpts{
   820  		Config: m,
   821  		ProviderResolver: providers.ResolverFixed(
   822  			map[string]providers.Factory{
   823  				"aws": testProviderFuncFixed(p),
   824  			},
   825  		),
   826  		Provisioners: map[string]ProvisionerFactory{
   827  			"shell": testProvisionerFuncFixed(pr),
   828  		},
   829  	})
   830  
   831  	diags := c.Validate()
   832  	if diags.HasErrors() {
   833  		t.Fatalf("unexpected error: %s", diags.Err())
   834  	}
   835  }
   836  
   837  func TestContext2Validate_requiredVar(t *testing.T) {
   838  	m := testModule(t, "validate-required-var")
   839  	p := testProvider("aws")
   840  	p.GetSchemaReturn = &ProviderSchema{
   841  		ResourceTypes: map[string]*configschema.Block{
   842  			"aws_instance": {
   843  				Attributes: map[string]*configschema.Attribute{
   844  					"ami": {Type: cty.String, Optional: true},
   845  				},
   846  			},
   847  		},
   848  	}
   849  
   850  	c := testContext2(t, &ContextOpts{
   851  		Config: m,
   852  		ProviderResolver: providers.ResolverFixed(
   853  			map[string]providers.Factory{
   854  				"aws": testProviderFuncFixed(p),
   855  			},
   856  		),
   857  	})
   858  
   859  	diags := c.Validate()
   860  	if !diags.HasErrors() {
   861  		t.Fatalf("succeeded; want error")
   862  	}
   863  }
   864  
   865  func TestContext2Validate_resourceConfig_bad(t *testing.T) {
   866  	m := testModule(t, "validate-bad-rc")
   867  	p := testProvider("aws")
   868  	p.GetSchemaReturn = &ProviderSchema{
   869  		ResourceTypes: map[string]*configschema.Block{
   870  			"aws_instance": {
   871  				Attributes: map[string]*configschema.Attribute{
   872  					"foo": {Type: cty.String, Optional: true},
   873  				},
   874  			},
   875  		},
   876  	}
   877  
   878  	c := testContext2(t, &ContextOpts{
   879  		Config: m,
   880  		ProviderResolver: providers.ResolverFixed(
   881  			map[string]providers.Factory{
   882  				"aws": testProviderFuncFixed(p),
   883  			},
   884  		),
   885  	})
   886  
   887  	p.ValidateResourceTypeConfigResponse = providers.ValidateResourceTypeConfigResponse{
   888  		Diagnostics: tfdiags.Diagnostics{}.Append(fmt.Errorf("bad")),
   889  	}
   890  
   891  	diags := c.Validate()
   892  	if !diags.HasErrors() {
   893  		t.Fatalf("succeeded; want error")
   894  	}
   895  }
   896  
   897  func TestContext2Validate_resourceConfig_good(t *testing.T) {
   898  	m := testModule(t, "validate-bad-rc")
   899  	p := testProvider("aws")
   900  	p.GetSchemaReturn = &ProviderSchema{
   901  		ResourceTypes: map[string]*configschema.Block{
   902  			"aws_instance": {
   903  				Attributes: map[string]*configschema.Attribute{
   904  					"foo": {Type: cty.String, Optional: true},
   905  				},
   906  			},
   907  		},
   908  	}
   909  
   910  	c := testContext2(t, &ContextOpts{
   911  		Config: m,
   912  		ProviderResolver: providers.ResolverFixed(
   913  			map[string]providers.Factory{
   914  				"aws": testProviderFuncFixed(p),
   915  			},
   916  		),
   917  	})
   918  
   919  	diags := c.Validate()
   920  	if diags.HasErrors() {
   921  		t.Fatalf("unexpected error: %s", diags.Err())
   922  	}
   923  }
   924  
   925  func TestContext2Validate_tainted(t *testing.T) {
   926  	p := testProvider("aws")
   927  	p.GetSchemaReturn = &ProviderSchema{
   928  		ResourceTypes: map[string]*configschema.Block{
   929  			"aws_instance": {
   930  				Attributes: map[string]*configschema.Attribute{
   931  					"foo": {Type: cty.String, Optional: true},
   932  					"num": {Type: cty.String, Optional: true},
   933  				},
   934  			},
   935  		},
   936  	}
   937  
   938  	m := testModule(t, "validate-good")
   939  	state := MustShimLegacyState(&State{
   940  		Modules: []*ModuleState{
   941  			{
   942  				Path: rootModulePath,
   943  				Resources: map[string]*ResourceState{
   944  					"aws_instance.foo": {
   945  						Type: "aws_instance",
   946  						Primary: &InstanceState{
   947  							ID:      "bar",
   948  							Tainted: true,
   949  						},
   950  					},
   951  				},
   952  			},
   953  		},
   954  	})
   955  	c := testContext2(t, &ContextOpts{
   956  		Config: m,
   957  		ProviderResolver: providers.ResolverFixed(
   958  			map[string]providers.Factory{
   959  				"aws": testProviderFuncFixed(p),
   960  			},
   961  		),
   962  		State: state,
   963  	})
   964  
   965  	p.ValidateResourceTypeConfigFn = func(req providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse {
   966  		var diags tfdiags.Diagnostics
   967  		if req.Config.GetAttr("foo").IsNull() {
   968  			diags.Append(errors.New("foo is not set"))
   969  		}
   970  		return providers.ValidateResourceTypeConfigResponse{
   971  			Diagnostics: diags,
   972  		}
   973  	}
   974  
   975  	diags := c.Validate()
   976  	if diags.HasErrors() {
   977  		t.Fatalf("unexpected error: %s", diags.Err())
   978  	}
   979  }
   980  
   981  func TestContext2Validate_targetedDestroy(t *testing.T) {
   982  	m := testModule(t, "validate-targeted")
   983  	p := testProvider("aws")
   984  	pr := simpleMockProvisioner()
   985  	p.ApplyFn = testApplyFn
   986  	p.DiffFn = testDiffFn
   987  	p.GetSchemaReturn = &ProviderSchema{
   988  		ResourceTypes: map[string]*configschema.Block{
   989  			"aws_instance": {
   990  				Attributes: map[string]*configschema.Attribute{
   991  					"foo": {Type: cty.String, Optional: true},
   992  					"num": {Type: cty.String, Optional: true},
   993  				},
   994  			},
   995  		},
   996  	}
   997  
   998  	ctx := testContext2(t, &ContextOpts{
   999  		Config: m,
  1000  		ProviderResolver: providers.ResolverFixed(
  1001  			map[string]providers.Factory{
  1002  				"aws": testProviderFuncFixed(p),
  1003  			},
  1004  		),
  1005  		Provisioners: map[string]ProvisionerFactory{
  1006  			"shell": testProvisionerFuncFixed(pr),
  1007  		},
  1008  		State: MustShimLegacyState(&State{
  1009  			Modules: []*ModuleState{
  1010  				{
  1011  					Path: rootModulePath,
  1012  					Resources: map[string]*ResourceState{
  1013  						"aws_instance.foo": resourceState("aws_instance", "i-bcd345"),
  1014  						"aws_instance.bar": resourceState("aws_instance", "i-abc123"),
  1015  					},
  1016  				},
  1017  			},
  1018  		}),
  1019  		Targets: []addrs.Targetable{
  1020  			addrs.RootModuleInstance.Resource(
  1021  				addrs.ManagedResourceMode, "aws_instance", "foo",
  1022  			),
  1023  		},
  1024  		Destroy: true,
  1025  	})
  1026  
  1027  	diags := ctx.Validate()
  1028  	if diags.HasErrors() {
  1029  		t.Fatalf("unexpected error: %s", diags.Err())
  1030  	}
  1031  }
  1032  
  1033  func TestContext2Validate_varRefUnknown(t *testing.T) {
  1034  	m := testModule(t, "validate-variable-ref")
  1035  	p := testProvider("aws")
  1036  	p.GetSchemaReturn = &ProviderSchema{
  1037  		ResourceTypes: map[string]*configschema.Block{
  1038  			"aws_instance": {
  1039  				Attributes: map[string]*configschema.Attribute{
  1040  					"foo": {Type: cty.String, Optional: true},
  1041  				},
  1042  			},
  1043  		},
  1044  	}
  1045  	c := testContext2(t, &ContextOpts{
  1046  		Config: m,
  1047  		ProviderResolver: providers.ResolverFixed(
  1048  			map[string]providers.Factory{
  1049  				"aws": testProviderFuncFixed(p),
  1050  			},
  1051  		),
  1052  		Variables: InputValues{
  1053  			"foo": &InputValue{
  1054  				Value:      cty.StringVal("bar"),
  1055  				SourceType: ValueFromCaller,
  1056  			},
  1057  		},
  1058  	})
  1059  
  1060  	var value cty.Value
  1061  	p.ValidateResourceTypeConfigFn = func(req providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse {
  1062  		value = req.Config.GetAttr("foo")
  1063  		return providers.ValidateResourceTypeConfigResponse{}
  1064  	}
  1065  
  1066  	c.Validate()
  1067  
  1068  	// Input variables are always unknown during the validate walk, because
  1069  	// we're checking for validity of all possible input values. Validity
  1070  	// against specific input values is checked during the plan walk.
  1071  	if !value.RawEquals(cty.UnknownVal(cty.String)) {
  1072  		t.Fatalf("bad: %#v", value)
  1073  	}
  1074  }
  1075  
  1076  // Module variables weren't being interpolated during Validate phase.
  1077  // related to https://github.com/hashicorp/terraform-plugin-sdk/issues/5322
  1078  func TestContext2Validate_interpolateVar(t *testing.T) {
  1079  	input := new(MockUIInput)
  1080  
  1081  	m := testModule(t, "input-interpolate-var")
  1082  	p := testProvider("null")
  1083  	p.ApplyFn = testApplyFn
  1084  	p.DiffFn = testDiffFn
  1085  	p.GetSchemaReturn = &ProviderSchema{
  1086  		ResourceTypes: map[string]*configschema.Block{
  1087  			"template_file": {
  1088  				Attributes: map[string]*configschema.Attribute{
  1089  					"template": {Type: cty.String, Optional: true},
  1090  				},
  1091  			},
  1092  		},
  1093  	}
  1094  
  1095  	ctx := testContext2(t, &ContextOpts{
  1096  		Config: m,
  1097  		ProviderResolver: providers.ResolverFixed(
  1098  			map[string]providers.Factory{
  1099  				"template": testProviderFuncFixed(p),
  1100  			},
  1101  		),
  1102  		UIInput: input,
  1103  	})
  1104  
  1105  	diags := ctx.Validate()
  1106  	if diags.HasErrors() {
  1107  		t.Fatalf("unexpected error: %s", diags.Err())
  1108  	}
  1109  }
  1110  
  1111  // When module vars reference something that is actually computed, this
  1112  // shouldn't cause validation to fail.
  1113  func TestContext2Validate_interpolateComputedModuleVarDef(t *testing.T) {
  1114  	input := new(MockUIInput)
  1115  
  1116  	m := testModule(t, "validate-computed-module-var-ref")
  1117  	p := testProvider("aws")
  1118  	p.ApplyFn = testApplyFn
  1119  	p.DiffFn = testDiffFn
  1120  	p.GetSchemaReturn = &ProviderSchema{
  1121  		ResourceTypes: map[string]*configschema.Block{
  1122  			"aws_instance": {
  1123  				Attributes: map[string]*configschema.Attribute{
  1124  					"attr": {Type: cty.String, Optional: true},
  1125  				},
  1126  			},
  1127  		},
  1128  	}
  1129  
  1130  	ctx := testContext2(t, &ContextOpts{
  1131  		Config: m,
  1132  		ProviderResolver: providers.ResolverFixed(
  1133  			map[string]providers.Factory{
  1134  				"aws": testProviderFuncFixed(p),
  1135  			},
  1136  		),
  1137  		UIInput: input,
  1138  	})
  1139  
  1140  	diags := ctx.Validate()
  1141  	if diags.HasErrors() {
  1142  		t.Fatalf("unexpected error: %s", diags.Err())
  1143  	}
  1144  }
  1145  
  1146  // Computed values are lost when a map is output from a module
  1147  func TestContext2Validate_interpolateMap(t *testing.T) {
  1148  	input := new(MockUIInput)
  1149  
  1150  	m := testModule(t, "issue-9549")
  1151  	p := testProvider("template")
  1152  	p.ApplyFn = testApplyFn
  1153  	p.DiffFn = testDiffFn
  1154  
  1155  	ctx := testContext2(t, &ContextOpts{
  1156  		Config: m,
  1157  		ProviderResolver: providers.ResolverFixed(
  1158  			map[string]providers.Factory{
  1159  				"template": testProviderFuncFixed(p),
  1160  			},
  1161  		),
  1162  		UIInput: input,
  1163  	})
  1164  
  1165  	diags := ctx.Validate()
  1166  	if diags.HasErrors() {
  1167  		t.Fatalf("unexpected error: %s", diags.Err())
  1168  	}
  1169  }
  1170  
  1171  // Manually validate using the new PlanGraphBuilder
  1172  func TestContext2Validate_PlanGraphBuilder(t *testing.T) {
  1173  	fixture := contextFixtureApplyVars(t)
  1174  	opts := fixture.ContextOpts()
  1175  	opts.Variables = InputValues{
  1176  		"foo": &InputValue{
  1177  			Value:      cty.StringVal("us-east-1"),
  1178  			SourceType: ValueFromCaller,
  1179  		},
  1180  		"test_list": &InputValue{
  1181  			Value: cty.ListVal([]cty.Value{
  1182  				cty.StringVal("Hello"),
  1183  				cty.StringVal("World"),
  1184  			}),
  1185  			SourceType: ValueFromCaller,
  1186  		},
  1187  		"test_map": &InputValue{
  1188  			Value: cty.MapVal(map[string]cty.Value{
  1189  				"Hello": cty.StringVal("World"),
  1190  				"Foo":   cty.StringVal("Bar"),
  1191  				"Baz":   cty.StringVal("Foo"),
  1192  			}),
  1193  			SourceType: ValueFromCaller,
  1194  		},
  1195  		"amis": &InputValue{
  1196  			Value: cty.MapVal(map[string]cty.Value{
  1197  				"us-east-1": cty.StringVal("override"),
  1198  			}),
  1199  			SourceType: ValueFromCaller,
  1200  		},
  1201  	}
  1202  	c := testContext2(t, opts)
  1203  
  1204  	graph, diags := (&PlanGraphBuilder{
  1205  		Config:     c.config,
  1206  		State:      states.NewState(),
  1207  		Components: c.components,
  1208  		Schemas:    c.schemas,
  1209  		Targets:    c.targets,
  1210  	}).Build(addrs.RootModuleInstance)
  1211  	if diags.HasErrors() {
  1212  		t.Fatalf("errors from PlanGraphBuilder: %s", diags.Err())
  1213  	}
  1214  	defer c.acquireRun("validate-test")()
  1215  	walker, diags := c.walk(graph, walkValidate)
  1216  	if diags.HasErrors() {
  1217  		t.Fatal(diags.Err())
  1218  	}
  1219  	if len(walker.NonFatalDiagnostics) > 0 {
  1220  		t.Fatal(walker.NonFatalDiagnostics.Err())
  1221  	}
  1222  }
  1223  
  1224  func TestContext2Validate_invalidOutput(t *testing.T) {
  1225  	m := testModuleInline(t, map[string]string{
  1226  		"main.tf": `
  1227  data "aws_data_source" "name" {}
  1228  
  1229  output "out" {
  1230    value = "${data.aws_data_source.name.missing}"
  1231  }`,
  1232  	})
  1233  
  1234  	p := testProvider("aws")
  1235  	ctx := testContext2(t, &ContextOpts{
  1236  		Config: m,
  1237  		ProviderResolver: providers.ResolverFixed(
  1238  			map[string]providers.Factory{
  1239  				"aws": testProviderFuncFixed(p),
  1240  			},
  1241  		),
  1242  	})
  1243  
  1244  	diags := ctx.Validate()
  1245  	if !diags.HasErrors() {
  1246  		t.Fatal("succeeded; want errors")
  1247  	}
  1248  	// Should get this error:
  1249  	// Unsupported attribute: This object does not have an attribute named "missing"
  1250  	if got, want := diags.Err().Error(), "Unsupported attribute"; strings.Index(got, want) == -1 {
  1251  		t.Fatalf("wrong error:\ngot:  %s\nwant: message containing %q", got, want)
  1252  	}
  1253  }
  1254  
  1255  func TestContext2Validate_invalidModuleOutput(t *testing.T) {
  1256  	m := testModuleInline(t, map[string]string{
  1257  		"child/main.tf": `
  1258  data "aws_data_source" "name" {}
  1259  
  1260  output "out" {
  1261    value = "${data.aws_data_source.name.missing}"
  1262  }`,
  1263  		"main.tf": `
  1264  module "child" {
  1265    source = "./child"
  1266  }
  1267  
  1268  resource "aws_instance" "foo" {
  1269    foo = "${module.child.out}"
  1270  }`,
  1271  	})
  1272  
  1273  	p := testProvider("aws")
  1274  	ctx := testContext2(t, &ContextOpts{
  1275  		Config: m,
  1276  		ProviderResolver: providers.ResolverFixed(
  1277  			map[string]providers.Factory{
  1278  				"aws": testProviderFuncFixed(p),
  1279  			},
  1280  		),
  1281  	})
  1282  
  1283  	diags := ctx.Validate()
  1284  	if !diags.HasErrors() {
  1285  		t.Fatal("succeeded; want errors")
  1286  	}
  1287  	// Should get this error:
  1288  	// Unsupported attribute: This object does not have an attribute named "missing"
  1289  	if got, want := diags.Err().Error(), "Unsupported attribute"; strings.Index(got, want) == -1 {
  1290  		t.Fatalf("wrong error:\ngot:  %s\nwant: message containing %q", got, want)
  1291  	}
  1292  }
  1293  
  1294  func TestContext2Validate_legacyResourceCount(t *testing.T) {
  1295  	m := testModuleInline(t, map[string]string{
  1296  		"main.tf": `
  1297  resource "aws_instance" "test" {}
  1298  
  1299  output "out" {
  1300    value = aws_instance.test.count
  1301  }`,
  1302  	})
  1303  
  1304  	p := testProvider("aws")
  1305  	ctx := testContext2(t, &ContextOpts{
  1306  		Config: m,
  1307  		ProviderResolver: providers.ResolverFixed(
  1308  			map[string]providers.Factory{
  1309  				"aws": testProviderFuncFixed(p),
  1310  			},
  1311  		),
  1312  	})
  1313  
  1314  	diags := ctx.Validate()
  1315  	if !diags.HasErrors() {
  1316  		t.Fatal("succeeded; want errors")
  1317  	}
  1318  	// Should get this error:
  1319  	// Invalid resource count attribute: The special "count" attribute is no longer supported after Terraform v0.12. Instead, use length(aws_instance.test) to count resource instances.
  1320  	if got, want := diags.Err().Error(), "Invalid resource count attribute:"; strings.Index(got, want) == -1 {
  1321  		t.Fatalf("wrong error:\ngot:  %s\nwant: message containing %q", got, want)
  1322  	}
  1323  }
  1324  
  1325  func TestContext2Validate_invalidModuleRef(t *testing.T) {
  1326  	// This test is verifying that we properly validate and report on references
  1327  	// to modules that are not declared, since we were missing some validation
  1328  	// here in early 0.12.0 alphas that led to a panic.
  1329  	m := testModuleInline(t, map[string]string{
  1330  		"main.tf": `
  1331  output "out" {
  1332    # Intentionally referencing undeclared module to ensure error
  1333    value = module.foo
  1334  }`,
  1335  	})
  1336  
  1337  	p := testProvider("aws")
  1338  	ctx := testContext2(t, &ContextOpts{
  1339  		Config: m,
  1340  		ProviderResolver: providers.ResolverFixed(
  1341  			map[string]providers.Factory{
  1342  				"aws": testProviderFuncFixed(p),
  1343  			},
  1344  		),
  1345  	})
  1346  
  1347  	diags := ctx.Validate()
  1348  	if !diags.HasErrors() {
  1349  		t.Fatal("succeeded; want errors")
  1350  	}
  1351  	// Should get this error:
  1352  	// Reference to undeclared module: No module call named "foo" is declared in the root module.
  1353  	if got, want := diags.Err().Error(), "Reference to undeclared module:"; strings.Index(got, want) == -1 {
  1354  		t.Fatalf("wrong error:\ngot:  %s\nwant: message containing %q", got, want)
  1355  	}
  1356  }
  1357  
  1358  func TestContext2Validate_invalidModuleOutputRef(t *testing.T) {
  1359  	// This test is verifying that we properly validate and report on references
  1360  	// to modules that are not declared, since we were missing some validation
  1361  	// here in early 0.12.0 alphas that led to a panic.
  1362  	m := testModuleInline(t, map[string]string{
  1363  		"main.tf": `
  1364  output "out" {
  1365    # Intentionally referencing undeclared module to ensure error
  1366    value = module.foo.bar
  1367  }`,
  1368  	})
  1369  
  1370  	p := testProvider("aws")
  1371  	ctx := testContext2(t, &ContextOpts{
  1372  		Config: m,
  1373  		ProviderResolver: providers.ResolverFixed(
  1374  			map[string]providers.Factory{
  1375  				"aws": testProviderFuncFixed(p),
  1376  			},
  1377  		),
  1378  	})
  1379  
  1380  	diags := ctx.Validate()
  1381  	if !diags.HasErrors() {
  1382  		t.Fatal("succeeded; want errors")
  1383  	}
  1384  	// Should get this error:
  1385  	// Reference to undeclared module: No module call named "foo" is declared in the root module.
  1386  	if got, want := diags.Err().Error(), "Reference to undeclared module:"; strings.Index(got, want) == -1 {
  1387  		t.Fatalf("wrong error:\ngot:  %s\nwant: message containing %q", got, want)
  1388  	}
  1389  }
  1390  
  1391  func TestContext2Validate_invalidDependsOnResourceRef(t *testing.T) {
  1392  	// This test is verifying that we raise an error if depends_on
  1393  	// refers to something that doesn't exist in configuration.
  1394  	m := testModuleInline(t, map[string]string{
  1395  		"main.tf": `
  1396  resource "test_instance" "bar" {
  1397    depends_on = [test_resource.nonexistant]
  1398  }
  1399  `,
  1400  	})
  1401  
  1402  	p := testProvider("test")
  1403  	ctx := testContext2(t, &ContextOpts{
  1404  		Config: m,
  1405  		ProviderResolver: providers.ResolverFixed(
  1406  			map[string]providers.Factory{
  1407  				"test": testProviderFuncFixed(p),
  1408  			},
  1409  		),
  1410  	})
  1411  
  1412  	diags := ctx.Validate()
  1413  	if !diags.HasErrors() {
  1414  		t.Fatal("succeeded; want errors")
  1415  	}
  1416  	// Should get this error:
  1417  	// Reference to undeclared module: No module call named "foo" is declared in the root module.
  1418  	if got, want := diags.Err().Error(), "Reference to undeclared resource:"; strings.Index(got, want) == -1 {
  1419  		t.Fatalf("wrong error:\ngot:  %s\nwant: message containing %q", got, want)
  1420  	}
  1421  }
  1422  
  1423  func TestContext2Validate_invalidResourceIgnoreChanges(t *testing.T) {
  1424  	// This test is verifying that we raise an error if ignore_changes
  1425  	// refers to something that can be statically detected as not conforming
  1426  	// to the resource type schema.
  1427  	m := testModuleInline(t, map[string]string{
  1428  		"main.tf": `
  1429  resource "test_instance" "bar" {
  1430    lifecycle {
  1431      ignore_changes = [does_not_exist_in_schema]
  1432    }
  1433  }
  1434  `,
  1435  	})
  1436  
  1437  	p := testProvider("test")
  1438  	ctx := testContext2(t, &ContextOpts{
  1439  		Config: m,
  1440  		ProviderResolver: providers.ResolverFixed(
  1441  			map[string]providers.Factory{
  1442  				"test": testProviderFuncFixed(p),
  1443  			},
  1444  		),
  1445  	})
  1446  
  1447  	diags := ctx.Validate()
  1448  	if !diags.HasErrors() {
  1449  		t.Fatal("succeeded; want errors")
  1450  	}
  1451  	// Should get this error:
  1452  	// Reference to undeclared module: No module call named "foo" is declared in the root module.
  1453  	if got, want := diags.Err().Error(), `no argument, nested block, or exported attribute named "does_not_exist_in_schema"`; strings.Index(got, want) == -1 {
  1454  		t.Fatalf("wrong error:\ngot:  %s\nwant: message containing %q", got, want)
  1455  	}
  1456  }