Search code examples
azureterraform-provider-azure

Azure Terraform - How to avoid conflicting configuration arguments while creating NSG Rules


I am getting below error while creating azurerm_network_security_rule.

Planning failed. Terraform encountered an error while generating this plan.

╷
│ Error: Conflicting configuration arguments
│ "source_port_range": conflicts with source_port_ranges ..
│ "source_port_ranges": conflicts with source_port_range .. 
│ "destination_port_range": conflicts with destination_port_ranges ..
│ "destination_port_ranges": conflicts with destination_port_range ..
│ "source_address_prefix": conflicts with source_address_prefixes ..
│ "source_address_prefixes": conflicts with source_address_prefix ..
│ "destination_address_prefix": conflicts with destination_address_prefixes ..
│ "destination_address_prefixes": conflicts with destination_address_prefix ..

Code snippets:


# tfvars : 

virtual_networks = [
  {
    vnet_index          = "vnet01"
    vnet_name_suffix    = "appvnet1"
    resource_group_name = "azd-rsg-prod-net"
    location            = "EastUS"
    address_space = [
      "10.10.0.0/16"
    ]
    subnets = [
      {
        subnet_suffix = "app"
        address_space = "10.10.0.0/24"
        nsg_rules = [
          {
            rule_name                    = "SR-AllowSomePorts-Inbound"
            rule_description             = "Allow Some Ports"
            access                       = "Allow"
            direction                    = "Inbound"
            priority                     = "1001"
            protocol                     = "*"
            source_port_range            = "*"
            source_port_ranges           = []
            destination_port_range       = ""
            destination_port_ranges      = ["3389", "443", "80"]
            source_address_prefix        = "*"
            source_address_prefixes      = []
            destination_address_prefix   = "*"
            destination_address_prefixes = []
          }
        ]
      },
      # Other subnet details here..
    ]
  },
]

# Module: 

resource "azurerm_network_security_rule" "NgsRule" {
  for_each                     = { for nsg_rule in local.nsg_rules : nsg_rule.key_name => nsg_rule }
  name                         = each.value.rule_name
  description                  = each.value.rule_description
  access                       = each.value.access
  direction                    = each.value.direction
  priority                     = each.value.priority
  protocol                     = each.value.protocol

  # Conflicts: 
  source_port_range  = length(each.value.source_port_range) != 0 ? each.value.source_port_range : ""
  source_port_ranges = length(each.value.source_port_ranges) != 0 ? each.value.source_port_ranges : []

  destination_port_range  = length(each.value.destination_port_range) != 0 ? each.value.destination_port_range : ""
  destination_port_ranges = length(each.value.destination_port_ranges) != 0 ? each.value.destination_port_ranges : []

  source_address_prefix   = length(each.value.source_address_prefix) != 0 ? each.value.source_address_prefix : ""
  source_address_prefixes = length(each.value.source_address_prefixes) != 0 ? each.value.source_address_prefixes : []

  destination_address_prefix   = length(each.value.destination_address_prefix) != 0 ? each.value.destination_address_prefix : ""
  destination_address_prefixes = length(each.value.destination_address_prefixes) != 0 ? each.value.destination_address_prefixes : []

  resource_group_name         = each.value.resource_group_name
  network_security_group_name = each.value.nsg_name
}

How to dynamically populate singular/plural property based on the presence of singular/plural argument value?


Solution

  • You cant use both the singular and plural properties in the same resource block. You can always provide a singular value in the plural property as a single item in the array object.

    # tfvars:
    ...
    nsg_rules = [
              {
                rule_name                    = "SR-AllowSomePorts-Inbound"
                rule_description             = "Allow Some Ports"
                access                       = "Allow"
                direction                    = "Inbound"
                priority                     = "1001"
                protocol                     = "*"
                source_port_ranges           = ["*"]
                destination_port_ranges      = ["3389", "443", "80"]
                source_address_prefixes      = ["*"]
                destination_address_prefixes = ["*"]
              }
            ]
    ... 
    
    # Module
    resource "azurerm_network_security_rule" "NgsRule" {
    ...
    source_port_range  = length(each.value.source_port_ranges) == 1 ? each.value.source_port_ranges[0] : null
      source_port_ranges = length(each.value.source_port_ranges) != 1 ? each.value.source_port_ranges : null
      destination_port_range  = length(each.value.destination_port_ranges) == 1 ? each.value.destination_port_ranges[0] : null
      destination_port_ranges = length(each.value.destination_port_ranges) != 1 ? each.value.destination_port_ranges : null
      source_address_prefix   = length(each.value.source_address_prefixes) == 1 ? each.value.source_address_prefixes[0] : null
      source_address_prefixes = length(each.value.source_address_prefixes) != 1 ? each.value.source_address_prefixes : null
      destination_address_prefix   = length(each.value.destination_address_prefixes) == 1 ? each.value.destination_address_prefixes[0] : null
      destination_address_prefixes = length(each.value.destination_address_prefixes) != 1 ? each.value.destination_address_prefixes : null
    ...
    }