diff --git a/backend/unparsed_value.go b/backend/unparsed_value.go index 65a05c823..22bc81369 100644 --- a/backend/unparsed_value.go +++ b/backend/unparsed_value.go @@ -69,21 +69,15 @@ func ParseVariableValues(vv map[string]UnparsedVariableValue, decls map[string]* if !declared { switch val.SourceType { case terraform.ValueFromConfig, terraform.ValueFromAutoFile, terraform.ValueFromNamedFile: - // These source types have source ranges, so we can produce - // a nice error message with good context. - // - // This one is a warning for now because there is an existing - // pattern of providing a file containing the superset of - // variables across all configurations in an organization. This - // is deprecated in v0.12.0 because it's more important to give - // feedback to users who make typos. Those using this approach - // should migrate to using environment variables instead before - // this becomes an error in a future major release. - if seenUndeclaredInFile < 3 { + // We allow undeclared names for variable values from files and warn in case + // users have forgotten a variable {} declaration or have a typo in their var name. + // Some users will actively ignore this warning because they use a .tfvars file + // across multiple configurations. + if seenUndeclaredInFile < 2 { diags = diags.Append(tfdiags.Sourceless( tfdiags.Warning, "Value for undeclared variable", - fmt.Sprintf("The root module does not declare a variable named %q but a value was found in file %q. To use this value, add a \"variable\" block to the configuration.\n\nUsing a variables file to set an undeclared variable is deprecated and will become an error in a future release. If you wish to provide certain \"global\" settings to all configurations in your organization, use TF_VAR_... environment variables to set these instead.", name, val.SourceRange.Filename), + fmt.Sprintf("The root module does not declare a variable named %q but a value was found in file %q. If you meant to use this value, add a \"variable\" block to the configuration.\n\nTo silence these warnings, use TF_VAR_... environment variables to provide certain \"global\" settings to all configurations in your organization. To reduce the verbosity of these warnings, use the -compact-warnings option.", name, val.SourceRange.Filename), )) } seenUndeclaredInFile++ @@ -114,7 +108,7 @@ func ParseVariableValues(vv map[string]UnparsedVariableValue, decls map[string]* ret[name] = val } - if seenUndeclaredInFile >= 3 { + if seenUndeclaredInFile > 2 { extras := seenUndeclaredInFile - 2 diags = diags.Append(&hcl.Diagnostic{ Severity: hcl.DiagWarning, diff --git a/backend/unparsed_value_test.go b/backend/unparsed_value_test.go index 27fba6257..0c37adbc6 100644 --- a/backend/unparsed_value_test.go +++ b/backend/unparsed_value_test.go @@ -1,6 +1,7 @@ package backend import ( + "strings" "testing" "github.com/google/go-cmp/cmp" @@ -59,7 +60,7 @@ func TestParseVariableValuesUndeclared(t *testing.T) { for _, diag := range diags { t.Logf("%s: %s", diag.Description().Summary, diag.Description().Detail) } - if got, want := len(diags), 5; got != want { + if got, want := len(diags), 4; got != want { t.Fatalf("wrong number of diagnostics %d; want %d", got, want) } @@ -73,14 +74,14 @@ func TestParseVariableValuesUndeclared(t *testing.T) { if got, want := diags[1].Description().Summary, undeclSingular; got != want { t.Errorf("wrong summary for diagnostic 1\ngot: %s\nwant: %s", got, want) } - if got, want := diags[2].Description().Summary, undeclSingular; got != want { + if got, want := diags[2].Description().Summary, undeclPlural; got != want { t.Errorf("wrong summary for diagnostic 2\ngot: %s\nwant: %s", got, want) } - if got, want := diags[3].Description().Summary, undeclPlural; got != want { - t.Errorf("wrong summary for diagnostic 3\ngot: %s\nwant: %s", got, want) + if got, want := diags[2].Description().Detail, "3 other variable(s)"; !strings.Contains(got, want) { + t.Errorf("wrong detail for diagnostic 2\ngot: %s\nmust contain: %s", got, want) } - if got, want := diags[4].Description().Summary, missingRequired; got != want { - t.Errorf("wrong summary for diagnostic 4\ngot: %s\nwant: %s", got, want) + if got, want := diags[3].Description().Summary, missingRequired; got != want { + t.Errorf("wrong summary for diagnostic 3\ngot: %s\nwant: %s", got, want) } wantVals := terraform.InputValues{ diff --git a/website/docs/language/values/variables.html.md b/website/docs/language/values/variables.html.md index 75f6b4780..f911b0406 100644 --- a/website/docs/language/values/variables.html.md +++ b/website/docs/language/values/variables.html.md @@ -437,6 +437,44 @@ $ export TF_VAR_availability_zone_names='["us-west-1b","us-west-1d"]' For readability, and to avoid the need to worry about shell escaping, we recommend always setting complex variable values via variable definitions files. +### Values for Undeclared Variables + +If you have defined a variable value, but not its corresponding `variable {}` +definition, you may get an error or warning depending on how you have provided +that value. + +If you provide values for undeclared variables defined as [environment variables](#environment-variables) +you will not get an error or warning. This is because environment variables may +be declared but not used in all configurations that might be run. + +If you provide values for undeclared variables defined [in a file](#variable-definitions-tfvars-files) +you will get a warning. This is to help in cases where you have provided a variable +value _meant_ for a variable declaration, but perhaps there is a mistake in the +value definition. For example, the following configuration: + +```terraform +variable "moose" { + type = string +} +``` + +And the following `.tfvars` file: + +```hcl +mosse = "Moose" +``` + +Will cause Terraform to warn you that there is no variable declared `"mosse"`, which can help +you spot this mistake. + +If you use `.tfvars` files across multiple configurations and expect to continue to see this warning, +you can use the [`-compact-warnings`](https://www.terraform.io/docs/cli/commands/plan.html#compact-warnings) +option to simplify your output. + +If you provide values for undeclared variables on the [command line](#variables-on-the-command-line), +Terraform will error. To avoid this error, either declare a variable block for the value, or remove +the variable value from your Terraform call. + ### Variable Definition Precedence The above mechanisms for setting variables can be used together in any