简体   繁体   中英

Passing the outputs from a module when the module is created using a for_each

This links to my the previous question, click the link for the rest of my code and how it all fits together: Use output value from module that has a for_each set

Whilst the answer was helpful in solving the issue and allowing me to run the pipeline, I think there is an error because of the way the VM is generated using the for_each on the module. This results in the incorrect value being passed to the network_security_rule. Below is an example of the error:

Error: Error Creating/Updating Network Security Rule "nsr-sbox-http80" (NSG "module.fico_app_vm.linux_vm_nsg" / Resource Group "rg-sbox-app"): network.SecurityRulesClient#CreateOrUpdate: Failure sending request: StatusCode=404 -- Original Error: Code="ResourceNotFound" Message="The Resource 'Microsoft.Network/networkSecurityGroups/module.fico_app_vm.linux_vm_nsg' under resource group 'rg-sbox-app' was not found. For more details please go to https://aka.ms/ARMResourceNotFoundFix"

  on main.tf line 58, in resource "azurerm_network_security_rule" "fico-app-sr-80":
  58: resource "azurerm_network_security_rule" "fico-app-sr-80" {

outputs.tf

output "linux_vm_ips" {
  value = azurerm_network_interface.dwp_network_interface.private_ip_address
}

output "linux_vm_nsg" {
  value = azurerm_network_security_group.dwp_network_security_group.name
}

At first I thought it was because the NSG isn't being created, but I checked the console and it does create it. The issue is the NSG is created in the module for each VM. The VM's are created by looping over the variable in tfvars file. How do I pass the NSG name created in the module to the security rule which is outside of the module?:

resource "azurerm_network_security_rule" "fico-app-sr-80" {
  name                        = "nsr-${var.environment}-${var.directorate}-${var.business_unit}-${var.vm_identifier}${var.instance_number}-http80"
  priority                    = 100
  direction                   = "Inbound"
  access                      = "Allow"
  protocol                    = "*"
  source_port_range           = "*"
  destination_port_range      = "80"
  source_address_prefixes     = ["module.fico_web_vm.linux_vm_ips"]
  destination_address_prefix  = "VirtualNetwork"
  resource_group_name         = azurerm_resource_group.rg_fico_app.name
  network_security_group_name = "module.fico_app_vm.linux_vm_nsg"
}
# Network Security Group
resource "azurerm_network_security_group" "network_security_group" {
  name                = "nsg-${var.environment}-${var.directorate}-${var.business_unit}-${var.vm_identifier}-${var.vm_name}"
  resource_group_name = var.resource_group
  location            = var.location
}

Something to note as well, is that the var.vm_name iterates through the key of each map and this makes up part of the name of the NSG.

module in main.tf:

module "fico_app_vm" {
  for_each                     = var.app_servers
  source                       = "../modules/compute/linux_vm"
  source_image_id              = var.app_image_id
  location                     = var.location
  vm_name                      = each.key
  vm_identifier                = "${var.vm_identifier}${var.instance_number}"
  vm                           = each.value
  disks                        = each.value["disks"]
  resource_group               = azurerm_resource_group.rg_fico_app.name
  directorate                  = var.directorate
  business_unit                = var.business_unit
  environment                  = var.environment
  network_rg_identifier        = var.network_rg_identifier
  subnet_name                  = "sub-${var.environment}-${var.directorate}-${var.business_unit}-be01"
  diag_storage_account_name    = var.diag_storage_account_name
  ansible_storage_account_name = var.ansible_storage_account_name
  ansible_storage_account_key  = var.ansible_storage_account_key
  log_analytics_workspace_name = var.log_analytics_workspace_name
  backup_policy_name           = var.backup_policy_name
  enable_management_locks      = true
}

tfvars:

app_servers ={
  app-1 = {
    size           = "Standard_E2s_v3"
    admin_username = "xxx"
    public_key     = "xxx"
    disks          = [32, 32]
    zone_vm        = "1"
    zone_disk      = ["1"]
  }
}

I think it's the problem that you read the previous answer not carefully. The answer shows you need to change the security group name like this:

network_security_group_name = module.fico_app_vm.linux_vm_nsg

There are no double-quotes. Double-quotes means it's a string. But you need to use the module attribute, not a string with a value "module.fico_app_vm.linux_vm_nsg" . The error also shows it directly.

I realised what my error was. I needed to change this:

network_security_group_name = "module.fico_app_vm.linux_vm_nsg"

to this

network_security_group_name = module.fico_app_vm[each.key].linux_vm_nsg

But I also needed to reference the value in the source address prefixes. So to reference the key I created another variable and changed this:

source_address_prefixes     = ["module.fico_web_vm.linux_vm_ips"]

to this:

source_address_prefix       = module.fico_web_vm[each.value.web_server].linux_vm_ip

I also had to change to source_address_prefix and thats why the type error was occurring!

The security rule now looks like this:

resource "azurerm_network_security_rule" "fico-app-sr-80" {
  for_each                    = var.app_servers
  name                        = "nsr-${var.environment}-${var.directorate}-${var.business_unit}-${var.vm_identifier}${var.instance_number}-http80"
  priority                    = 100
  direction                   = "Inbound"
  access                      = "Allow"
  protocol                    = "*"
  source_port_range           = "*"
  destination_port_range      = "80"
  source_address_prefix       = module.fico_web_vm[each.value.web_server].linux_vm_ip
  destination_address_prefix  = "VirtualNetwork"
  resource_group_name         = azurerm_resource_group.rg_dwp_fico_app.name
  network_security_group_name = module.fico_app_vm[each.key].linux_vm_nsg

And variable looks like this:

app_servers = {
  app-1 = {
    size           = "Standard_E2s_v3"
    admin_username = "azureuser"
    public_key     = xxxx
    disks          = [32, 32]
    zone_vm        = "1"
    zone_disk      = ["1"]
    web_server     = "web-1"
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM