configs: Fix check block configuration diagnostics

When validating self-references for resource and data source
preconditions and postconditions, we previously did not nil-check the
block's condition field, which caused a panic when the block had no
condition.

While fixing this I noticed that we were not validating that there are
no self-references in the error message, so fixed that.
pull/31290/head
Alisdair McDiarmid 4 years ago
parent fd45fb969c
commit 64cf53bd7e

@ -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

@ -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
}
}
}

@ -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."
}
}
}
Loading…
Cancel
Save