在Terraform中使用嵌套变量的正确方法

时间:2019-11-20 13:14:41

标签: terraform terraform-provider-azure

在我的Terraform脚本中,我有

let billable = { aanwezig: "Aanwezig", hours: 12 }
if (!this.urenRegistratie.some(x => x.aanwezig == billable.aanwezig && x.hours == billable.hours)) {
  this.urenRegistratie.push(billable);
}

我运行resource "azuread_application" "main" { count = "${length(var.sp_names)}" name = "${sp_prefix}-${var.sp_names[count.index]}" available_to_other_tenants = false } resource "azuread_service_principal" "main" { count = "${length(var.sp_names)}" application_id = "${azuread_application.main.["${sp_prefix}"-"${var.sp_names[count.index]}"].application_id}" } 时遇到以下错误:

  

点名后需要属性名称。

使用嵌套变量和列表对象的正确方法是什么?

2 个答案:

答案 0 :(得分:0)

为了将资源表示为实例映射而不是实例列表,您需要使用for_each而不是count

resource "azuread_application" "main" {
  for_each = { for n in var.sp_names : n => "${var.sp_prefix}-${n}" }

  name                       = each.value
  available_to_other_tenants = false
}

上面的for_each表达式是for expression,它将您的列表或名称集转换为从给定名称到前缀名称的映射。因此,在该块的其他表达式中,each.key将产生原始给定名称,而each.value将产生前缀名称。

然后,您可以类似地使用for_each来声明意图“通过为应用程序创建一个服务主体”,方法是将应用程序资源的映射本身用作服务主体资源的for_each表达式:

resource "azuread_service_principal" "main" {
  for_each = azuread_application.main

  application_id  = each.value.application_id
}

在这种情况下,azuread_application.main值是从无前缀名称到代表每个已声明应用程序的对象的映射。因此, this 块中的each.key仍然是未前缀的名称,而each.value是我们可以从中访问application_id值的相应应用程序对象。

如果您的var.sp_names中包含字符串"example",则Terraform会将以上内容解释为创建两个名为azuread_application.main["example"]azuread_service_principal.main["example"]的对象的请求,以标识这些实例通过var.sp_names值。这与count不同,在azuread_application.main[0]中,实例的地址将类似于azuread_service_principal.main[0]for_each。通过使用var.sp_names,我们确保从return ''.join(y) 添加和删除项目将在这些资源中添加和删除相应的实例,而不是更新碰巧共享相同数字索引的现有实例。

答案 1 :(得分:0)

我假设您使用的版本早于0.12.x。如果不是,马丁的答案是最好的。

您需要利用喷溅。

resource "azuread_service_principal" "main" {
  count           = "${length(var.sp_names)}"
  application_id  = "${azuread_application.main.*.application_id}"
}