如何在Terraform中引用对象

时间:2019-07-03 00:38:41

标签: azure terraform

我正在使用terraform创建一个Azure VNet,并在其中创建几个子网。稍后,我想创建一个网络接口,并将其放在为VNet已经创建的子网之一中。我不知道如何引用该子网。

我在下面尝试过,但是现在可以使用了:

subnet_id = "${azurerm_virtual_network.virtual-network.subnet.ServersSubnet.id}"

resource "azurerm_virtual_network" "virtual-network" {
    name                = "${var.ClientShortName}-az-network"
    address_space       = ["${local.AzureInfraNetwork}"]
    location            = "${var.resource-location}"
    resource_group_name =  "${azurerm_resource_group.test-resource-group.name}"

subnet {
    name           = "ServersSubnet"
    address_prefix = "${local.ServersSubnet}"
}

subnet {
    name           = "GatewaySubnet"
    address_prefix = "${local.GatewaySubnet}"
} 
}

错误:无法索引设置值

在main.tf行120上的资源“ azurerm_network_interface”“ DCNIC”中:  120:subnet_id =“ $ {azurerm_virtual_network.virtual-network.subnet.ServersSubnet.id}”

块类型“子网”由一组对象表示,而设置元素则 没有可寻址的密钥。要查找符合特定条件的元素,请使用 带有“ if”子句的“ for”表达式。

4 个答案:

答案 0 :(得分:1)

将子网创建为块时,必须使用列表语法引用它们,例如:

foo = azurerm_virtual_network.virtual-network.subnet[0].id
bar = azurerm_virtual_network.virtual-network.subnet[1].id

如果子网形成了冗余资源池,并且您并不特别在意引用任何子网,这将很有用。

我不认为这是您的情况,因此您可以考虑将子网创建为单独的资源,例如:

resource "azurerm_virtual_network" "main" {
    name                = "${var.ClientShortName}-az-network"
    address_space       = [local.AzureInfraNetwork]
    location            = var.resource-location
    resource_group_name = azurerm_resource_group.test-resource-group.name
}

resource "azurerm_subnet" "server" {
    virtual_network_name  = azurerm_virtual_network.main.name
    name                  = "ServersSubnet"
    address_prefix        = local.ServersSubnet
}

resource "azurerm_subnet" "gateway" {
    virtual_network_name  = azurerm_virtual_network.main.name
    name                  = "GatewaySubnet"
    address_prefix        = local.ServersSubnet
}

然后,您可以使用常规对象属性语法引用一个子网:

foo = azurerm_subnet.server.id

还要注意,我使用的是terraform => 0.12语法,因此在不需要字符串插值时可以写foo.bar而不是"${foo.bar}"

答案 1 :(得分:1)

如果其他人需要答案,请使用此

“ $ {element(azuread_application.events_backend.app_role [*]。id,0)}”

答案 2 :(得分:1)

下面是完整的解决方案。

如果将子网创建为块,则可以按如下所示引用给定子网的资源ID:

resource "azurerm_resource_group" "main" {
  name     = "vnet-rg"
  location = "eastus"
}

resource "azurerm_virtual_network" "main" {
  name                = "my-vnet"
  location            = azurerm_resource_group.main.location
  resource_group_name = azurerm_resource_group.main.name
  address_space       = ["10.0.0.0/16"]

  subnet {
    name           = "subnet1"
    address_prefix = "10.0.1.0/24"
  }

  subnet {
    name           = "subnet2"
    address_prefix = "10.0.2.0/24"
  }

  subnet {
    name           = "subnet3"
    address_prefix = "10.0.3.0/24"
  }

}

output "subnet1_id" {
  value = azurerm_virtual_network.main.subnet.*.id[0]
}

output "subnet2_id" {
  value = azurerm_virtual_network.main.subnet.*.id[1]
}

output "subnet3_id" {
  value = azurerm_virtual_network.main.subnet.*.id[2]
}

答案 3 :(得分:0)

您可以将其分解为将虚拟网络和子网创建为单独的资源。这样做的好处是您可以将您的子网作为映射而不是列表返回,这样以后可以更轻松地按名称检索,如果您需要在稍后阶段添加/删除子网,也可以使其稳定。

locals {
  subnets = {
    Servers = "10.0.1.0/24",
    Gateway = "10.0.2.0/24"
  }
}

resource "azurerm_resource_group" "main" {
  name     = "vnet-rg"
  location = "eastus"
}

resource "azurerm_virtual_network" "main" {
  name                = "my-vnet"
  location            = azurerm_resource_group.main.location
  resource_group_name = azurerm_resource_group.main.name
  address_space       = [ local.AzureInfraNetwork ]    
}

resource "azurerm_subnet" "main" {
  for_each = var.subnets

  name                 = "${each.key}-subnet"
  resource_group_name  = azurerm_resource_group.main.name
  virtual_network_name = azurerm_virtual_network.main.name
  address_prefixes     = [ each.value ]
}

output "subnets" {
  value = azurerm_subnet.main
}