Azure terraform 报告缺少资源实例密钥
Azure terraform reports Missing resource instance key
我有一个 Terraform 模块,如下所示
main.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]
我无法理解实际错误是什么以及如何纠正它。
您的错误消息中显示的源代码片段与您为 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
值。如果您的目标是 return 所有资源组的所有名称的列表,您可以将其写为 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
instead of 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 to obtain them. We'll also use 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
一起使用,以便为每个资源组生成一个对象。
我有一个 Terraform 模块,如下所示
main.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]
我无法理解实际错误是什么以及如何纠正它。
您的错误消息中显示的源代码片段与您为 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
值。如果您的目标是 return 所有资源组的所有名称的列表,您可以将其写为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
instead of 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 to obtain them. We'll also use 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
一起使用,以便为每个资源组生成一个对象。