Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

FinOps as Code: gerencie o DoiT Cloud Intelligence com Terraform

By Hannes HayashiJun 25, 202611 min read

Esta página também está disponível em English, Deutsch, Español, Français, Italiano e 日本語.

Você versiona sua infraestrutura e revisa pull requests do código da aplicação. Mas e a sua configuração de FinOps — budgets, alocações de custo, alertas e relatórios analíticos?

Na maioria dos times, essas configurações ficam em uma UI. Alguém passa por um wizard, define um threshold, escolhe um filtro e torce para que a próxima pessoa que precisar mexer ali consiga entender o que foi feito. Não há histórico, nem peer review, nem como replicar o setup entre ambientes. Quando suas práticas de FinOps são tão críticas quanto sua infraestrutura, elas merecem o mesmo rigor.

Foi por isso que criamos o provider Terraform da DoiT. Ele leva sua configuração do DoiT Cloud Intelligence para o mesmo fluxo de Infrastructure as Code que você já usa para recursos de nuvem — com 17 recursos gerenciados e 61 data sources que cobrem desde budgets e relatórios até consultas ao assistente de IA e diagramas de infraestrutura em nuvem.

Primeiros passos

Para começar, basta um bloco de provider e uma API key:

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

Defina DOIT_API_TOKEN no seu ambiente (dá para criar API keys no DoiT Console) e pronto. É só isso — nenhuma configuração adicional.

O fluxo central de FinOps

Vamos passar pelos recursos que a maioria dos times adota primeiro: alocações, budgets, alertas e relatórios. Juntos, eles formam um pipeline completo de FinOps — e gerenciá-los como código permite versionar, revisar e replicar todo o setup.

Alocações de custo

As alocações são a forma de fatiar o gasto em nuvem em categorias que fazem sentido. O provider conta com um motor de fórmulas booleanas para combinar critérios de filtro, alocações em grupo que dividem custos em buckets nomeados e até alocações aninhadas que referenciam outras alocações por ID.

Veja uma alocação em grupo que divide os custos por região, com um catch-all para o que não se encaixar:

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"]
}]
}
]
}

Precisa de mais granularidade? Use type = "allocation_rule" em um componente para referenciar uma alocação existente — compondo alocações a partir de outras, em até 3 níveis de profundidade. E em vez de cravar valores de dimensão como "US" ou "DE" no código, dá para usar o data source doit_dimension para descobrir os valores válidos dinamicamente via API.

Budgets

Budgets são as guardrails. O provider permite definir alertas com múltiplos thresholds, restringir o escopo de budgets a alocações ou dimensões específicas e — aqui vai um padrão útil — filtrar colaboradores por função em vez de adicionar todo mundo da organização:

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]
}]
}

Esse budget tem escopo na alocação por região que acabamos de criar e só notifica usuários com o cargo "Software / Ops Engineer". Os budgets também suportam seasonal_amounts para meses em que suas metas de gasto variam, e campos computados como current_utilization e forecasted_utilization ficam disponíveis como saídas somente leitura.

Alertas

Alertas disparam notificações quando o custo ou o uso ultrapassa um threshold. A grande sacada aqui é o escopo — você pode restringir um alerta a um provedor de nuvem, serviço, região ou qualquer dimensão. Este exemplo usa o data source doit_products para buscar dinamicamente o ID do serviço Compute Engine, em vez de deixá-lo cravado no código:

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]
}

Relatórios

Os relatórios do Cloud Analytics são o recurso mais completo do provider. Dá para configurar até 4 métricas, adicionar comparações ano a ano com secondary_time_range, aplicar filtros e dimensões de group-by e organizar relatórios em pastas.

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"
}
}

Se precisar descobrir IDs e tipos de dimensão válidos para filtros e agrupamentos, o data source doit_dimensions entrega um catálogo completo — chega de chutar.

Além do FinOps

Os recursos centrais de FinOps são por onde a maioria dos times começa, mas o provider cobre bem mais coisa da plataforma DoiT. Algumas dessas funcionalidades você pode nem saber que existem no console — e gerenciá-las como código é uma ótima forma de descobri-las.

Pergunte para a Ava direto do Terraform

Sim, dá para consultar a Ava — a assistente de IA da DoiT — diretamente da sua configuração Terraform. O que torna isso especialmente útil é poder referenciar IDs de relatórios de outros recursos Terraform no seu 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
}

Crie um relatório e, logo em seguida, peça à Ava para explicá-lo — tudo no mesmo terraform apply. Também dá para usar isso em consultas rápidas como "Quais são meus 3 principais serviços de nuvem por custo neste mês?" e direcionar a resposta para outputs do Terraform.

Consultas analíticas ad-hoc

Às vezes você não precisa de um relatório persistido — só quer responder a uma pergunta. O data source doit_report_query roda consultas do Cloud Analytics na hora e retorna JSON estruturado, que você pode parsear, transformar ou 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)])]
))
}

Isso é especialmente útil para cost gates em CI/CD — rode uma consulta no pipeline, verifique se o gasto ultrapassa um threshold e quebre o build se for o caso. Você também pode usar doit_report_result para buscar resultados de relatórios já salvos.

