Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

FinOps as Code: gestiona DoiT Cloud Intelligence con Terraform

By Hannes HayashiJun 25, 202611 min read

Esta página también está disponible en English, Deutsch, Français, Italiano, 日本語 y Português.

Versionas tu infraestructura. Revisas pull requests del código de tus aplicaciones. Pero ¿qué pasa con tu configuración de FinOps: presupuestos, asignación de costos, alertas y reportes analíticos?

En la mayoría de los equipos, todo eso vive en una UI. Alguien recorre un wizard a punta de clics, define un umbral, elige un filtro y cruza los dedos para que la próxima persona que necesite tocarlo entienda la intención original. No hay historial, no hay peer review y no hay forma de replicar la configuración entre ambientes. Si tus prácticas de FinOps son tan críticas como tu infraestructura, merecen el mismo rigor.

Por eso construimos el provider de Terraform de DoiT. Lleva tu configuración de DoiT Cloud Intelligence al mismo flujo de Infrastructure as Code que ya usas para tus recursos en la nube, con 17 recursos gestionados y 61 data sources que cubren desde presupuestos y reportes hasta consultas al asistente de IA y diagramas de infraestructura cloud.

Primeros pasos

Para arrancar solo hace falta un bloque de provider y una API key:

terraform {
required_providers {
doit = {
source = "doitintl/doit"
version = "~> 1.0"
}
}
}
provider "doit" {}

Define DOIT_API_TOKEN en tu entorno (puedes crear API keys desde la DoiT Console) y listo. Eso es todo: no requiere configuración adicional.

El flujo central de FinOps

Repasemos los recursos por los que la mayoría de los equipos empieza: asignaciones, presupuestos, alertas y reportes. Juntos forman un pipeline completo de FinOps, y gestionarlos como código te permite versionar, revisar y replicar toda la configuración.

Asignación de costos

Las asignaciones son la forma de dividir el gasto en la nube en categorías con sentido. El provider incluye un motor de fórmulas booleanas para combinar criterios de filtrado, asignaciones de grupo que reparten los costos en buckets con nombre e incluso asignaciones anidadas que referencian otras asignaciones por ID.

Aquí va un ejemplo de asignación de grupo que separa los costos por región, con un comodín para todo lo que no coincida:

resource "doit_allocation" "by_region" {
name = "By Region"
description = "Group costs by geographic region"
unallocated_costs = "Other Regions"
rules = [
{
action = "create"
name = "US"
formula = "A"
components = [{
key = "country", mode = "is", type = "fixed", values = ["US"]
}]
},
{
action = "create"
name = "Europe"
formula = "A"
components = [{
key = "country", mode = "is", type = "fixed", values = ["DE", "FR", "GB", "NL"]
}]
}
]
}

¿Necesitas más granularidad? Usa type = "allocation_rule" en un componente para referenciar una asignación existente y componer asignaciones a partir de otras, hasta 3 niveles de profundidad. Y en lugar de hardcodear valores de dimensión como "US" o "DE", puedes usar el data source doit_dimension para descubrir valores válidos de forma dinámica desde la API.

Presupuestos

Los presupuestos son las barreras de protección. El provider te deja definir alertas con múltiples umbrales, acotar presupuestos a asignaciones o dimensiones específicas y —un patrón muy útil— filtrar colaboradores por función en vez de agregar a cada usuario de la organización:

data "doit_users" "all" {}
locals {
engineers = [
for u in data.doit_users.all.users : u
if u.job_title == "Software / Ops Engineer"
]
}
resource "doit_budget" "eng_budget" {
name = "Engineering Budget"
currency = "USD"
type = "recurring"
amount = 10000
time_interval = "month"
start_period = provider::time::rfc3339_parse("2026-01-01T00:00:00Z") * 1000
alerts = [
{ percentage = 50 },
{ percentage = 80 },
{ percentage = 100 }
]
collaborators = concat(
[{ email = data.doit_current_user.me.email, role = "owner" }],
[for u in local.engineers : { email = u.email, role = "viewer" }]
)
recipients = [for u in local.engineers : u.email]
scopes = [{
type = "allocation_rule"
id = "allocation_rule"
mode = "is"
values = [doit_allocation.by_region.id]
}]
}

