command: Specialized error message for var decls in tfvars
A common new-user mistake is to place variable _declarations_ into .tfvars files instead of variable _values_. To guide towards the correct approach here, we add a specialized error message for that situation that includes guidance on the distinction between declaring and setting values for variables, and an example of what setting a value should look like.
This commit is contained in:
parent
9c0e3cc819
commit
552dddfb4c
|
@ -165,6 +165,37 @@ func (m *Meta) addVarsFromFile(filename string, sourceType terraform.ValueSource
|
|||
}
|
||||
}
|
||||
|
||||
// Before we do our real decode, we'll probe to see if there are any blocks
|
||||
// of type "variable" in this body, since it's a common mistake for new
|
||||
// users to put variable declarations in tfvars rather than variable value
|
||||
// definitions, and otherwise our error message for that case is not so
|
||||
// helpful.
|
||||
{
|
||||
content, _, _ := f.Body.PartialContent(&hcl.BodySchema{
|
||||
Blocks: []hcl.BlockHeaderSchema{
|
||||
{
|
||||
Type: "variable",
|
||||
LabelNames: []string{"name"},
|
||||
},
|
||||
},
|
||||
})
|
||||
for _, block := range content.Blocks {
|
||||
name := block.Labels[0]
|
||||
diags = diags.Append(&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Variable declaration in .tfvars file",
|
||||
Detail: fmt.Sprintf("A .tfvars file is used to assign values to variables that have already been declared in .tf files, not to declare new variables. To declare variable %q, place this block in one of your .tf files, such as variables.tf.\n\nTo set a value for this variable in %s, use the definition syntax instead:\n %s = <value>", name, block.TypeRange.Filename, name),
|
||||
Subject: &block.TypeRange,
|
||||
})
|
||||
}
|
||||
if diags.HasErrors() {
|
||||
// If we already found problems then JustAttributes below will find
|
||||
// the same problems with less-helpful messages, so we'll bail for
|
||||
// now to let the user focus on the immediate problem.
|
||||
return diags
|
||||
}
|
||||
}
|
||||
|
||||
attrs, hclDiags := f.Body.JustAttributes()
|
||||
diags = diags.Append(hclDiags)
|
||||
|
||||
|
|
|
@ -686,6 +686,38 @@ func TestPlan_varFileDefault(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestPlan_varFileWithDecls(t *testing.T) {
|
||||
tmp, cwd := testCwd(t)
|
||||
defer testFixCwd(t, tmp, cwd)
|
||||
|
||||
varFilePath := testTempFile(t)
|
||||
if err := ioutil.WriteFile(varFilePath, []byte(planVarFileWithDecl), 0644); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
p := planVarsFixtureProvider()
|
||||
ui := cli.NewMockUi()
|
||||
c := &PlanCommand{
|
||||
Meta: Meta{
|
||||
testingOverrides: metaOverridesForProvider(p),
|
||||
Ui: ui,
|
||||
},
|
||||
}
|
||||
|
||||
args := []string{
|
||||
"-var-file", varFilePath,
|
||||
testFixturePath("plan-vars"),
|
||||
}
|
||||
if code := c.Run(args); code == 0 {
|
||||
t.Fatalf("succeeded; want failure\n\n%s", ui.OutputWriter.String())
|
||||
}
|
||||
|
||||
msg := ui.ErrorWriter.String()
|
||||
if got, want := msg, "Variable declaration in .tfvars file"; !strings.Contains(got, want) {
|
||||
t.Fatalf("missing expected error message\nwant message containing %q\ngot:\n%s", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlan_detailedExitcode(t *testing.T) {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
|
@ -892,6 +924,13 @@ const planVarFile = `
|
|||
foo = "bar"
|
||||
`
|
||||
|
||||
const planVarFileWithDecl = `
|
||||
foo = "bar"
|
||||
|
||||
variable "nope" {
|
||||
}
|
||||
`
|
||||
|
||||
const testPlanNoStateStr = `
|
||||
<not created>
|
||||
`
|
||||
|
|
Loading…
Reference in New Issue