如何将数据源从一个模块引用到另一个模块并将其作为变量传递给根模块?

Posted

技术标签:

【中文标题】如何将数据源从一个模块引用到另一个模块并将其作为变量传递给根模块?【英文标题】:How to reference a data source from a module to another module and pass it as a variable to root module? 【发布时间】:2020-03-23 16:08:11 【问题描述】:

我的 terraform 目录结构如下:

terraform/
main.tf  modules  outputs.tf  provider.tf  variables.tf

./modules:
compute  network  resourcegroup

./modules/compute:
main.tf  outputs.tf  variables.tf

./modules/network:
main.tf  outputs.tf  variables.tf

./modules/resourcegroup:
main.tf  outputs.tf  variables.tf

resourcegroup模块配置文件如下:

目的:在这个模块中,我引用了一个现有资源组,我想利用它来创建虚拟机及其关联对象。

ma​​in.tf

data "azurerm_resource_group" "tf-rg-external" 
  name = var.rg_name

variables.tf

variable "rg_name" 
  type = string


网络模块

目的:我想使用资源组模块中的资源组在这个模块中被引用。这样,我在一个地方定义并在 root 和其他模块例如计算、应用服务、aks 等中使用它

ma​​in.tf

# Reference existing Virtual Network
data "azurerm_virtual_network" "tf-vn" 
  name                = var.vnet_name
  resource_group_name = module.resource_groups.external_rg_name


# Reference existing subnet
data "azurerm_subnet" "tf-sn" 
  name                 = var.subnet_name
  virtual_network_name = data.azurerm_virtual_network.tf-vn.name
  resource_group_name  = module.resource_groups.external_rg_name

variables.tf

# Declare env variable
variable "vnet_name" 
  type = string


variable "subnet_name" 
  type = string

计算模块。

目的:定义计算(VM)的所有属性。这个想法是,根模块将使用这个模块来启动不同的 VM 角色。

ma​​in.tf

module "vm_iis" 
  source                        = "Azure/compute/azurerm"
  location                      = data.resourcegroup.tf-rg-external.location
  vnet_subnet_id                = data.network.tf-sn.id
  admin_password                = var.admin_password
  data_sa_type                  = var.data_sa_type
  delete_os_disk_on_termination = var.delete_os_disk_on_termination
  nb_instances                 = var.nb_instances
  nb_public_ip                 = var.nb_public_ip
  public_ip_address_allocation = var.public_ip_address_allocation
  resource_group_name          = data.resourcegroup.tf-rg-external.name
  .
  .
  .

variables.tf

variable "admin_password" 
  type = string

variable "admin_username" 
  type = string

variable "boot_diagnostics" 
  type = bool

variable "boot_diagnostics_sa_type" 
  type = string
...

terraform 根模块。

目的:这应该利用定义的模块来创建各种不同大小和主机名的虚拟机

ma​​in.tf:

module "sql_vm" 
  source                        = "./modules/compute/"
  #location                      = data.resourcegroup.tf-rg-external.location
  #vnet_subnet_id                = data.network.tf-sn.id
  public_ip_address_allocation  = var.public_ip_address_allocation
  #resource_group_name          = data.resourcegroup.tf-rg-external.name
  storage_account_type          = var.storage_account_type
  vm_hostname                   = var.vm_hostname

variables.tf:ma​​in.tf文件中声明所有变量。

注意:我有意硬编码根模块主/变量文件中的变量。这只是让模块之间的通信正确。正确理解和使用模块的方法。

但是,当我在根模块中运行 terraform plan 时。我收到以下错误:

Error: Reference to undeclared resource

  on modules/compute/main.tf line 3, in module "vm_iis":
   3:   location                      = data.resourcegroup.tf-rg-external.location

A data resource "resourcegroup" "tf-rg-external" has not been declared in
sql_vm.


Error: Reference to undeclared resource

  on modules/compute/main.tf line 4, in module "vm_iis":
   4:   vnet_subnet_id                = data.network.tf-sn.id

A data resource "network" "tf-sn" has not been declared in sql_vm.


Error: Reference to undeclared resource

  on modules/compute/main.tf line 22, in module "vm_iis":
  22:   resource_group_name          = data.resourcegroup.tf-rg-external.name

