Crea Recursos en Terraform Solo Si Los Necesitas con `count`

Gestionar recursos en Terraform no tiene por qué ser complicado. Te muestro cómo crear o no un recurso usando solo una variable booleana, evitando la sobreingeniería.

Cuando necesitas que Terraform cree un recurso de forma condicional, basándose en si activas o no una característica, la solución es bastante simple: usa el parámetro count. Me he topado muchas veces con gente que intenta dar vueltas con for_each o módulos complejos para algo que se resuelve con una línea.

Imagínate que tienes un registro DNS en Cloudflare, pero solo quieres crearlo si una variable cloudflare_enabled es verdadera. Aquí tienes cómo lo hago yo:

resource "cloudflare_record" "record" {
  count = var.cloudflare_enabled ? 1 : 0

  zone_id = data.cloudflare_zones.domain.zones[0].id
  name    = var.subdomain
  value   = var.origin_server
  type    = "CNAME"
  ttl     = 1
  proxied = true
}

Así de directo. Si var.cloudflare_enabled es true (definida en tu .tfvars), el count será 1 y Terraform creará el recurso. Si es false, count será 0 y el recurso simplemente no existirá. Es simple y funciona, que es lo que busco siempre.

Ahora, ¿cómo accedes a los atributos de este recurso si no sabes si existe? La forma estándar es usar el índice [0], porque al usar count, Terraform trata el recurso como una lista, incluso si solo hay uno:

output "record_id" {
  value = cloudflare_record.record[0].id
}

Pero ojo que esto tiene un detalle: si count fue 0, intentar acceder a cloudflare_record.record[0] te va a dar un error. En mi caso, esto me frustró un par de veces hasta que encontré una forma más elegante.

Para eso, puedes usar la función one(). Lo que hace one() es tomar una lista y devolver el único elemento que contiene, o null si la lista está vacía (o tiene más de uno, pero en este caso, con count = 0 o 1, no pasa). Esto te permite referenciar el recurso sin el índice [0] y, más importante, sin que falle si el recurso no se creó.

Primero, defines una variable local:

locals {
  record_id_or_null = one(cloudflare_record.record[*].id)
}

Luego, puedes usar local.record_id_or_null en cualquier parte. Si el recurso se creó, obtendrás el ID. Si no, obtendrás null, que muchas veces es lo que necesitas para lógica condicional en otros sitios, o simplemente para no romper tu pipeline.

De hecho, esta técnica con one() la descubrí un poco tarde. Antes me la pasaba con try() o con un lookup() incómodo, pero esta es mucho más limpia para este tipo de escenarios. Te ahorra varios dolores de cabeza.

Mi recomendación es que siempre optes por la solución más directa. La sobreingeniería en Terraform solo te trae complejidad extra que no necesitas. La gente suele equivocarse intentando hacer loops complejos con for_each para una condición booleana, o no maneja bien las referencias a recursos que podrían no existir. Con count y, si es necesario, one(), tienes la herramienta justa para el problema.

Jorge RequenaDeveloper full-stack · Chile