【问题标题】:Terraform assign default to local variableTerraform 将默认值分配给局部变量
【发布时间】:2020-07-10 11:38:03
【问题描述】:

我的 variables.tfvars 中有以下代码:

variable "is_premium_service_bus_required" {
  description = "When set to 1, premium service bus will be created"
  type        = "string"
  default     = "0"
}

variable "service_bus_type_cloud" {
  description = "Type of service bus to be created, value can only be standard or premium"
  type        = "string"
}

以下代码创建 azure 资源:

resource "azurerm_servicebus_namespace" "premium-ffdac-cloud-servicebus" {
  count               = "${var.is_premium_service_bus_required}"
  name                = "${terraform.workspace}-ffdac-cloud-sbus"
  location            = "west europe"
  resource_group_name = "fusson"
  sku                 = "Premium"
  capacity            = "1"   
}

resource "azurerm_servicebus_namespace" "ffdac-cloud-servicebus" {
  name                = "${terraform.workspace}-ffdac-cloud-servicebus"
  location            = "west europe"
  resource_group_name = "fusson"
  sku                 = "Standard"
}

可以看出,我们通过将变量值 is_premium_service_bus_required 设置为 0(未创建)或 1(已创建)来操纵 Azure 上资源的创建

我有以下局部变量:

locals {
  standard_service_bus_cloud_connection_string = "${azurerm_servicebus_namespace.ffdac-cloud-servicebus.default_primary_connection_string};TransportType=Amqp"
}


locals {
  premium_service_bus_cloud_connection_string = "${azurerm_servicebus_namespace.premium-ffdac-cloud-servicebus.default_primary_connection_string};TransportType=Amqp"
}

它只负责操作默认连接字符串并在末尾添加协议。

我们有以下代码,它根据“service_bus_type_cloud”的值确定应该为“service_bus_cloud_connection_string”变量分配什么值,该变量稍后会在不同的 terraform 文件中使用。

locals {
  service_bus_type_cloud_names = {
    "premium"  = "${local.premium_service_bus_cloud_connection_string}"
    "standard" = "${local.standard_service_bus_cloud_connection_string}"
  }

  cloud_connection_string_default = "${local.standard_service_bus_cloud_connection_string}"

  service_bus_cloud_connection_string = "${lookup(local.service_bus_type_cloud_names, var.service_bus_type_cloud, local.cloud_connection_string_default)}"
}

现在的问题是,当 "is_premium_service_bus_required" 的值设置为 "0" 时,高级服务总线 azure 服务没有创建并且本地变量 "premium_service_bus_cloud_connection_string" 值为空,我们最终得到以下错误:

Error: Error running plan: 1 errors occurred:
    * local.premium_service_bus_cloud_connection_string: local.premium_service_bus_cloud_connection_string: Resource 'azurerm_servicebus_namespace.premium-ffdac-cloud-servicebus' not found for variable 'azurerm_servicebus_namespace.premium-ffdac-cloud-servicebus.default_primary_connection_string'

有没有办法绕过这个错误或重写逻辑的更好方法?我们正在运行 Terraform 版本 0.11,因此提到的条件运算符 here 不能用作使用以下代码:

locals {
  service_bus_cloud_connection_string = "${var.service_bus_type_cloud == "premium" ? "${azurerm_servicebus_namespace.premium-ffdac-cloud-servicebus.default_primary_connection_string};TransportType=Amqp" : "${azurerm_servicebus_namespace.ffdac-cloud-servicebus.default_primary_connection_string};TransportType=Amqp"}"
}

将评估这两个值表达式,即使只返回一个,并且它似乎是在 0.12 中修复的错误,如 here 所见@

【问题讨论】:

  • 条件运算符?(或三元)早在 Terraform 0.8 中就被引入了。 0.12 增加了一些关于惰性评估的改进,但它没有添加。
  • 条件运算符的 Terraform 0.11 变体在 Terraform 0.11“插值”页面中记录为 Conditionals
  • 您需要提供整个 Terraform 代码,以便我们找出导致错误的原因。
  • @MartinAtkins 谢谢,我读完了。
  • @CharlesXu 我添加了缺少的代码来创建天蓝色资源

标签: azure terraform terraform-provider-azure terraform0.11


【解决方案1】:

您仍然可以使用条件句 (Terraform v0.11.14)。这是代码。

variable "is_premium_service_bus_required" {
  description = "When set to 1, premium service bus will be created"
  type = "string"
  default     = "0"
}

locals {
  standard_service_bus_cloud_connection_string = "${var.is_premium_service_bus_required == "0" ? "non_premium_connection_string" : "premium_connection_string"}"
}

output "is_required" {
  value = "${local.standard_service_bus_cloud_connection_string}"
}

这是输出。

