Search code examples
terraformterraform-provider-azureterraform-modules

how to pass map of objects using output.tf from one module to another module in Terraform


I am trying to associate existing Application Security Group to newly created Virtual Machine - Network Interfaces using the output.tf.

I have infra-asg, app-asg, service-asg and db-asg in the existing pluto-infra resource group. Now I want to associate asg to nics as below

infra-asg & app-asg to pluto-app-1-nic and pluto-app-2-nic
infra-asg & service-asg to pluto-service-1-nic and pluto-service-2-nic
infra-asg & db-asg to pluto-db-1-1-nic, pluto-db-1-2-nic, pluto-db-2-1-nic & pluto-db-2-2-nic

Terraform Module Package structure as below

enter image description here

main.tf

module "virtualmachine" {
  source                  = "./virtualmachine"
  existing_resource_group = var.existing_resource_group
  virtual_machines        = var.virtual_machines
  vm_prefix               = var.vm_prefix
}

module "associate-asg" { 
  source = "./application-security-group"
}

variables.tf

variable "resource_group_location" {
  type        = string
  default     = "eastus"
}

variable "vm_prefix" {
  type        = string
  default     = "pluto"
}

variable "virtual_machines" {
}

variable "existing_resource_group" {
  type = string
}

variable.tfvars

existing_resource_group = "pluto"
existing_infra_rg = "pluto-infra"

virtual_machines = {
  nodes = {
    app1_node1 = {
      "vm_name"   = "app"
      "vm_num"    = "1"
      networks = {
        nic1 = {
          "nic_name"           = "app-1"
          "subnet"             = "/subscriptions/****/resourceGroups/pluto/providers/Microsoft.Network/virtualNetworks/pluto-vnet/subnets/app-subnet"
        },
      }
    },
    app1_node2 = {
      "vm_name"   = "app"
      "vm_num"    = "2"
      networks = {
        nic1 = {
          "nic_name"           = "app-2"
          "subnet"             = "/subscriptions/****/resourceGroups/pluto/providers/Microsoft.Network/virtualNetworks/pluto-vnet/subnets/app-subnet"
        },
      }
    },
    service1_node1 = {
      "vm_name"   = "service"
      "vm_num"    = "1"
      networks = {
        nic1 = {
          "nic_name"           = "service-1"
          "subnet"             = "/subscriptions/****/resourceGroups/pluto/providers/Microsoft.Network/virtualNetworks/pluto-vnet/subnets/app-subnet"
        },
      }
    },
    service2_node2 = {
      "vm_name"   = "service"
      "vm_num"    = "2"
      networks = {
        nic1 = {
          "nic_name"           = "service-2"
          "subnet"             = "/subscriptions/****/resourceGroups/pluto/providers/Microsoft.Network/virtualNetworks/pluto-vnet/subnets/app-subnet"
        },
      }
    },
    db1_node1 = {
      "vm_name"            = "db"
      "vm_num"             = "1"
      networks = {
        nic1 = {
          "nic_name"           = "db-1-1"
          "subnet"             = "/subscriptions/****/resourceGroups/pluto/providers/Microsoft.Network/virtualNetworks/pluto-vnet/subnets/app-subnet"
        },
        nic2 = {
          "nic_name"           = "db-1-2"
          "subnet"             = "/subscriptions/****/resourceGroups/pluto/providers/Microsoft.Network/virtualNetworks/pluto-vnet/subnets/db-subnet"
        }
      }
    },
    db2_node2 = {
      "vm_name"            = "db"
      "vm_num"             = "2"
      networks = {
        nic1 = {
          "nic_name"           = "db-2-1"
          "subnet"             = "/subscriptions/****/resourceGroups/pluto/providers/Microsoft.Network/virtualNetworks/pluto-vnet/subnets/app-subnet"
        },
        nic2 = {
          "nic_name"           = "db-2-2"
          "subnet"             = "/subscriptions/****/resourceGroups/pluto/providers/Microsoft.Network/virtualNetworks/pluto-vnet/subnets/db-subnet"
        },
      }
    },
  }
}

Virtual Machine module details

main.tf

data "azurerm_resource_group" "rg" {
  name = var.existing_resource_group
}

