Search code examples
terraformterraform-provider-azure

Can you retrieve an item from a list using regex in Terraform?


The problem I am trying to solve is I need to identify one of the Azure subnets in a virtual network by part of it's name. This is so I can then later retrieve it's CIDR. I only know part beforehand such as "mgmt-1" or "egress-1". The actual name of the subnet is much longer but will end in something like that. This was my process:

I have the vnet name so I pull all subnets:

data "azurerm_virtual_network" "this" {
  name = local.vnet
  resource_group_name = "myrg"
}

Now what I wish I could do is this:

locals {
  mgmt_index = index(data.azurerm_virtual_network.this.subnets, "*mgmt-1")
  mgmt_subnet = data.azurerm_virtual_network.this.subnets[local.mgmt_index]
}

However index wants an exact match, not a regex. Is this possible to do? Perhaps a better way?

Thank you,


Solution

  • It is not possible to directly look up a list item using a regex match, but you can use for expressions to apply arbitrary filters to a collection when constructing a new collection:

    locals {
      mgmt_subnets = toset([
        for s in data.azurerm_virtual_network.this.subnets : s
        if can(regex(".*?mgmt-1", s.name))
      ])
    }
    

    In principle an expression like the above could match more than one object, so I wrote this to produce a set of objects that match.

    If you expect that there will never be more than one object whose name matches the pattern then you can use Terraform's one function to assert that and then Terraform will check to confirm that there's no more than one element (returning an error if not) and then return that one value.

    locals {
      mgmt_subnet = one([
        for s in data.azurerm_virtual_network.this.subnets : s
        if can(regex(".*?mgmt-1", s.name))
      ])
    }
    

    If the condition doesn't match any of the subnet objects then in the first case you'll have an empty set and in the second case you'll have the value null.