【问题标题】:Azure terraform reports Missing resource instance keyAzure terraform 报告缺少资源实例密钥
【发布时间】:2019-11-12 01:53:43
【问题描述】:

我有一个 Terraform 模块,如下所示

ma​​in.tf

resource "azurerm_resource_group" "test1"{
    count    = "${length(var.azurerm_resource_group_name)}"
    name     = "${element(var.azurerm_resource_group_name, count.index)}"
    location = "${element(var.azurerm_resource_group_location, count.index)}"
}

我已将 output.tf 定义如下

output "resource_gp" {
    value = "${azurerm_resource_group.test1[count.index]}"
}

对于同一个模块,variables.tf如下:

variable "azurerm_resource_group_name" {
    type = "list"
    default = ["SimpleMoon-Terra"]
}
variable "azurerm_resource_group_location" {
    type = "list"
    default = ["Central US"]
}

调用模块如下:

variable "azurerm_resource_group" {

    default={
    name     = "simpletestrg"
    location = "Central US"
    }
}

# Create Resource Group
module "Test_Resource_Groups" {
    source ="../../Modules/Test_Resource_Groups"
    #name                ="${var.azurerm_resource_group.name}"
    #location            ="${var.azurerm_resource_group.location}"
}

但是,我收到如下错误:

Error: Missing resource instance key

  on ../../Modules/Test_Resource_Groups/output.tf line 2, in output "resource_gp":
   2:     value = "${azurerm_resource_group.test1.name[count.index]}"

Because azurerm_resource_group.test1 has "count" set, its attributes must be
accessed on specific instances.

For example, to correlate with indices of a referring resource, use:
    azurerm_resource_group.test1[count.index]

我无法理解实际的错误是什么以及如何纠正它。

【问题讨论】:

  • var.azurerm_resource_group_name 这一定是var.azurerm_resource_group?在 main.tf
  • 我不这么认为,我现在为模块添加了 variables.tf 文件。请再检查一次。泰
  • azurerm_resource_group.test1 是资源而不是导出的属性。您要输出什么导出属性?

标签: terraform terraform-provider-azure


【解决方案1】:

您的错误消息中显示的源代码 sn-p 与您为outputs.tf 共享的源代码不一致:

    value = "${azurerm_resource_group.test1.name[count.index]}" # in the error message
    value = "${azurerm_resource_group.test1[count.index]}"      # in the given source code

这里有几个问题,其中一个仅在错误信息中显示的源代码中:

  • 因为azurerm_resource_group.test1 设置了count,所以它在表达式中显示为对象列表。因此,应用于它的第一个操作必须是索引操作,给出类似azurerm_resource_group.test1[count.index].name 的表达式:取azurerm_resource_group.test1 列表的count.index 元素的name 属性。
  • 您不能在输出值表达式中使用count.index,因为范围内没有count 参数来知道要使用什么count.index 值。如果您的目标是返回所有资源组的所有名称的列表,则可以将其写为azurerm_resource_group.test1[*].name,即splat expression

在这种特殊情况下,output "resource_gp" 的值将始终与var.azurerm_resource_group_name 的值相同,因为名称是从那里填充的。但是,通过资源 进行的这种引用很有用,因为它告诉 Terraform 引用该输出值的任何内容都必须反过来依赖于 azurerm_resource_group.test1,从而有助于确保应用所有操作以适当的顺序。


有一种不同的方式来编写您在此处编写的内容,这将在初始创建时获得类似的结果,但对于随后对var.azurerm_resource_group_name 的更改也能更好地工作。

首先,我们将变量定义为对象映射,这样我们就可以只使用一个变量来指定资源组。

variable "azurerm_resource_groups" {
  type = map(object({
    location = string
  }))
  default = {
    SimpleMoon-Terra = {
      location = "Central US"
    }
  }
}

然后我们可以在定义资源组时使用for_each而不是count

resource "azurerm_resource_group" "test1"{
  for_each = var.azurerm_resource_groups

  name     = each.key
  location = each.value.location
}

除了使表达式更简单之外,这还有另一个重要作用:Terraform 将识别地址为 azurerm_resource_group.test1["SimpleMoon-Terra"] 而不是 azurerm_resource_group.test1[0] 的资源组,因此当您从 var.azurerm_resource_groups 添加和删除项目时,Terraform 可以保留跟踪哪个远程资源组对象属于映射的哪个元素。

for_each 也会导致azurerm_resource_group.test1 在表达式中以映射而不是列表的形式出现,因此我们需要更改输出value 以使用它。因为映射键是资源组名称,所以我们可以使用the keys function 来获取它们。我们还将使用toset 将其转换为一个集合,反映这些没有任何特定顺序,因此该值的用户不应依赖于排序:

output "resource_group_names" {
  value = toset(keys(azurerm_resource_group.test1))
}

然后您的调用模块可以调用此模块,如下例所示:

module "test_resource_groups" {
  source = "../../Modules/Test_Resource_Groups"

  azurerm_resource_groups = {
    simpletestrg = {
      location = "Central US"
    }
  }
}

在该调用模块中,对module.test_resource_groups.resource_group_names 的引用将生成一组资源组名称,然后可以在配置中的其他位置与for_each 一起使用,从而为每个资源组生成一个对象。

【讨论】:

  • 真正惊人的反应。我还没消化。我会在这方面做更多的练习,并询问我是否需要任何进一步的帮助。
猜你喜欢
  • 2020-11-18
  • 1970-01-01
  • 1970-01-01
  • 2021-01-23
  • 1970-01-01
  • 1970-01-01
  • 2020-12-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多