resource "azurerm_network_interface" "nic" {

  for_each = {
    for vm in flatten([
      for vm_name, vm in var.virtual_machines.nodes : [
        for nic_name, nic in vm.networks : {
          vm_number          = vm.vm_num,
          vm_name            = vm_name,
          nic_name           = nic_name,
          subnet_value       = nic.subnet
          nic_name_value     = nic.nic_name

        }
      ]
      ]
    ) : "${vm.vm_name}-${vm.nic_name}" => vm
  }
  name                = "${var.vm_prefix}-${each.value.nic_name_value}-nic"
  location            = "eastus"
  resource_group_name = var.existing_resource_group

  ip_configuration {
    name                          = "${var.vm_prefix}-${each.value.nic_name_value}-ipconfig"
    subnet_id                     = each.value.subnet_value
    private_ip_address_allocation = "Dynamic"
  }
}

resource "azurerm_linux_virtual_machine" "vm" {

  depends_on                      = [azurerm_network_interface.nic]
  for_each                        = var.virtual_machines.nodes
  name                            = "${var.vm_prefix}-${each.value.vm_name}-${each.value.vm_num}"
  admin_username                  = "plutoadmin"
  admin_password                  = "pluto@1234522"
  disable_password_authentication = false
  location                        = "eastus"
  resource_group_name             = var.existing_resource_group
  network_interface_ids           = [for nic_key, nic in azurerm_network_interface.nic : nic.id if startswith(nic_key, "${each.key}-")]
  size                = "Standard_B2ms"

  os_disk {
    name                 = "${var.vm_prefix}-${each.value.vm_name}-${each.value.vm_num}-OSdisk"
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }

  source_image_reference {
     publisher = "RedHat"
    offer     = "RHEL"
    sku       = "82gen2"
    version   = "latest"
  }
}

variable.tf

variable "vm_prefix" {
  type        = string
  default     = "pluto"
}

variable "virtual_machines" {
}

variable "existing_resource_group" {
  type = string
}

output.tf

output "vm_nics_ids" {

  value = [for nic_key, nic in azurerm_network_interface.nic : nic.id]
}

Application Security Group module details

data "azurerm_application_security_group" "infra-asg" {
  name                = "infra-asg"
  resource_group_name = "pluto-infra"
}

data "azurerm_application_security_group" "app-asg" {
  name                = "app-asg"
  resource_group_name = "pluto-infra"
}


data "azurerm_application_security_group" "service-asg" {
  name                = "service-asg"
  resource_group_name = "pluto-infra"
}

data "azurerm_application_security_group" "db-asg" {
  name                = "db-asg"
  resource_group_name = "pluto-infra"
}

data "azurerm_network_interface" "app-nic-1" {
  name                = "pluto-app-1-nic"
  resource_group_name = "pluto"
}


resource "azurerm_network_interface_application_security_group_association" "infra-app-asg-1" {

  network_interface_id          = data.azurerm_network_interface.app-nic-1.id
  application_security_group_id = data.azurerm_application_security_group.infra-asg.id
}

resource "azurerm_network_interface_application_security_group_association" "app-asg-1" {

  network_interface_id          = data.azurerm_network_interface.app-nic-1.id
  application_security_group_id = data.azurerm_application_security_group.app-asg.id
}

# App Node 2

data "azurerm_network_interface" "app-nic-2" {
  name                = "pluto-app-2-nic"
  resource_group_name = "pluto"
}


resource "azurerm_network_interface_application_security_group_association" "infra-app-asg-2" {

  network_interface_id          = data.azurerm_network_interface.app-nic-2.id
  application_security_group_id = data.azurerm_application_security_group.infra-asg.id
}

resource "azurerm_network_interface_application_security_group_association" "app-asg-2" {

  network_interface_id          = data.azurerm_network_interface.app-nic-2.id
  application_security_group_id = data.azurerm_application_security_group.app-asg.id
}



# service Node 1 

data "azurerm_network_interface" "service-nic-1" {
  name                = "pluto-service-1-nic"
  resource_group_name = "pluto"
}


resource "azurerm_network_interface_application_security_group_association" "infra-service-asg-1" {

  network_interface_id          = data.azurerm_network_interface.service-nic-1.id
  application_security_group_id = data.azurerm_application_security_group.infra-asg.id
}

resource "azurerm_network_interface_application_security_group_association" "service-asg-1" {

  network_interface_id          = data.azurerm_network_interface.service-nic-1.id
  application_security_group_id = data.azurerm_application_security_group.service-asg.id
}

# service Node 2

data "azurerm_network_interface" "service-nic-2" {
  name                = "pluto-service-2-nic"
  resource_group_name = "pluto"
}

