Terraform 对象中存在每个值时的地形

Terraform 对象中存在每个值时的地形,terraform,terraform0.12+,Terraform,Terraform0.12+,我想从.tfvars文件动态创建一些子网和路由表,然后将每个子网链接到关联的路由表(如果指定) 这是我的.tfvars文件: vnet_spoke_object = { specialsubnets = { Subnet_1 = { name = "test1"

我想从.tfvars文件动态创建一些子网和路由表,然后将每个子网链接到关联的路由表(如果指定)

这是我的.tfvars文件:

vnet_spoke_object                      = {
    specialsubnets                     = {
        Subnet_1                       = {
            name                       = "test1"
            cidr                       = ["10.0.0.0/28"]
            route                      = "route1"
        }
        Subnet_2                       = {
            name                       = "test2"
            cidr                       = ["10.0.0.16/28"]
            route                      = "route2"
        }
        Subnet_3                       = {
            name                       = "test3"
            cidr                       = ["10.0.0.32/28"]
        }
    }
}

route_table                            = {
    route1                             = {
        name                           = "route1"
        disable_bgp_route_propagation  = true
        route_entries                  = {
            re1                        = {
                name                   = "rt-rfc-10-28"
                prefix                 = "10.0.0.0/28"
                next_hop_type          = "VirtualAppliance"
                next_hop_in_ip_address = "10.0.0.10"
            }
        }
    }
    route2                             = {
        name                           = "route2"
        disable_bgp_route_propagation  = true
        route_entries                  = {
            re1                        = {
                name                   = "rt-rfc-10-28"
                prefix                 = "10.0.0.16/28"
                next_hop_type          = "VirtualAppliance"
                next_hop_in_ip_address = "10.0.0.10"
            }
        }
    }
}
…下面是我的构建脚本:

provider "azurerm" {
    version                        = "2.18.0"
    features{}
}

variable "ARM_LOCATION" {
    default                        = "uksouth"
}

variable "ARM_SUBSCRIPTION_ID" {
    default                        = "asdf-b31e023c78b8"
}

variable "vnet_spoke_object" {}
variable "route_table" {}

module "names" {
    source                         = "./nbs-azure-naming-standard"
    env                            = "dev"
    location                       = var.ARM_LOCATION
    subId                          = var.ARM_SUBSCRIPTION_ID
}

resource "azurerm_resource_group" "test" {
    name                           = "${module.names.standard["resource-group"]}-vnet"
    location                       = var.ARM_LOCATION
}

resource "azurerm_virtual_network" "test" {
    name                           = "${module.names.standard["virtual-network"]}-test"
    location                       = var.ARM_LOCATION
    resource_group_name            = azurerm_resource_group.test.name
    address_space                  = ["10.0.0.0/16"]
}

resource "azurerm_subnet" "test" {
    for_each                       = var.vnet_spoke_object.specialsubnets
    name                           = "${module.names.standard["subnet"]}-${each.value.name}"
    resource_group_name            = azurerm_resource_group.test.name
    virtual_network_name           = azurerm_virtual_network.test.name
    address_prefixes               = each.value.cidr
}

resource "azurerm_route_table" "test" {
    for_each                       = var.route_table
    name                           = "${module.names.standard["route-table"]}-${each.value.name}"
    location                       = var.ARM_LOCATION
    resource_group_name            = azurerm_resource_group.test.name
    disable_bgp_route_propagation  = each.value.disable_bgp_route_propagation
    dynamic "route" {
        for_each                   = each.value.route_entries
        content {
            name                   = route.value.name
            address_prefix         = route.value.prefix
            next_hop_type          = route.value.next_hop_type
            next_hop_in_ip_address = contains(keys(route.value), "next_hop_in_ip_address") ? route.value.next_hop_in_ip_address: null
        }
    }
}
这一部分在创建vnet/subnet/route资源时工作得很好,但我面临的问题是将每个子网动态链接到.tfvars中列出的路由表。并非所有子网都有与之关联的路由表,因此仅当列出键/值路由时才需要运行

resource "azurerm_subnet_route_table_association" "test" {
    for_each                       = {
        for key, value in var.vnet_spoke_object.specialsubnets:
            key => value
            if value.route != null
    }

    lifecycle {
        ignore_changes             = [
            subnet_id
        ]
    }
    subnet_id                      = azurerm_subnet.test[each.key].id
    route_table_id                 = azurerm_route_table.test[each.key].id
}
我在上述代码中遇到的错误是:

Error: Unsupported attribute

  on main.tf line 65, in resource "azurerm_subnet_route_table_association" "test":
  65:             if value.route != null

This object does not have an attribute named "route".

我尝试了各种方法,但都没有成功,我在这里不知所措,希望能提供任何指导。

根据您的场景,我猜输入中的vnet_speak_对象如下所示:

vnet_spoke_object = {
  specialsubnets = {
    subnetA = {
      cidr  = "..."
    }
    subnetB = {
      cidr  = "..."
      route = "..."
    }
  }
}
for_each                       = {
    for key, value in var.vnet_spoke_object.specialsubnets:
        key => value
        if lookup(value, "route", null) != null
}
问题是丢失的路由条目不能解析为null,它会导致恐慌或崩溃。您需要像这样使用显式空值编写输入:

或按名称路由,并在for map generator表达式中提供空默认值,如下所示:

vnet_spoke_object = {
  specialsubnets = {
    subnetA = {
      cidr  = "..."
    }
    subnetB = {
      cidr  = "..."
      route = "..."
    }
  }
}
for_each                       = {
    for key, value in var.vnet_spoke_object.specialsubnets:
        key => value
        if lookup(value, "route", null) != null
}

根据您的场景,我猜输入中的vnet_speak_对象如下所示:

vnet_spoke_object = {
  specialsubnets = {
    subnetA = {
      cidr  = "..."
    }
    subnetB = {
      cidr  = "..."
      route = "..."
    }
  }
}
for_each                       = {
    for key, value in var.vnet_spoke_object.specialsubnets:
        key => value
        if lookup(value, "route", null) != null
}
问题是丢失的路由条目不能解析为null,它会导致恐慌或崩溃。您需要像这样使用显式空值编写输入:

或按名称路由,并在for map generator表达式中提供空默认值,如下所示:

vnet_spoke_object = {
  specialsubnets = {
    subnetA = {
      cidr  = "..."
    }
    subnetB = {
      cidr  = "..."
      route = "..."
    }
  }
}
for_each                       = {
    for key, value in var.vnet_spoke_object.specialsubnets:
        key => value
        if lookup(value, "route", null) != null
}

非常感谢。my.tfvars中的null部分是修复方法:DYou可以通过在变量上设置一个更明确的值,如type=mapobject{cidr=string,route=string},然后Terraform将在.tfvars文件中报告该值,如果它没有同时设置这两个属性,而不是在模块的实现中失败。谢谢。my.tfvars中的null部分是修复方法:DYou可以通过在变量上设置一个更明确的值,如type=mapobject{cidr=string,route=string},然后Terraform将在.tfvars文件中报告该值,如果它没有同时设置这两个属性,则该值无效,而不是在模块的实现中失败。