diff --git a/internal/configs/checks.go b/internal/configs/checks.go index 10ad62b69a42..417dff45eece 100644 --- a/internal/configs/checks.go +++ b/internal/configs/checks.go @@ -40,27 +40,36 @@ type CheckRule struct { // is found. func (cr *CheckRule) validateSelfReferences(checkType string, addr addrs.Resource) hcl.Diagnostics { var diags hcl.Diagnostics - refs, _ := lang.References(cr.Condition.Variables()) - for _, ref := range refs { - var refAddr addrs.Resource - - switch rs := ref.Subject.(type) { - case addrs.Resource: - refAddr = rs - case addrs.ResourceInstance: - refAddr = rs.Resource - default: + exprs := []hcl.Expression{ + cr.Condition, + cr.ErrorMessage, + } + for _, expr := range exprs { + if expr == nil { continue } - - if refAddr.Equal(addr) { - diags = diags.Append(&hcl.Diagnostic{ - Severity: hcl.DiagError, - Summary: fmt.Sprintf("Invalid reference in %s", checkType), - Detail: fmt.Sprintf("Configuration for %s may not refer to itself.", addr.String()), - Subject: cr.Condition.Range().Ptr(), - }) - break + refs, _ := lang.References(expr.Variables()) + for _, ref := range refs { + var refAddr addrs.Resource + + switch rs := ref.Subject.(type) { + case addrs.Resource: + refAddr = rs + case addrs.ResourceInstance: + refAddr = rs.Resource + default: + continue + } + + if refAddr.Equal(addr) { + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: fmt.Sprintf("Invalid reference in %s", checkType), + Detail: fmt.Sprintf("Configuration for %s may not refer to itself.", addr.String()), + Subject: expr.Range().Ptr(), + }) + break + } } } return diags diff --git a/internal/configs/testdata/invalid-files/precondition-postcondition-badref.tf b/internal/configs/testdata/invalid-files/precondition-postcondition-badref.tf new file mode 100644 index 000000000000..ff5ff712962b --- /dev/null +++ b/internal/configs/testdata/invalid-files/precondition-postcondition-badref.tf @@ -0,0 +1,29 @@ +data "example" "example" { + foo = 5 + + lifecycle { + precondition { + condition = data.example.example.foo == 5 # ERROR: Invalid reference in precondition + error_message = "Must be five." + } + postcondition { + condition = self.foo == 5 + error_message = "Must be five, but is ${data.example.example.foo}." # ERROR: Invalid reference in postcondition + } + } +} + +resource "example" "example" { + foo = 5 + + lifecycle { + precondition { + condition = example.example.foo == 5 # ERROR: Invalid reference in precondition + error_message = "Must be five." + } + postcondition { + condition = self.foo == 5 + error_message = "Must be five, but is ${example.example.foo}." # ERROR: Invalid reference in postcondition + } + } +} diff --git a/internal/configs/testdata/invalid-files/precondition-postcondition-missing-condition.tf b/internal/configs/testdata/invalid-files/precondition-postcondition-missing-condition.tf new file mode 100644 index 000000000000..d0a6ab3074da --- /dev/null +++ b/internal/configs/testdata/invalid-files/precondition-postcondition-missing-condition.tf @@ -0,0 +1,12 @@ +resource "example" "example" { + foo = 5 + + lifecycle { + precondition { # ERROR: Missing required argument + error_message = "Can a check block fail without a condition?" + } + postcondition { # ERROR: Missing required argument + error_message = "Do not try to pass the check; only realize that there is no check." + } + } +}