Terraform,资源可以作为变量传递到模块中吗?

Terraform,资源可以作为变量传递到模块中吗?,terraform,Terraform,我刚刚开始研究Terraform(如果这是一个愚蠢的问题,我深表歉意) 我正在用一组子网建立一个azure vnet,每个子网都有一个路由表,通过防火墙发送流量 看起来子网和路由表的组合将成为一个很好的可重用模块 按照惯例,我希望在与父vnet相同的资源组和位置中创建子网和路由表 如果我将模块中需要的所有值作为单个值提供,则模块正常工作:) 我更愿意做的是将表示父vnet的资源作为“参数”有效地传递到模块中,并让模块直接从vnet资源读取资源组名称、位置和vnet名称,以便: -我输入更少(我只

我刚刚开始研究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(数据源没有资源组信息)),但是我什么都没有,所以我想知道我是否错过了什么


干杯,安迪

这目前是不可能的-根据,模块的输入变量只能是标准变量类型:
字符串
列表
,和
映射


我遇到过同样的用例,不得不向模块提供大量的输入列表,这并不理想,但似乎是当前世界的现状。

这在terraform>0.12中是可能的。您可以使用
对象
类型,但必须明确列出模块中使用的字段

# 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
}

如果要避免传递其他资源的长属性列表,可以使用
data
资源来避免传递

假设您需要模块“使用者”中的所有资源“提供者”属性,传入数据源的标识符,然后使用模块中的数据源获取所有属性

resource "producer" {
id = "id"
}

module "consumer" {
 second-module-id = resource.producer.id
}
在“消费”模块中,您现在可以使用数据源调用access“生产者”的所有属性(前提是您的云提供商有数据源):


到目前为止你能分享你的代码吗?如果您有一些不同的选择,请给出每个和硬件的最小示例,它们不适合您。添加了示例。干杯,你是在同时创建路由表和虚拟网络吗?或者您是否使用单独的应用命令来构建它们?随着时间的推移,将添加新的子网-因此它们将是单独的应用命令在您的示例中,路由表和虚拟网络之间似乎没有明显的联系(我不太了解Azure)但是,您不只是传入虚拟网络恰好所在的资源组名称和位置吗?但是我不明白为什么路由表资源甚至需要指定位置,而不是从资源组中提取它并简化API。谢谢,这是有意义的。我希望有一种方法可以将资源转换为映射,并将映射用作变量值,但似乎只能获取资源属性列表。我只是在学习(所以我可能不知道我在说什么),但我通过将变量类型(在模块中)指定为字符串来实现,我们已经开始使用“数据”资源,它们很有用,但是您不能将它们用于“在同一次运行中”创建的资源。我们已经决定直接引用资源(如果它们处于相同状态),或者使用Tf远程状态数据源直接引用不同状态文件中的属性。使用“数据”时,您可以在“模块”中的“depends_on”块中指定要传递给模块的资源块这允许Terraform首先创建模块所依赖的所有资源,然后将它们作为“数据”在模块内使用。
data "producer-data" {
id = second-module-id
}

resource "resource" {
  prop1 = data.prop1
  prop2 = data.prop2
  ...
}