A data resource "resourcegroup" "tf-rg-external" has not been declared in
sql_vm.

问题是什么以及如何解决?

另外,可以通过某个循环创建不同的(角色)虚拟机吗?例如 sql-vm、iis-vm、testvm、abcvm?将要改变的是它们的主机名和虚拟机大小。

===========

发布答案更改

===========

我更新了子网、资源组和位置的值 compute/main.tfterraform/main.tf 如下:

location                      = module.resourcegroup.tf-rg-external-location
vnet_subnet_id                = module.network.subnet-id
resource_group_name           = module.resourcegroup.tf-rg-external-name

我在 resourcegroupnetwork 模块中的 outputs.tf 文件如下所示:

network模块的

outputs.tf

output "subnet-id" 
  value = "data.network.tf-sn.id"

resourcegroup 模块的

outputs.tf

output "tf-rg-external-location" 
  value = data.resourcegroup.tf-rg-external.location

output "tf-rg-external-name" 
  value = data.resourcegroup.tf-rg-external.name

不幸的是,我仍然遇到如下错误

Error: Unsupported argument

  on main.tf line 3, in module "sql_vm":
   3:   location                      = module.resourcegroup.tf-rg-external-location

An argument named "location" is not expected here.


Error: Unsupported argument

  on main.tf line 4, in module "sql_vm":
   4:   vnet_subnet_id                = module.network.subnet-id

An argument named "vnet_subnet_id" is not expected here.


Error: Unsupported argument

  on main.tf line 5, in module "sql_vm":
   5:   resource_group_name           = module.resourcegroup.tf-rg-external-name

An argument named "resource_group_name" is not expected here.

那么,看来我们不应该在根模块中引用它们?

另外,它们的变量应该在根模块 variables.tf 文件中定义,因为我相信您可以覆盖根模块中模块变量的值?

如果我显得愚蠢,请原谅我。我试图了解它在现实生活中是如何运作的。

上次提交和公开回购后,错误如下

Error: Reference to undeclared module

  on main.tf line 3, in module "sql_vm":
   3:   location                      = module.resourcegroup.tf-rg-external-location

No module call named "resourcegroup" is declared in the root module.


Error: Reference to undeclared module

  on main.tf line 4, in module "sql_vm":
   4:   vnet_subnet_id                = module.network.subnet-id

No module call named "network" is declared in the root module.


Error: Reference to undeclared module

  on main.tf line 5, in module "sql_vm":
   5:   resource_group_name           = module.resourcegroup.tf-rg-external-name

No module call named "resourcegroup" is declared in the root module.


Error: Reference to undeclared module

  on modules/compute/main.tf line 3, in module "vm_iis":
   3:   location                      = module.resourcegroup.tf-rg-external-location

No module call named "resourcegroup" is declared in sql_vm.


Error: Reference to undeclared module

  on modules/compute/main.tf line 4, in module "vm_iis":
   4:   vnet_subnet_id                = module.network.subnet-id

No module call named "network" is declared in sql_vm.


Error: Reference to undeclared module

  on modules/compute/main.tf line 5, in module "vm_iis":
   5:   resource_group_name           = module.resourcegroup.tf-rg-external-name

No module call named "resourcegroup" is declared in sql_vm.


Error: Reference to undeclared module

  on modules/network/main.tf line 5, in data "azurerm_virtual_network" "tf-vn":
   5:   resource_group_name = module.resource_groups.external_rg_name

No module call named "resource_groups" is declared in test2.


Error: Reference to undeclared resource

  on modules/resourcegroup/outputs.tf line 2, in output "tf-rg-external-location":
   2:   value = data.resourcegroup.tf-rg-external.location

A data resource "resourcegroup" "tf-rg-external" has not been declared in
test1.


Error: Reference to undeclared resource

  on modules/resourcegroup/outputs.tf line 5, in output "tf-rg-external-name":
   5:   value = data.resourcegroup.tf-rg-external.name

A data resource "resourcegroup" "tf-rg-external" has not been declared in
test1.

【问题讨论】:

