diff --git a/configs/parser_config_test.go b/configs/parser_config_test.go index 13d90fed6..2fe645ed7 100644 --- a/configs/parser_config_test.go +++ b/configs/parser_config_test.go @@ -224,3 +224,62 @@ func TestParserLoadConfigFileWarning(t *testing.T) { }) } } + +// TestParseLoadConfigFileError is a test that verifies files from +// testdata/warning-files produce particular warnings. +// +// This test does not verify that reading these files produces the correct +// file element contents in spite of those warnings. More detailed assertions +// may be made on some subset of these configuration files in other tests. +func TestParserLoadConfigFileError(t *testing.T) { + files, err := ioutil.ReadDir("testdata/error-files") + if err != nil { + t.Fatal(err) + } + + for _, info := range files { + name := info.Name() + t.Run(name, func(t *testing.T) { + src, err := ioutil.ReadFile(filepath.Join("testdata/error-files", name)) + if err != nil { + t.Fatal(err) + } + + // First we'll scan the file to see what warnings are expected. + // That's declared inside the files themselves by using the + // string "WARNING: " somewhere on each line that is expected + // to produce a warning, followed by the expected warning summary + // text. A single-line comment (with #) is the main way to do that. + const marker = "ERROR: " + sc := bufio.NewScanner(bytes.NewReader(src)) + wantErrors := make(map[int]string) + lineNum := 1 + for sc.Scan() { + lineText := sc.Text() + if idx := strings.Index(lineText, marker); idx != -1 { + summaryText := lineText[idx+len(marker):] + wantErrors[lineNum] = summaryText + } + lineNum++ + } + + parser := testParser(map[string]string{ + name: string(src), + }) + + _, diags := parser.LoadConfigFile(name) + + gotErrors := make(map[int]string) + for _, diag := range diags { + if diag.Severity != hcl.DiagError || diag.Subject == nil { + continue + } + gotErrors[diag.Subject.Start.Line] = diag.Summary + } + + if diff := cmp.Diff(wantErrors, gotErrors); diff != "" { + t.Errorf("wrong errors\n%s", diff) + } + }) + } +} diff --git a/configs/provisioner.go b/configs/provisioner.go index 6f380860a..769382513 100644 --- a/configs/provisioner.go +++ b/configs/provisioner.go @@ -147,8 +147,8 @@ func onlySelfRefs(body hcl.Body) hcl.Diagnostics { if !valid { diags = append(diags, &hcl.Diagnostic{ - Severity: hcl.DiagWarning, - Summary: "External references from destroy provisioners are deprecated", + Severity: hcl.DiagError, + Summary: "Invalid reference from destroy provisioner", Detail: "Destroy-time provisioners and their connection configurations may only " + "reference attributes of the related resource, via 'self', 'count.index', " + "or 'each.key'.\n\nReferences to other resources during the destroy phase " + diff --git a/configs/testdata/warning-files/destroy-provisioners.tf b/configs/testdata/error-files/destroy-provisioners.tf similarity index 69% rename from configs/testdata/warning-files/destroy-provisioners.tf rename to configs/testdata/error-files/destroy-provisioners.tf index c6c28b823..4831b5302 100644 --- a/configs/testdata/warning-files/destroy-provisioners.tf +++ b/configs/testdata/error-files/destroy-provisioners.tf @@ -5,7 +5,7 @@ locals { resource "null_resource" "a" { connection { host = self.hostname - user = local.user # WARNING: External references from destroy provisioners are deprecated + user = local.user # ERROR: Invalid reference from destroy provisioner } provisioner "remote-exec" { @@ -36,9 +36,9 @@ resource "null_resource" "b" { when = destroy connection { host = self.hostname - user = local.user # WARNING: External references from destroy provisioners are deprecated + user = local.user # ERROR: Invalid reference from destroy provisioner } - command = "echo ${local.name}" # WARNING: External references from destroy provisioners are deprecated + command = "echo ${local.name}" # ERROR: Invalid reference from destroy provisioner } }