[PS][7.0.2] tst > terraform11.exe apply -var "is_premium_service_bus_required=0"

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

is_required = non_premium_connection_string


[PS][7.0.2] tst > terraform11.exe apply -var "is_premium_service_bus_required=1"

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

is_required = premium_connection_string

【讨论】:

    【解决方案2】:

    如我所见,您想根据条件创建具有不同类型的服务总线。然后获取服务总线的连接字符串。我不知道是标准类型是必要的。我认为没有必要。然后你可以改成这样:

    variable "is_premium_service_bus_required" {
      description = "When set to 1, premium service bus will be created"
      type        = "bool"
      default     = true
    }
    
    resource "azurerm_servicebus_namespace" "ffdac-cloud-servicebus" {
      count               = "${var.is_premium_service_bus_required}" ? 1 : 0
      name                = "${terraform.workspace}-ffdac-cloud-servicebus"
      location            = "west europe"
      resource_group_name = "fusson"
      sku                 = "${var.is_premium_service_bus_required}" ? "Premium" : "Standard"
    }
    

    在这种情况下,您可以直接使用"${azurerm_servicebus_namespace.ffdac-cloud-servicebus.default_primary_connection_string};TransportType=Amqp" 获取连接字符串,如您在代码中显示的那样。

    但如果需要标准类型,那就稍微复杂一点:

    variable "is_premium_service_bus_required" {
      description = "When set to 1, premium service bus will be created"
      type        = "bool"
      default     = true
    }
    
    variable "service_bus_type_cloud" {
      description = "Type of service bus to be created, value can only be standard or premium"
      type        = "string"
    }
    
    resource "azurerm_servicebus_namespace" "premium-ffdac-cloud-servicebus" {
      count               = "${var.is_premium_service_bus_required}" ? 1 : 0
      name                = "${terraform.workspace}-ffdac-cloud-sbus"
      location            = "west europe"
      resource_group_name = "fusson"
      sku                 = "Premium"
      capacity            = "1"   
    }
    
    resource "azurerm_servicebus_namespace" "ffdac-cloud-servicebus" {
      name                = "${terraform.workspace}-ffdac-cloud-servicebus"
      location            = "west europe"
      resource_group_name = "fusson"
      sku                 = "Standard"
    }
    
    locals {
      service_bus_cloud_connection_string = "${var.is_premium_service_bus_required}" && "${var.service_bus_type_cloud}" == "premium" ? "${azurerm_servicebus_namespace.premium-ffdac-cloud-servicebus[0].default_primary_connection_string};TransportType=Amqp" : "${azurerm_servicebus_namespace.ffdac-cloud-servicebus.default_primary_connection_string};TransportType=Amqp"
    }
    

    在这种情况下,只有当变量is_premium_service_bus_required为真且变量service_bus_type_cloud为“premium”时,你才能得到premium service bus连接字符串,否则你会得到标准。

    【讨论】:

    • 谢谢,我尝试运行您的建议,但我收到以下错误:Failed to load backend: Error loading backend config: Error parsing /Users/.../variables_service_bus.tf: At 20:44: expected: IDENT | STRING got: LBRACE 是的,要求是同时具有高级和标准,这就是复杂性出现的地方。
    • 我能够解决这个问题,整个条件语句需要在"${..}" 内,但我现在又收到一个错误:Error: Error loading /.../variables_service_bus.tf: Variable 'is_premium_service_bus_required' type must be one of [string, map, list] - 'bool' is not a valid type
    • 所以,我删除了type = "bool",它最终给出了同样的错误:* local.service_bus_cloud_connection_string: local.service_bus_cloud_connection_string: Resource 'azurerm_servicebus_namespace.premium-ffdac-cloud-servicebus' not found for variable 'azurerm_servicebus_namespace.premium-ffdac-cloud-servicebus.default_primary_connection_string' with is_premium_service_bus_required set to false
    • 将本地更改为service_bus_cloud_connection_string = "${var.is_premium_service_bus_required}" == "premium" ? "${azurerm_servicebus_namespace.premium-ffdac-cloud-servicebus[0].default_primary_connection_string};TransportType=Amqp" : "${azurerm_servicebus_namespace.ffdac-cloud-servicebus.default_primary_connection_string};TransportType=Amqp" 或者您是否尝试过以下答案?
    • @Spaniard89 Terraform 0.12 及更高版本支持布尔类型。而且这个版本支持的功能更多,所以推荐给大家。示例代码在我的测试中也适用于这个版本。
    【解决方案3】:

    应该更容易只创建一个对象并根据输入变量调整参数。拥有一张包含标准参数和高级参数的地图。

    【讨论】:

    • 能否提供代码示例?只是一个 sn-p 会有所帮助。我可以试试看。
    猜你喜欢
    • 2015-01-19
    • 2019-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多