resource "azurerm_network_interface_application_security_group_association" "infra-service-asg-2" {

  network_interface_id          = data.azurerm_network_interface.service-nic-2.id
  application_security_group_id = data.azurerm_application_security_group.infra-asg.id
}

resource "azurerm_network_interface_application_security_group_association" "service-asg-2" {

  network_interface_id          = data.azurerm_network_interface.service-nic-2.id
  application_security_group_id = data.azurerm_application_security_group.service-asg.id
}


# DB -1-1

data "azurerm_network_interface" "db-nic-1-1" {
  name                = "pluto-db-1-1-nic"
  resource_group_name = "pluto"
}

resource "azurerm_network_interface_application_security_group_association" "infra-db-asg-1-1" {

  network_interface_id          = data.azurerm_network_interface.db-nic-1-1.id
  application_security_group_id = data.azurerm_application_security_group.infra-asg.id
}

resource "azurerm_network_interface_application_security_group_association" "db-asg-1-1" {

  network_interface_id          = data.azurerm_network_interface.db-nic-1-1.id
  application_security_group_id = data.azurerm_application_security_group.db-asg.id
}


# DB -1-2

data "azurerm_network_interface" "db-nic-1-2" {
  name                = "pluto-db-1-2-nic"
  resource_group_name = "pluto"
}

resource "azurerm_network_interface_application_security_group_association" "infra-db-asg-1-2" {

  network_interface_id          = data.azurerm_network_interface.db-nic-1-2.id
  application_security_group_id = data.azurerm_application_security_group.infra-asg.id
}

resource "azurerm_network_interface_application_security_group_association" "db-asg-1-2" {

  network_interface_id          = data.azurerm_network_interface.db-nic-1-2.id
  application_security_group_id = data.azurerm_application_security_group.db-asg.id
}

# DB -2-1


data "azurerm_network_interface" "db-nic-2-1" {
  name                = "pluto-db-2-1-nic"
  resource_group_name = "pluto"
}

resource "azurerm_network_interface_application_security_group_association" "infra-db-asg-2-1" {

  network_interface_id          = data.azurerm_network_interface.db-nic-2-1.id
  application_security_group_id = data.azurerm_application_security_group.db-asg.id
}

resource "azurerm_network_interface_application_security_group_association" "db-asg-2-1" {

  network_interface_id          = data.azurerm_network_interface.db-nic-2-1.id
  application_security_group_id = data.azurerm_application_security_group.infra-asg.id
}

# DB -2-2

data "azurerm_network_interface" "db-nic-2-2" {
  name                = "pluto-db-2-2-nic"
  resource_group_name = "pluto"
}

resource "azurerm_network_interface_application_security_group_association" "infra-db-asg-2-2" {

  network_interface_id          = data.azurerm_network_interface.db-nic-2-2.id
  application_security_group_id = data.azurerm_application_security_group.infra-asg.id
}

resource "azurerm_network_interface_application_security_group_association" "db-asg-2-2" {

  network_interface_id          = data.azurerm_network_interface.db-nic-2-2.id
  application_security_group_id = data.azurerm_application_security_group.db-asg.id
}

could you guide me how to pass the nic ids from virtual machine module to Application security group module and loop them ?


Solution

  • You can use outputs to pass data from one module to another. You are already on the right path as you have an output block that has the map of your nic ID's. To retrieve, on your root main.tf (the one that references both your vm and asg module) pass them is by accessing the attributes as you would normally do on any other resource block with the keyword "module". Then only thing missing is a variable on your asg module that allows you to pass in the collection

    main.tf

    module "virtualmachine" {
      source                  = "./virtualmachine"
      existing_resource_group = 
      var.existing_resource_group
      virtual_machines        = var.virtual_machines
      vm_prefix               = var.vm_prefix
    }
    
    module "associate-asg" { 
      source = "./application-security-group"
      nic_ids = module.virtualmachine.vm_nics_ids //passing in via the variable declared on asg module
    }
    

    variable.tf (on your asg module)

    variable "nic_ids" {
      type = list(string)
    }
    

    main.tf (asg module)

    resource "azurerm_network_interface_application_security_group_association" "infra-db-asg-2-2" {
      count = length(var.nic_ids)
      network_interface_id          = 
      var.nic_ids[count.index]
      application_security_group_id = 
      data.azurerm_application_security_group.infra-asg.id
    }
    

    You already have your output done on your vm module so this will work. Dont forget to do a terraform init after the changes so your root will get the latest changes from modules. Hope this helps