core: skip resource validation when count is unknown
The approach here is a little hacky, since this edge case applies only to validate and all of the other evaluateResourceCountExpression callers don't care about it: we overload the "count" return value as a flag to allow NodeValidatableResource to allow it to detect this situation and silently ignore errors in this case.
This commit is contained in:
parent
b54342460c
commit
2c1ef35965
|
@ -22,8 +22,13 @@ import (
|
||||||
// If the result is -1, this indicates that the given expression is nil and so
|
// If the result is -1, this indicates that the given expression is nil and so
|
||||||
// the "count" behavior should not be enabled for this resource at all.
|
// the "count" behavior should not be enabled for this resource at all.
|
||||||
//
|
//
|
||||||
// If error diagnostics are returned then the result is undefined and must
|
// If error diagnostics are returned then the result is always the meaningless
|
||||||
// not be used.
|
// placeholder value -1, except in one case: if the count expression evaluates
|
||||||
|
// to an unknown number value then the result is zero, allowing this situation
|
||||||
|
// to be treated by the caller as special if needed. For example, an early
|
||||||
|
// graph walk may wish to just silently skip resources with unknown counts
|
||||||
|
// to allow them to be dealt with in a later graph walk where more information
|
||||||
|
// is available.
|
||||||
func evaluateResourceCountExpression(expr hcl.Expression, ctx EvalContext) (int, tfdiags.Diagnostics) {
|
func evaluateResourceCountExpression(expr hcl.Expression, ctx EvalContext) (int, tfdiags.Diagnostics) {
|
||||||
if expr == nil {
|
if expr == nil {
|
||||||
return -1, nil
|
return -1, nil
|
||||||
|
@ -60,7 +65,11 @@ func evaluateResourceCountExpression(expr hcl.Expression, ctx EvalContext) (int,
|
||||||
Detail: `The "count" value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how many instances will be created. To work around this, use the -target argument to first apply only the resources that the count depends on.`,
|
Detail: `The "count" value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how many instances will be created. To work around this, use the -target argument to first apply only the resources that the count depends on.`,
|
||||||
Subject: expr.Range().Ptr(),
|
Subject: expr.Range().Ptr(),
|
||||||
})
|
})
|
||||||
return -1, diags
|
// We return zero+errors in this one case to allow callers to handle
|
||||||
|
// an unknown count as special. This is rarely necessary, but is used
|
||||||
|
// by the validate walk in particular so that it can just skip
|
||||||
|
// validation in this case, assuming a later walk will take care of it.
|
||||||
|
return 0, diags
|
||||||
}
|
}
|
||||||
|
|
||||||
err := gocty.FromCtyValue(countVal, &count)
|
err := gocty.FromCtyValue(countVal, &count)
|
||||||
|
|
|
@ -31,10 +31,19 @@ func (n *NodeValidatableResource) DynamicExpand(ctx EvalContext) (*Graph, error)
|
||||||
count, countDiags := evaluateResourceCountExpression(n.Config.Count, ctx)
|
count, countDiags := evaluateResourceCountExpression(n.Config.Count, ctx)
|
||||||
diags = diags.Append(countDiags)
|
diags = diags.Append(countDiags)
|
||||||
if countDiags.HasErrors() {
|
if countDiags.HasErrors() {
|
||||||
log.Printf("[TRACE] %T %s: count expression has errors", n, n.Name())
|
if count != 0 {
|
||||||
return nil, diags.Err()
|
log.Printf("[TRACE] %T %s: count expression has errors", n, n.Name())
|
||||||
}
|
return nil, diags.Err()
|
||||||
if count >= 0 {
|
}
|
||||||
|
|
||||||
|
// evaluateResourceCountExpression returns zero+errors only in the
|
||||||
|
// case where the count value successfully evaluated to an unknown
|
||||||
|
// number. We don't treat this as an error here because counts that
|
||||||
|
// are computed during validate can become known during the plan
|
||||||
|
// walk, if they refer to data resources, and so we'll just defer
|
||||||
|
// our validation steps to the plan phase in that case.
|
||||||
|
log.Printf("[TRACE] %T %s: count expression value not yet known, so deferring validation until the plan walk", n, n.Name())
|
||||||
|
} else if count >= 0 {
|
||||||
log.Printf("[TRACE] %T %s: count expression evaluates to %d", n, n.Name(), count)
|
log.Printf("[TRACE] %T %s: count expression evaluates to %d", n, n.Name(), count)
|
||||||
} else {
|
} else {
|
||||||
log.Printf("[TRACE] %T %s: no count argument present", n, n.Name())
|
log.Printf("[TRACE] %T %s: no count argument present", n, n.Name())
|
||||||
|
|
Loading…
Reference in New Issue