Este presupuesto se acota a la asignación por región que acabamos de crear y solo notifica a usuarios con el cargo "Software / Ops Engineer". Los presupuestos también admiten seasonal_amounts para los meses en los que tus metas de gasto varían, y campos calculados como current_utilization y forecasted_utilization están disponibles como salidas de solo lectura.

Alertas

Las alertas disparan notificaciones cuando el costo o el uso supera un umbral. La verdadera ventaja está en el acotamiento: puedes restringir una alerta a un proveedor cloud, servicio, región o cualquier dimensión específica. Este ejemplo usa el data source doit_products para buscar dinámicamente el ID del servicio Compute Engine en lugar de hardcodearlo:

data "doit_products" "gcp" {
platform = "google_cloud_platform"
}
resource "doit_alert" "compute_cost" {
name = "GCP Compute Cost Alert"
config = {
metric = { type = "basic", value = "cost" }
time_interval = "day"
value = 500
currency = "USD"
condition = "value"
operator = "gt"
scopes = [{
type = "fixed"
id = "service_description"
mode = "is"
values = [
for p in data.doit_products.gcp.products : p.id
if p.display_name == "Compute Engine"
]
}]
}
recipients = [data.doit_current_user.me.email]
}

Reportes

Los reportes de Cloud Analytics son el recurso más completo del provider. Puedes configurar hasta 4 métricas, sumar comparativas año contra año con secondary_time_range, aplicar filtros y dimensiones de agrupación, y organizar los reportes en carpetas.

resource "doit_report" "monthly_costs" {
name = "Monthly Cost Report"
description = "Tracks monthly costs across cloud providers with YoY comparison"
config = {
metrics = [
{ type = "basic", value = "cost" },
{ type = "basic", value = "usage" }
]
aggregation = "total"
time_interval = "month"
data_source = "billing"
time_range = {
mode = "last"
amount = 3
include_current = true
unit = "month"
}
secondary_time_range = {
amount = 1, unit = "year", include_current = false
}
filters = [{
id = "cloud_provider", type = "fixed", mode = "is"
values = ["amazon-web-services", "google-cloud"]
}]
group = [{ id = "cloud_provider", type = "fixed" }]
layout = "table"
display_values = "actuals_only"
currency = "USD"
}
}

Si necesitas descubrir IDs y tipos de dimensión válidos para filtros y agrupaciones, el data source doit_dimensions ofrece un catálogo completo: se acabaron las suposiciones.

Más allá de FinOps

Los recursos centrales de FinOps son por donde empieza la mayoría, pero el provider cubre mucho más de la plataforma DoiT. Hay funcionalidades que quizás ni sabías que existían en la consola, y gestionarlas como código es una excelente forma de descubrirlas.

Consultarle a Ava desde Terraform

Sí, puedes consultar a Ava —el asistente de IA de DoiT— directamente desde tu configuración de Terraform. Lo realmente útil es que puedes referenciar IDs de reportes de otros recursos de Terraform dentro del prompt:

data "doit_ava" "report_summary" {
question = "Can you summarize report ${doit_report.monthly_costs.id} for me?"
}
output "report_summary" {
value = data.doit_ava.report_summary.answer
}

Crea un reporte y, acto seguido, pídele a Ava que te lo explique, todo en el mismo terraform apply. También sirve para consultas rápidas como "¿Cuáles son mis 3 servicios cloud con mayor costo este mes?" y enviar la respuesta a outputs de Terraform.

Consultas analíticas ad-hoc

A veces no necesitas un reporte persistente: solo quieres responder una pregunta. El data source doit_report_query ejecuta consultas de Cloud Analytics al vuelo y devuelve JSON estructurado que puedes parsear, transformar o exportar:

data "doit_report_query" "cost_by_provider" {
config = {
metrics = [{ type = "basic", value = "cost" }]
aggregation = "total"
time_interval = "month"
currency = "USD"
time_range = {
mode = "last", amount = 3, include_current = true, unit = "month"
}
group = [{ id = "cloud_provider", type = "fixed" }]
}
}
locals {
result = jsondecode(data.doit_report_query.cost_by_provider.result_json)
columns = [for s in local.result.schema : s.name]
}
resource "local_file" "query_csv" {
filename = "cost_by_provider.csv"
content = join("\n", concat(
[join(",", local.columns)],
[for row in local.result.rows :
join(",", [for cell in row : cell == null ? "" : tostring(cell)])]
))
}