我认为你需要仔细阅读答案,它说你需要定义输出,以便你可以参考你需要的资源。 我实际上做了,然后只运行了 terraform 计划,我没有将 output.tf 粘贴到我的问题帖子中。我将修改我的问题,以便您可以看到 output.tf。如果未定义 output.tf,它本身会报告不同的错误。 也许现在有意义了?我需要一些帮助,因为我无法根据 BMW Sir 提出的解决方案使其正常工作。 【参考方案1】:

浏览您正在处理的存储库 (https://github.com/ameyaagashe/help_me_cross/tree/d7485d2a3db339723e9c791e592b2f1dbc1f0788)。现在对我来说很有意义。

问题是,您将如何使用公共模块的想法与您自己创建的模块混为一谈。

事实上,您不需要设置任何模块来引用其他公共 terraform 注册表模块。

将子模块(模块/计算、模块/网络、模块/资源组)中的所有代码移动到顶部文件夹(<repo_root>/main.tf)。

如(代码未经验证,仅供参考)

data "azurerm_resource_group" "tf-rg-external" 
  name = var.rg_name


data "azurerm_virtual_network" "tf-vn" 
  name                = var.vnet_name
  resource_group_name = var.rg_name


# Reference existing subnet
data "azurerm_subnet" "tf-sn" 
  name                 = var.subnet_name
  virtual_network_name = data.azurerm_virtual_network.tf-vn.name
  resource_group_name  = var.rg_name


module "sql_vm" 
  source                        = "Azure/compute/azurerm"
  location                      = data.azurerm_resource_group.tf-rg-external.location
  vnet_subnet_id                = data.azurerm_virtual_network.tf-vn.subnets
  resource_group_name           = data.azurerm_resource_group.tf-rg-external.name
  admin_password                = var.admin_password
  admin_username                = var.admin_username
  boot_diagnostics              = var.boot_diagnostics
  boot_diagnostics_sa_type      = var.boot_diagnostics_sa_type
  data_disk                     = var.data_disk
  data_disk_size_gb             = var.data_disk_size_gb
  data_sa_type                  = var.data_sa_type
  delete_os_disk_on_termination = var.delete_os_disk_on_termination
  enable_accelerated_networking = var.enable_accelerated_networking
  # flag is_windows_image is required only when you use a custom image to spin up a VM
  # is_windows_image
  # flag vm_os_id is required only when you are using custom image
  # you need to provide id of your custom image
  # vm_os_id
  nb_instances                 = var.nb_instances
  nb_public_ip                 = var.nb_public_ip
  public_ip_address_allocation = var.public_ip_address_allocation
  storage_account_type         = var.storage_account_type
  vm_hostname                  = var.vm_hostname
  vm_os_offer                  = var.vm_os_offer
  vm_os_publisher              = var.vm_os_publisher
  # vm_os_simple is to be used is you do not wish to specify offer, publisher and sku
  # vm_os_simple                  = UbuntuServer, WindowsServer, RHEL, openSUSE-Leap, CentOS, Debian, CoreOS and SLES
  vm_os_sku     = var.vm_os_sku
  vm_os_version = var.vm_os_version
  vm_size       = var.vm_size

【讨论】:

先生,我现在已经用新的错误更新了我的问题,请指教。 我添加了答案,让我知道它是否可以解决您的问题。 先生,请协助。我的整个回购现在是公开的。 github.com/ameyaagashe/help_me_cross 现在说得通了。您根本不需要创建子模块。一切都应该在顶部。因为您尝试引用公共 terraform 注册表模块。我给你一些代码,看看我的更新。 非常感谢!我现在明白我在做什么混合。还有很多东西要学!

以上是关于如何将数据源从一个模块引用到另一个模块并将其作为变量传递给根模块?的主要内容,如果未能解决你的问题,请参考以下文章

如何将二进制数据嵌入/链接到 Windows 模块中

将变量从linux内核传递给进程

如何将模块从一个 virtualenv 复制到另一个

KMM:如何将共享模块引用到现有的 iOS 项目中

如何使用 fetch 从一个模块导出从 GET API 获得的响应数据到另一个模块

将 listView 数据从一个活动发送到另一个活动