In my terraform azure code, when I run the plan, it says it will replace the resource but I can’t seem to find the issue.
My code creates load balancer, lb rule, lb probe, backend pools etc. The error is specifically in the below block
Wherever it’s calling data azurerm_lb_backend_address_pool, it’s saying ‘known after apply’ and recreating it
locals {
backend_pool_add = flatten([
for lb in var.load_balancer:
[
for vm in lb.backend_pool:
[
for ip in vm.ip_address:
{
lb_name = lb.lb_name
backend_address_pool_name = vm.backend_address_pool_name
ip_address = ip
nic_name = vm.ip_address != null ? "nic" : null
}
] if vm.vm_nic_name == null
]
])
backend_pool_add_ori = flatten([
for lb in var.load_balancer:
[
for vm in lb.backend_pool:
{
lb_name = lb.lb_name
backend_address_pool_name = vm.backend_address_pool_name
nic_name = vm.ip_address != null ? "nic" : null
}
if vm.vm_nic_name == null
]
]) }
data "azurerm_lb_backend_address_pool" "bap_pool_ipname_ori" {
for_each = { for bap in local.backend_pool_add_ori : "${bap.backend_address_pool_name}-${bap.lb_name}" => bap if bap.nic_name != null}
name = each.value.backend_address_pool_name
loadbalancer_id = azurerm_lb.lb[each.value.lb_name].id
}
resource "azurerm_lb_backend_address_pool_address" "bap_address" {
for_each = { for idx , bp in local.backend_pool_add : idx => bp if bp.nic_name != null}
name = data.azurerm_lb_backend_address_pool.bap_pool_ipname_ori["${each.value.backend_address_pool_name}-${each.value.lb_name}"].backend_address[each.key % 2].name
backend_address_pool_id = azurerm_lb_backend_address_pool.bap_pool_ip[each.value.ip_address].id
virtual_network_id = data.azurerm_virtual_network.vnet_backend_address_pool[each.value.lb_name].id
ip_address = each.value.ip_address
depends_on = [ azurerm_lb.lb, azurerm_lb_backend_address_pool.bap_pool_ip]
}
I tried to get the output of data block and that too says "known after apply"
Issue:
" # module.load_balancer.azurerm_lb_backend_address_pool_address.bap_address[\"3\"] must be replaced",
"-/+ resource \"azurerm_lb_backend_address_pool_address\" \"bap_address\" {",
" ~ id = \"/subscriptions/subscription_id/resourceGroups/rg-smartops-prod-att-appaccess-prod-nx01/providers/Microsoft.Network/loadBalancers/lb_name/backendAddressPools/pool_name/addresses/xxxxx-xx-yyyy\" -> (known after apply)",
" ~ inbound_nat_rule_port_mapping = [] -> (known after apply)",
" ~ name = \"xxxxx-xx-xxx-yyyyy\" -> (known after apply) # forces replacement",
" # (3 unchanged attributes hidden)",
" }",
Expectation:
No Changes.
Please let me know how it can be solved and if any details required
2
Answers
This typically happens when using generic indices within your maps (like "0","1","2",etc) as the order in which those are processed might shift due to certain circumstances. In your example – code is complaining about
module.load_balancer.azurerm_lb_backend_address_pool_address.bap_address[\"3\"]
which is a good indication if this behaviour and it signals that the resource previously stored at the third index position might be different than the one it’s trying to store now.My suggestion would be to switch to iterate that resource through a named index structure and go for something like (similar to what you’ve done in the data):
On another note — would help to share the original
var.load_balancer
to help troubleshoot better. And out of curiosity – can you not reuse the same local for both the data and resource? Seems the structure and information will be identical betweenbackend_pool_add
andbackend_pool_add_ori
and you could simply use the one local var and reference whatever you need from it.TL;DR Avoid using a
for_each
loop with an index – if the order of the elements in the array/list changes, it might recreate resources.Workaround: use a
map
instead, based on a property that is unique.Example 1 – using for_each with an index
Creating resources based on an index:
Running
terraform apply
:Resources were created based on the index – e.g.
null_resource.name["0"]
.Let’s now change the order of the array:
Running
terraform plan
:Example 2 – using for_each with a map
Creating resources using a
map
:Running
terraform apply
:Resources were created based on the map key – e.g.
null_resource.name["foo"]
.Let’s now change the order of the elements:
Running
terraform plan
: