Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Terraform custom validation for variable that can be null

Tags:

terraform

I'm trying to use Terraform 0.13's custom variable validation to ensure that the value is either null or between a specified range. I've tried every combination I can think of (using can, try, etc) but can't get it working for every case.

Here is the full non-working example:

variable "target_group_stickiness_duration" {
  default = null
  type    = number
 
  validation {
    condition = ( 
      var.target_group_stickiness_duration == null ||
      ( var.target_group_stickiness_duration >= 1 && var.target_group_stickiness_duration <= 604800 )
    )   
 
    error_message = "Target group stickiness duration must be >= 1 and <= 604800."
  }
}

This will fail if the value is null with the following error:

Error during operation: argument must not be null.

I believe this is due to eager evaluation of the conditional expression. Am I missing something obvious? Or any clever workarounds for this?

like image 344
richid Avatar asked Mar 03 '26 17:03

richid


1 Answers

It looks like there are two different things going on here.

The first is that your condition expression includes the following subexpression:

var.target_group_stickiness_duration == null

This seems to be allowing the value to be null.

However, if we correct that to the opposite then it will expose a second problem:

    condition = ( 
      var.target_group_stickiness_duration != null &&
      ( var.target_group_stickiness_duration >= 1 && var.target_group_stickiness_duration <= 604800 )
    )   

Terraform's logical operators don't have the "short circuit" behavior in some other languages, where the result of the first operand can prevent any attempt to evaluate the second operand. Therefore both operands of && must be valid and successfully return either true or false.

The second operand (the nested && testing the range of the number) can't succeed if the value is null, because >= isn't defined for null numbers.

To make this work requires using a different strategy that avoids applying the >= operator to a null number. There are a few different ways to do that, including one with coalesce discussed in the accepted answer to this question.

Another alternative strategy is to use the conditional operator, which does allow the unselected result operand to fail, to allow us to use it as a guard for situations like this:

  condition = (
    var.target_group_stickiness_duration == null ? false : (
      var.target_group_stickiness_duration >= 1 && 
      var.target_group_stickiness_duration <= 604800
    )
  )

This is essentially an explicit implementation of the automatic short-circuit behavior some other languages offer in their logical operators. Terraform, at least in its current design, requires you to explicitly write out that the >= and <= operations are desirable only for non-null numbers.

like image 136
Martin Atkins Avatar answered Mar 06 '26 08:03

Martin Atkins



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!