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.
Steps: Clone the repo from here. Change your directory to ./terraform/passing-outputs so you can list modules directory, variables.tf and main.tf files. Change the variables in root variables.tf file according to your needs.
Modules on the public Terraform Registry can be referenced using a registry source address of the form <NAMESPACE>/<NAME>/<PROVIDER> , with each module's information page on the registry site including the exact address to use.
In this case, we can create an explicit dependency using the depends_on key in a Terraform resource. Explicitly specifying a dependency is only necessary when a resource relies on some other resource's behavior but doesn't access any of that resource's data in its arguments.
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With