5
votes

I have terraform directory structure as below:

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 module config files as below:

Purpose: In this module, I am referencing an existing resource group which I would like to utilized to create a Virtual machine and its associated objects.

main.tf

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

variables.tf

variable "rg_name" {
  type = string

}

network module

Purpose: I would like to use resource group from resourcegroup module to be referenced in this module. That way, I define at one place and use it in root and other modules example, compute, app service, aks etc

main.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
}

compute module.

Purpose: To define all attributes for compute(VM). The idea is, root module will use this module to spin up different VM roles.

main.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 root module.

Purpose: This should utilize modules defined to create a variety of VMs of different sizes and host names

main.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: Declares all variables in main.tf file.

Note: I have intentionally hard coded the variables in root module main/variable file. This is just get the communication between the modules right. Correct approach to understand and use modules.

However, when I run terraform plan in the root module. I get the error below:

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.

What is the issue and how to resolve it?

Also, possible to create different (roles) vms by some loop? example sql-vm, iis-vm, testvm, abcvm? What is going to change is their hostnames and vm sizes.

==========

Post answer changes

==========

I updated the values for subnet, resource group and location in compute/main.tf and terraform/main.tf as like below:

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

My outputs.tf file in resourcegroup and network modules look like below:

outputs.tf of network module

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

outputs.tf of resourcegroup module

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

I'm unfortunately still getting errors like below

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.

So, it appears that we should not be referencing them in the root module?

Also, where their variables should be defined as in root modules variables.tf file as I believe you can override values for a variable of modules in the root module?

Forgive me if I am appearing as stupid. I'm trying to understand how it works in real life.

After last commit and public repo, error's are as below

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.
1
I think you need to read the answer carefully, it said you need to define the output so that you can refer to the resources you need.Charles Xu
I in fact did and then only ran the terraform plan, I did not paste the output.tf in my question post. I shall amend my question so you can see outputs.tf. If outputs.tf was not defined it would have reported a different error in itself.learner
Perhaps now it would make sense? I need some assistance as I am unable to get it working based on the solution proposed by BMW Sir.learner

1 Answers

2
votes

Go through the repo you are working on (https://github.com/ameyaagashe/help_me_cross/tree/d7485d2a3db339723e9c791e592b2f1dbc1f0788) . It makes sense for me now.

The problem is, you mix the idea on how to use public modules with your own created modules.

In fact, you needn't set any modules to reference other public terraform registry modules.

Move all codes in sub-modules (module/compute, module/network, module/resourcegroup) to top folder (<repo_root>/main.tf).

such as (codes are not validated, just for reference)

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
}