首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果对象中存在值,则为Terraform for_each

如果对象中存在值,则为Terraform for_each
EN

Stack Overflow用户
提问于 2020-07-11 10:44:39
回答 1查看 8.8K关注 0票数 2

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

这是我的.tfvars文件:

代码语言:javascript
复制
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"
            }
        }
    }
}

...and这里是我的构建脚本:

代码语言:javascript
复制
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/子网/路由资源方面运行良好,但我面临的问题是将每个子网动态链接到.tfvars中列出的路由表。并非所有子网都有与其关联的路由表,因此,如果列出了键/值route,则只需要运行route

代码语言:javascript
复制
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
}

我在上述代码中遇到的错误是:

代码语言:javascript
复制
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".

我尝试过不同的方法,但没有成功,我在这里感到困惑,并将感谢任何指导的可能性。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-11 14:29:36

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

代码语言:javascript
复制
vnet_spoke_object = {
  specialsubnets = {
    subnetA = {
      cidr  = "..."
    }
    subnetB = {
      cidr  = "..."
      route = "..."
    }
  }
}

问题是缺少的路由条目不能解析为,它会造成恐慌或崩溃。您需要像这样编写输入(使用显式):

代码语言:javascript
复制
vnet_spoke_object = {
  specialsubnets = {
    subnetA = {
      cidr  = "..."
      route = null
    }
    subnetB = {
      cidr  = "..."
      route = "..."
    }
  }
}

或者查找 按名称路由,并在for生成器表达式中提供null默认值,如下所示:

代码语言:javascript
复制
for_each                       = {
    for key, value in var.vnet_spoke_object.specialsubnets:
        key => value
        if lookup(value, "route", null) != null
}
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62848141

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档