Resulta especialmente útil para cost gates en CI/CD: lanza una consulta dentro de tu pipeline, verifica si el gasto supera un umbral y haz fallar el build si es el caso. También puedes usar doit_report_result para traer resultados de reportes ya guardados.

Diagramas cloud como flowcharts Mermaid

El provider incluye 12 data sources para la funcionalidad de Cloud Diagrams, que cubren búsqueda, exportación, relaciones, snapshots y estadísticas. Un caso de uso creativo: generar flowcharts en Mermaid a partir de la topología de tu infraestructura cloud, que puedes embeber directamente en READMEs, páginas de Confluence o reportes de incidentes.

data "doit_cloud_diagrams_search" "project" {
query = "my-gcp-project"
}
data "doit_cloud_diagrams_schemes" "diagram" {
layer_ids = [data.doit_cloud_diagrams_search.project.scheme[0].ss_id]
components = true
link = true
}
locals {
ss = data.doit_cloud_diagrams_schemes.diagram.statussheet[
data.doit_cloud_diagrams_search.project.scheme[0].ss_id
]
node_lines = [
for id, n in local.ss.node :
" ${id}[\"${replace(coalesce(n.name, id), "\"", "#quot;")}\"]"
]
edge_lines = [
for id, l in local.ss.link :
l.connection_type != null
? " ${l.origin._id} -->|${l.connection_type}| ${l.destination._id}"
: " ${l.origin._id} --> ${l.destination._id}"
]
mermaid = join("\n", concat(["flowchart LR"], local.node_lines, local.edge_lines))
}
output "mermaid" {
value = local.mermaid
}

Pega la salida en mermaid.live o en cualquier renderizador de Markdown y obtendrás una representación visual de las relaciones de tu infraestructura: diffs de topología en el tiempo, snapshots de compliance o un panorama rápido de qué se conecta con qué.

Sharing y control de acceso

Gestionar quién puede ver tus recursos de FinOps suele dejarse para después… hasta que ya no se puede postergar. El recurso doit_sharing te permite definir permisos para reportes, presupuestos, alertas y asignaciones:

locals {
permissions = [
{ user = data.doit_current_user.me.email, role = "owner" },
{ user = "[email protected]", role = "editor" },
{ user = "[email protected]", role = "viewer" },
]
}
resource "doit_sharing" "report" {
resource_type = "reports"
resource_id = doit_report.monthly_costs.id
permissions = local.permissions
public = "viewer" # Grant org-wide read access
}

Define tus sets de permisos una sola vez en locals y aplícalos de forma consistente a cada recurso compartido. Combínalo con doit_user para incorporar nuevos miembros del equipo y con doit_roles para descubrir los roles disponibles, todo desde tu config de Terraform.

Anotaciones y etiquetas

¿Alguna vez miraste un pico de costos de hace seis meses y te preguntaste qué pasó? Las anotaciones te permiten documentar eventos de costo —despliegues, migraciones, incidentes— directamente sobre tus datos de gasto:

resource "doit_label" "infrastructure" {
name = "infrastructure"
color = "blue"
}
resource "doit_annotation" "black_friday" {
content = "AWS cost spike due to Black Friday traffic"
timestamp = "2024-11-29T00:00:00Z"
reports = [doit_report.monthly_costs.id]
labels = [doit_label.infrastructure.id]
}

Las etiquetas y sus asignaciones permiten tagging entre recursos: categoriza reportes, alertas y anotaciones por equipo, proyecto o cualquier taxonomía que tenga sentido para tu organización.

Organización a escala con carpetas

A medida que tu configuración de FinOps gestionada con Terraform crece, las carpetas ayudan a mantener el orden. Soportan anidamiento y funcionan tanto con reportes como con asignaciones:

resource "doit_folder" "analytics" {
name = "Analytics"
description = "Cloud Analytics reports and dashboards"
}
resource "doit_folder" "cost_reports" {
name = "Cost Reports"
description = "Monthly and quarterly cost breakdowns"
parent_folder_id = doit_folder.analytics.id
}
resource "doit_report" "monthly_costs" {
name = "Monthly Cost Overview"
folder_id = doit_folder.cost_reports.id
# ... report config ...
}

También puedes darle identidad de marca a tus analíticas con temas personalizados: define paletas de colores en modo claro y oscuro que se aplican a los gráficos de los reportes de Cloud Analytics y dale a tus dashboards un look pulido y alineado con tu marca.

Onboarding de AWS CloudConnect

Conectar cuentas de AWS a DoiT suele ser un proceso de varios pasos: crear un rol IAM, configurar un bucket S3 y registrar la cuenta. Publicamos un módulo de Terraform dedicado que se encarga del stack completo en un único terraform apply:

module "doit_cloudconnect" {
source = "doitintl/doit-cloudconnect/aws"
version = "~> 1.0"
}

El módulo crea el rol IAM, el bucket S3 y el registro de CloudConnect de una sola vez. Para empresas que incorporan decenas de cuentas, úsalo con for_each sobre una lista de cuentas. Si necesitas más control, el recurso subyacente doit_cloudconnect_aws_account está disponible para uso directo.

Custom Insights

Si corres tus propios chequeos de optimización —buscando recursos sin uso, identificando oportunidades de right-sizing o detectando problemas de seguridad— puedes publicar los hallazgos directamente en la DoiT console:

resource "doit_insight" "unused_instances" {
key = "unused-ec2-instances"
title = "Unused EC2 Instances"
short_description = "EC2 instances with consistently low CPU utilization"
cloud_provider = "aws"
categories = ["FinOps"]
}

Combínalo con doit_insight_resource_results para adjuntar hallazgos por recurso, y tu motor de optimización personalizado mostrará resultados junto a los insights nativos de DoiT.

El patrón de la composabilidad

En todos estos ejemplos vas a notar un tema recurrente: los data sources son el pegamento. En lugar de hardcodear IDs de dimensión, nombres de servicios o emails de usuarios, los descubres en tiempo de plan:

data "doit_dimensions" "all" {}
locals {
dimension_types = { for id, types in {
for d in data.doit_dimensions.all.dimensions : d.id => d.type...
} : id => types[0] }
}

Este mapa de lookup de dimensiones se reutiliza entre reportes, presupuestos, alertas y asignaciones: escríbelo una sola vez y referencia local.dimension_types["region"] donde lo necesites. Del mismo modo, doit_current_user elimina emails hardcodeados, doit_products descubre valores válidos para filtros de servicio y doit_platforms lista los proveedores cloud disponibles en tu organización.

En desarrollo activo y open source

El provider acumula 5 releases menores en los cuatro meses transcurridos desde el lanzamiento de v1.0 en febrero de 2026, cada uno con nuevos recursos y data sources. Entre los aportes recientes se destacan el soporte para Cloud Diagrams, los temas personalizados de la consola, la gestión de carpetas, el sharing y control de acceso, el onboarding de AWS CloudConnect y el data source de Ava AI.

Si todavía estás en una release v0.x, este es un gran momento para actualizar. Las versiones v0.x fueron un technical preview; v1.x es la línea estable, lista para producción, con migración automática del state para que la transición sea fluida. Consulta la guía de actualización a v1.0.0 para ver las instrucciones de migración.

El provider es open source en github.com/doitintl/terraform-provider-doit. Damos la bienvenida a issues, feature requests y contribuciones. Cada recurso tiene tests de aceptación que corren contra la API real de DoiT, y el módulo CloudConnect AWS es el primero de una serie de módulos de más alto nivel que componen recursos del provider en patrones listos para usar.

Empieza ahora

  1. Instálalo desde el Terraform Registry
  2. Crea una API key
  3. Recorre la documentación completa para ver detalles de schema y más ejemplos
  4. Dale una estrella al repo de GitHub y cuéntanos qué te gustaría ver a continuación

Tus prácticas de FinOps merecen el mismo control de versiones, peer review y reproducibilidad que tu infraestructura. Prueba el provider y lleva tu cloud intelligence al código.