Terraform 可以为 null 的变量的自定义验证

ric*_*hid 6 terraform

我正在尝试使用 Terraform 0.13 的自定义变量验证来确保该值位于null指定范围内或之间。我已经尝试了我能想到的每种组合(使用cantry等),但无法让它适用于每种情况。

这是完整的非工作示例:

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."
  }
}
Run Code Online (Sandbox Code Playgroud)

如果该值出现null以下错误,则此操作将失败:

操作期间出错:参数不能为空。

我相信这是由于对条件表达式的急切求值造成的。我错过了一些明显的东西吗?或者有什么聪明的解决方法吗?

Mar*_*ins 13

看起来这里发生了两件不同的事情。

首先,您的条件表达式包含以下子表达式:

var.target_group_stickiness_duration == null
Run Code Online (Sandbox Code Playgroud)

这似乎允许该值为空。

但是,如果我们将其纠正为相反的情况,则会暴露第二个问题:

    condition = ( 
      var.target_group_stickiness_duration != null &&
      ( var.target_group_stickiness_duration >= 1 && var.target_group_stickiness_duration <= 604800 )
    )   
Run Code Online (Sandbox Code Playgroud)

Terraform 的逻辑运算符在某些其他语言中没有“短路”行为,其中第一个操作数的结果可以阻止任何对第二个操作数求值的尝试。因此 的两个操作数都&&必须有效并成功返回truefalse

如果值为空,第二个操作数(嵌套&&测试数字的范围)不会成功,因为>=没有为空数字定义。

要实现此目的,需要使用不同的策略来避免将>=运算符应用于空数字。有几种不同的方法可以做到这一点,包括coalesce在该问题的公认答案中讨论的方法。

另一种替代策略是使用条件运算符,它确实允许未选择的结果操作数失败,以允许我们将其用作以下情况的防护:

  condition = (
    var.target_group_stickiness_duration == null ? false : (
      var.target_group_stickiness_duration >= 1 && 
      var.target_group_stickiness_duration <= 604800
    )
  )
Run Code Online (Sandbox Code Playgroud)

这本质上是其他一些语言在其逻辑运算符中提供的自动短路行为的显式实现。Terraform,至少在其当前的设计中,要求您明确写出>=<=运算仅适用于非空数字。

  • 啊,是的,今天我以新的眼光看到这里发生了两件不同的事情,而我在看到第一件事情时只关注其中一件。我会更新我的答案以使其更加完整,尽管我看到您已经接受了其他答案,所以我这样做只是为了不在这里留下不完整的答案。 (2认同)
  • 一个小的变化:三元组的第一部分应该是“true”,但这是一个非常干净的解决方案。非常感谢您指出条件/三元运算符支持短路,这对将来会有帮助! (2认同)

Mar*_*cin 7

它失败了,因为当你target_group_stickiness_duration是时null

(var.target_group_stickiness_duration >= 1 && var.target_group_stickiness_duration <= 604800
)
Run Code Online (Sandbox Code Playgroud)

是无效的。

您可以尝试使用合并的以下操作:

variable "target_group_stickiness_duration" {
  default = null
  type    = number
 
  validation {
    condition = ( 
      var.target_group_stickiness_duration == null ||      
     (coalesce(var.target_group_stickiness_duration, 0) >= 1 && coalesce(var.target_group_stickiness_duration, 604801) <= 604800))
 
    error_message = "Target group stickiness duration must be >= 1 and <= 604800."
  }
  
}
Run Code Online (Sandbox Code Playgroud)