Terraform中OR(||)条件未短路引发validation报错求助
Terraform azurerm_app_service变量验证问题解决
问题原因
Terraform的变量验证规则不支持短路求值——也就是说,var.node_version == null || contains(...)里的两个表达式会被完整计算,哪怕前面的null判断已经为true。当node_version为null时,contains函数收到null作为参数(它要求参数是列表/集合类型),直接触发无效参数错误,根本不会走到逻辑判断的短路环节。
可行解决办法
方法1:用coalesce将null转为空值,避免contains报错
把null转换成一个不在允许列表里的空字符串,这样即使contains执行,前面的null判断已经满足条件,整体验证通过;如果用户传入了值,就会正常校验是否在列表中。
variable "app_service_stack" { type = object({ current_stack = optional(string) dotnet_version = optional(string) node_version = optional(string) }) default = {} validation { condition = (var.current_stack == null || contains(["dotnet", "node"], coalesce(var.current_stack, ""))) && (var.dotnet_version == null || contains(["6.0", "7.0"], coalesce(var.dotnet_version, ""))) && (var.node_version == null || contains(["18lts", "20lts"], coalesce(var.node_version, ""))) error_message = "Stack版本参数不符合要求,current_stack可选值为dotnet/node,dotnet_version可选值为6.0/7.0,node_version可选值为18lts/20lts,或留空(null)。" } }
方法2:用can函数包裹contains,捕获无效参数场景
can函数会检查表达式是否能成功执行,返回布尔值。如果node_version是null,contains执行失败,can返回false,但前面的null判断已经为true,整体验证通过;如果传入了有效值,can返回true后再校验是否在允许列表中。
variable "app_service_stack" { type = object({ current_stack = optional(string) dotnet_version = optional(string) node_version = optional(string) }) default = {} validation { condition = (var.current_stack == null || (can(contains(["dotnet", "node"], var.current_stack)) && contains(["dotnet", "node"], var.current_stack))) && (var.dotnet_version == null || (can(contains(["6.0", "7.0"], var.dotnet_version)) && contains(["6.0", "7.0"], var.dotnet_version))) && (var.node_version == null || (can(contains(["18lts", "20lts"], var.node_version)) && contains(["18lts", "20lts"], var.node_version))) error_message = "Stack版本参数不符合要求,current_stack可选值为dotnet/node,dotnet_version可选值为6.0/7.0,node_version可选值为18lts/20lts,或留空(null)。" } }
方法3:用try函数容错失败的表达式
try函数会尝试执行第一个表达式,失败则返回指定的默认值。当node_version为null时,contains执行失败,try返回false,配合前面的null判断让验证通过;有效值则正常校验。
variable "app_service_stack" { type = object({ current_stack = optional(string) dotnet_version = optional(string) node_version = optional(string) }) default = {} validation { condition = (var.current_stack == null || try(contains(["dotnet", "node"], var.current_stack), false)) && (var.dotnet_version == null || try(contains(["6.0", "7.0"], var.dotnet_version), false)) && (var.node_version == null || try(contains(["18lts", "20lts"], var.node_version), false)) error_message = "Stack版本参数不符合要求,current_stack可选值为dotnet/node,dotnet_version可选值为6.0/7.0,node_version可选值为18lts/20lts,或留空(null)。" } }
内容的提问来源于stack exchange,提问作者amantur
相关产品推荐
相关产品推荐

