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

问题描述 投票:0回答:3

我刚刚开始掌握 Terraform(如果这是一个愚蠢的问题,我深表歉意)。

我正在设置一个带有一组子网的天蓝色虚拟网络,每个子网都有一个通过防火墙发送流量的路由表。

看起来子网和路由表的组合将成为一个很好的可重用模块。

按照惯例,我想在与父 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
3个回答
57
投票

这在 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
}

6
投票

编辑:请参阅https://stackoverflow.com/a/57963406/866021获取更新的答案

目前这是不可能的 - 根据 Terraform 创建模块页面,模块的输入变量只能是标准变量类型:

string
list
map

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


5
投票

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

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
  ...
}
© www.soinside.com 2019 - 2024. All rights reserved.