Terraform 40: cableado de Service Bus con for_each
easy⏱ 5 mincourseterraform
Un mapa, tres recursos ligados
Describí cada binding de queue/topic una vez en un mapa locals. El mismo mapa for_each alimenta luego: (1) un data lookup de la authorization rule del topic de Service Bus, y (2) el secreto de Key Vault que guarda su connection string. Agregar un subscriber es una entrada del mapa.
locals {
environment_name = "dev"
service_bus = {
"orders-events-receiver" = {
system = "shop"
topic = "orders-events-topic"
rg = "myorg-shop-bus-dev-rg"
}
"billing-events-publisher" = {
system = "shop"
topic = "billing-events-topic"
rg = "myorg-shop-bus-dev-rg"
}
}
}
Data-source de la auth rule, luego keyvault-secret
Terraform no crea el namespace acá — lee la authorization rule de cada topic con un data source, y luego escribe primary_connection_string en Key Vault. Notá la convención de nombres con strcontains(...): un receiver usa -sub-rule, un publisher -publisher-rule.
data "azurerm_servicebus_topic_authorization_rule" "bus" {
for_each = local.service_bus
name = strcontains(each.key, "receiver") ? "${each.key}-sub-rule" : "${each.key}-publisher-rule"
resource_group_name = each.value.rg
namespace_name = "${local.environment_name}-${each.value.system}-namespace"
topic_name = each.value.topic
}
resource "azurerm_key_vault_secret" "bus_conn" {
for_each = local.service_bus
name = "${each.key}-connectionstring"
value = data.azurerm_servicebus_topic_authorization_rule.bus[each.key].primary_connection_string
key_vault_id = data.azurerm_key_vault.app.id
expiration_date = "2099-12-30T00:00:00Z"
}
Indexá instancias por su clave de mapa
Con un for_each map, cada instancia se direcciona por clave: data.<...>.bus[each.key] o ["orders-events-receiver"]. Las claves son estables, así que quitar una entrada destruye solo esa instancia — a diferencia de los índices de count en listas, que se corren y provocan reemplazos en cascada.
El connection string igual queda en el state
Aun hecho bien, primary_connection_string queda guardado en el state — justamente por eso el backend debe ser un store remoto cifrado, con locking y acceso de mínimo privilegio. La ganancia es que ningún secreto vive en tu código fuente; los consumidores lo leen de Key Vault en runtime.
Resolvé el nombre de auth-rule de cada entrada
Escribí authRuleName(key) replicando el ternario del HCL: si key contiene "receiver" devolvé `${key}-sub-rule`, si no `${key}-publisher-rule`. Luego mapealo sobre las claves de serviceBus y logueá cada línea key -> ruleName. orders-events-receiver debe mapear a orders-events-receiver-sub-rule.