我刚刚接触Terraform(如果这是一个愚蠢的问题,请道歉)。
我正在设置一个带有一组子网的azure vnet,每个子网都有一个通过防火墙发送流量的路由表。
看起来子网和路由表组合将构成一个良好的可重用模块。
按照惯例,我想在与父vnet相同的资源组和位置创建子网和路由表。
如果我将模块中所需的所有值都作为单独的值提供,那么模块可以正常工作:)
我宁愿做的是将代表父vnet的资源有效地作为“参数”传递给模块,让模块直接从vnet资源中读取资源组名称,位置和vnet名称等内容,这样那: - 我输入较少(我只使用vnet创建模块实例,而不是为vnet名称,资源组名称和位置创建单独的值) - 它在路由表和子网上设置位置和资源组名称时删除了出错的机会(如果我从模块中的父vnet读取值,则值将与父vnet相同)
目前,模块变量定义为:
variable "parent-vnet-name" {}
variable "parent-vnet-resource-group-name" {}
variable "parent-vnet-location" {}
variable "subnet-name" {
type = "string"
}
variable "subnet-address-prefix" {}
variable "firewall-ip-private" {}
和模块:
resource "azurerm_route_table" "rg-mgt-network__testtesttest" {
name = "${var.subnet-name}"
location = "${var.parent-vnet-location}"
resource_group_name = "${var.parent-vnet-resource-group-name}"
route {
name = "Default"
address_prefix = "0.0.0.0/0"
next_hop_type = "VirtualAppliance"
next_hop_in_ip_address = "${var.firewall-ip-private}"
}
}
我想做的更像是变量:
variable "parent-vnet" {}
variable "subnet-name" {
type = "string"
}
variable "subnet-address-prefix" {}
variable "firewall-ip-private" {}
模块执行类似:
resource "azurerm_route_table" "rg-mgt-network__testtesttest" {
name = "${var.subnet-name}"
location = "${var.parent-vnet.location}"
resource_group_name = "${var.parent-vnet.resource-group-name}"
route {
name = "Default"
address_prefix = "0.0.0.0/0"
next_hop_type = "VirtualAppliance"
next_hop_in_ip_address = "${var.firewall-ip-private}"
}
}
我玩过各种各样的事情(例如尝试传递vnet而不指定属性名称(验证失败)或使用数据源撤回vnet(数据源没有资源)小组信息))但没有任何地方,所以我想知道我是否错过了什么?
干杯,安迪
答案 0 :(得分:3)
这在Terraform> 0.12时是可能的。您可以使用object
类型,但是必须显式列出您在模块中使用的字段。
# module's variables.tf
variable "parent_vnet" {
# List each field in `azurerm_route_table` that your module will access
type = object({
name = string
location = string
resource_group_name = string
})
}
# caller
resource "azurerm_route_table" "my_parent_vnet" {
# ...
}
module "my-module" {
parent_vnet = azurerm_route_table.my_parent_vnet
}
答案 1 :(得分:2)
目前不可能 - 根据Terraform Creating Modules page,模块的输入变量只能是标准变量类型:string
,list
和map
。< / p>
我遇到了同样的用例,不得不提供大量的模块输入列表,这不是理想的,但似乎是世界的现状。
答案 2 :(得分:1)
如果您要避免传递其他资源的较长属性列表,可以使用data
资源来避免这种情况。
假设您需要模块“消费者”中的所有资源“提供者”属性,传入数据源的标识符,然后使用模块中的数据源获取所有属性。
resource "producer" {
id = "id"
}
module "consumer" {
second-module-id = resource.producer.id
}
在“消费”模块中,您现在可以使用数据源调用访问“生产者”的所有属性(前提是您的云提供商具有数据源):
data "producer-data" {
id = second-module-id
}
resource "resource" {
prop1 = data.prop1
prop2 = data.prop2
...
}