Diagramas de nuvem como fluxogramas Mermaid

O provider inclui 12 data sources para a funcionalidade Cloud Diagrams, cobrindo busca, exportação, relacionamentos, snapshots e estatísticas. Um caso de uso criativo: gerar fluxogramas Mermaid a partir da topologia da sua infraestrutura em nuvem, que dá para embutir diretamente em READMEs, páginas do Confluence ou relatórios de incidente.

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
}

Cole a saída no mermaid.live ou em qualquer renderizador de Markdown e você terá uma representação visual dos relacionamentos da sua infraestrutura — diffs de topologia ao longo do tempo, snapshots de compliance ou só uma visão rápida do que está conectado a quê.

Compartilhamento e controle de acesso

Gerenciar quem pode ver seus recursos de FinOps costuma ficar para depois — até o dia em que não dá mais. O recurso doit_sharing permite definir permissões para relatórios, budgets, alertas e alocações:

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
}

Defina seus conjuntos de permissões uma vez em locals e aplique-os de forma consistente em todos os recursos compartilhados. Combine isso com doit_user para o onboarding de novos integrantes do time e doit_roles para descobrir as roles disponíveis — tudo direto da sua configuração Terraform.

Anotações e labels

Já olhou para um pico de custo de seis meses atrás e ficou se perguntando o que tinha acontecido? As anotações permitem documentar eventos de custo — deploys, migrações, incidentes — diretamente sobre seus dados de custo:

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]
}

Labels e suas atribuições oferecem tagging cross-resource — categorize relatórios, alertas e anotações por time, projeto ou qualquer taxonomia que faça sentido para a sua organização.

Organização em escala com pastas

À medida que sua configuração de FinOps gerenciada por Terraform cresce, as pastas mantêm tudo no lugar. Elas suportam aninhamento e funcionam tanto para relatórios quanto para alocações:

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 ...
}

Também dá para personalizar a identidade visual dos seus analytics com temas customizados — defina paletas de cores para os modos claro e escuro que se aplicam aos gráficos dos relatórios do Cloud Analytics, deixando seus dashboards com um visual caprichado e alinhado à marca.

Onboarding do AWS CloudConnect

Conectar contas AWS ao DoiT costuma ser um processo de várias etapas: criar uma IAM role, configurar um bucket S3, registrar a conta. Publicamos um módulo Terraform dedicado que cuida da stack inteira em um único terraform apply:

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

O módulo cria a IAM role, o bucket S3 e o registro no CloudConnect de uma vez só. Para empresas fazendo o onboarding de dezenas de contas, use-o com for_each sobre uma lista de contas. Se precisar de mais controle, o recurso subjacente doit_cloudconnect_aws_account está disponível para uso direto.

Insights customizados

Se você roda suas próprias verificações de otimização — varrendo recursos ociosos, identificando oportunidades de right-sizing, sinalizando problemas de segurança — pode publicar os achados direto no console da DoiT:

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"]
}

Combine isso com doit_insight_resource_results para anexar achados por recurso, e seu motor de otimização customizado passa a mostrar os resultados ao lado dos insights nativos da DoiT.

O padrão de composabilidade

Em todos esses exemplos, dá para perceber um tema recorrente: os data sources são a cola. Em vez de deixar IDs de dimensão, nomes de serviço ou e-mails de usuário cravados no código, você descobre tudo em tempo 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] }
}

Esse mapa de lookup de dimensões é reutilizável em relatórios, budgets, alertas e alocações — escreva uma vez e referencie local.dimension_types["region"] em todo lugar. Da mesma forma, doit_current_user elimina e-mails cravados no código, doit_products descobre valores válidos para filtros de serviço e doit_platforms lista os provedores de nuvem disponíveis para a sua organização.

Em desenvolvimento ativo e open source

O provider teve 5 releases menores nos quatro meses desde o lançamento da v1.0, em fevereiro de 2026, e cada uma trouxe novos recursos e data sources. Entre os destaques recentes estão suporte a Cloud Diagrams, temas customizados de console, gestão de pastas, compartilhamento e controle de acesso, onboarding do AWS CloudConnect e o data source da Ava AI.

Se você ainda está em uma release v0.x, este é um ótimo momento para atualizar. As versões v0.x eram um technical preview — a linha v1.x é a estável e pronta para produção, com migração automática de estado para tornar a transição tranquila. Confira o Guia de Upgrade da v1.0.0 para as instruções de migração.

O provider é open source em github.com/doitintl/terraform-provider-doit. Aceitamos issues, feature requests e contribuições. Todo recurso conta com testes de aceitação que rodam contra a API real da DoiT, e o módulo CloudConnect AWS é o primeiro de uma série de módulos de mais alto nível que combinam recursos do provider em padrões prontos para uso.

Comece agora

  1. Instale a partir do Terraform Registry
  2. Crie uma API key
  3. Explore a documentação completa para detalhes de schema e mais exemplos
  4. Dê uma estrela no repositório do GitHub e conte para a gente o que gostaria de ver a seguir

Suas práticas de FinOps merecem o mesmo controle de versão, peer review e reprodutibilidade que sua infraestrutura. Experimente o provider e coloque seu cloud intelligence sob código.