Terraform 13,根据另一个变量的值验证变量

ale*_*xis 18 terraform terraform-provider-aws

有没有办法实现以下逻辑

variable "environment" {
  description = "The environment this will be run in can only be set to [preprod|test|prod]"
  type        = string
  default     = "test"
  validation {
    condition     = can(regex("^(prod|preprod|test)$", var.environment))
    error_message = "The environment variable can only be set to [prod|preprod|test]."
  }
}

variable "fet_code" {
  description = "Set the feature code"
  type        = string
  default     = ""
  validation {
    condition     = var.environment == "test" && length(var.fet_code) != 3
    error_message = "The environment has been set to 'test' but the fet_code has not be defined."
  }
}
Run Code Online (Sandbox Code Playgroud)

目前我收到以下错误:

Error: Invalid reference in variable validation

  on variable.tf line 17, in variable "fet_code":
  17:     condition     = var.environment == "fet" && length(var.fet_code) == 3

The condition for variable "fet_code" can only refer to the variable itself,
using var.fet_code.
Run Code Online (Sandbox Code Playgroud)

我明白代码有什么问题,我只是想知道是否有办法绕过限制?

tzr*_*rlk 14

虽然将其实现为一项功能存在Github 问题,但验证多个变量的唯一方法是使用局部变量在运行时抛出错误:

variable "environment" {
  description = "The environment this will be run in can only be set to [preprod|test|prod]"
  type        = string
  default     = "test"
  validation {
    condition     = can(regex("^(prod|preprod|test)$", var.environment))
    error_message = "The environment variable can only be set to [prod|preprod|test]."
  }
}

variable "fet_code" {
  description = "Set the feature code"
  type        = string
  default     = ""
}

locals {
  validate_fet_code_cnd = var.environment == "test" && length(var.fet_code) != 3
  validate_fet_code_msg = "The environment has been set to 'test' but the fet_code has not been defined."
  validate_fet_code_chk = regex(
      "^${local.validate_fet_code_msg}$",
      ( !local.validate_fet_code_cnd
        ? local.validate_fet_code_msg
        : "" ) )
}
Run Code Online (Sandbox Code Playgroud)

这是一个混乱、粗略的黑客行为,但它应该可以防止应用无效值。

  • 我认为最近在上面的 github 问题中提出了一个更干净的解决方案。看看https://github.com/hashicorp/terraform/issues/25609#issuecomment-1057614400 (7认同)

小智 13

在我看来,这两个变量密切相关。我会将它们更改为一个对象以实现您想要的。

variable "environment" {
  type = object({
    environment = string
    fet_code = string
  })
  default = {
    environment = "test"
    fet_code = ""
  }

  validation {
    condition     = can(regex("^(prod|preprod|test)$", var.environment.environment))
    error_message = "The environment variable can only be set to [prod|preprod|test]."
  }

  validation {
    condition     = var.environment.environment == "test" && length(var.environment.fet_code) != 3
    error_message = "The environment has been set to 'test' but the fet_code has not be defined."
  }
}
Run Code Online (Sandbox Code Playgroud)

然后您可以像这样传递变量:

environment = {
  environment = "test"
  fet_code = "1234"
}
Run Code Online (Sandbox Code Playgroud)


小智 5

我为自己找到的类似问题的最佳解决方案是将检查放入模块中。然后,仅当环境需要设置变量时才包含所述模块。

module input_validation {
    source   = "./modules/input_validation"
    count    = var.environment == "test" ? 1 : 0
    fet_code = var.fet_code
}
Run Code Online (Sandbox Code Playgroud)

然后在modules/input_validation/input_validation.tf中:

variable "fet_code" {
  default = ""
  type    = string
  validation {
    condition     = length(var.fet_code) != 3
    error_message = "The environment has been set to 'test' but the fet_code has not be defined."
  }
}
Run Code Online (Sandbox Code Playgroud)