Terraform Plan Summarizer · IaC
Sumarizador de plano do Terraform — leia o plano antes de aplicar
Cole a saída do terraform plan — com cores ANSI e CRLF de um log de CI, sem problema — ou do terraform show -json tfplan. Adds, changes, destroys e replacements são contados como quatro números separados, cada atributo forces replacement é nomeado no recurso a que pertence, e tudo que destrói um banco de dados, um NAT gateway ou um control plane de cluster sobe para o topo. Depois os totais são checados contra a própria linha de resumo do Terraform — porque um leitor de plano que diverge em silêncio é pior do que nenhum.
Roda no seu navegador — nada do que você cola sai desta página. Como comprovamos isso
Playground do sumarizador de plano do Terraform
Both formats work and the format is detected for you: the human-readable terraform plan transcript (ANSI colour codes and CRLF from a CI log are fine) or terraform show -json tfplan. Up to 2 MiB — roughly a 50,000-line plan. It stays in this tab: there is no server here to send it to, which matters, because plan output is full of account IDs, ARNs, CIDRs and policy JSON.
Results update as you type — press Enter to run now.
By action puts replacements and destroys first, because those are the ones that can take something down. By module follows the code instead, which is what you want when one module call is the thing under review.
Paste a plan to see adds, changes, destroys and replacements counted separately, the replacement-forcing attributes named, and the totals cross-checked against Terraform’s own summary line.
A lacuna
O único -/+ que importa está na linha 310.
Um plano real são milhares de linhas de diff de atributos, e a parte que pode derrubar a produção tem três caracteres de largura. Revisar um plano em um pull request é rolar um log de CI dobrado procurando um -/+ entre centenas de mudanças de tag ~, e depois rolar mais para achar o comentário # forces replacement que diz qual atributo causou. O resumo do fim não ajuda: 2 to add se lê como duas coisas novas, quando uma delas é o seu banco de dados sendo destruído e reconstruído.
Então as pessoas colam o plano em um chatbot. É a pior opção disponível, e por dois motivos. Primeiro, exfiltração: a saída de um plano carrega IDs de conta, ARNs, faixas de sub-rede e CIDR, documentos de política IAM, regras de security group e nomes DNS internos — um documento com o desenho da sua rede que você nunca anexaria a um ticket, entregue a um terceiro e, nos planos de consumo, aos dados de treinamento. Segundo, precisão: um modelo de linguagem lendo um plano faz reconhecimento de padrões sobre texto. Atribui um comentário forces replacement ao recurso errado, descarta recursos em silêncio quando a colagem está truncada, e soma com confiança números que nunca contou.
Esta página é a versão de dados de verdade da mesma pergunta, e é deliberada exatamente no ponto que uma resposta de IA não consegue oferecer: uma declaração de quanto ela não sabe. A saída legível do Terraform não é uma interface estável, então a lista de recursos lida é somada e comparada com a própria linha Plan: do Terraform, sempre. Quando as duas concordam, isso é dito. Quando não concordam — que é a cara de uma colagem de CI truncada — os dois números são nomeados e o do Terraform é apontado como o que vale. O sexto chip de exemplo é exatamente esse caso: um log do GitHub Actions cujo meio o visualizador dobrou, em que a linha do Terraform informa 4 to add, 3 to change e 2 to destroy e apenas 2, 1 e 1 sobreviveram à cópia.
Revisando a pipeline que roda o plano, e não o plano? O validador do GitHub Actions e o validador do GitLab CI checam o workflow, e o verificador de .env.example acha as variáveis que ele esqueceu de passar.
A pipeline
Como funciona.
Cinco passos determinísticos, todos dentro da sua aba — dois parsers atrás de um único ponto de entrada que detecta o formato, e uma checagem cruzada que transforma um formato de entrada instável em uma resposta honesta.
-
Detectar o formato — e dizer quando o arquivo é outro.
JSON ou texto é decidido pelo primeiro caractere e pelas chaves presentes. Um dump de state, um resultado de terraform validate -json ou um JSON cortado no meio de um array recebem cada um o seu nome, com o comando que produz um plano de verdade — nunca um "entrada inválida" seco.
-
Remover ANSI, normalizar quebras de linha.
Um plano copiado do GitHub Actions, GitLab ou Jenkins chega embrulhado em escapes de cor e quebras CRLF. Os dois são removidos antes de qualquer parse, então uma colagem de CI e uma de terminal produzem saída idêntica. A entrada é limitada a 2.097.152 caracteres — 2 MiB, mais ou menos um plano de 50.000 linhas.
-
Ler os recursos, não o diff.
Cada linha de cabeçalho "# <endereço> …" carrega o caminho de módulo e o índice, então é ela que vale como fonte de verdade para o endereço; a linha de símbolo abaixo contribui com a ordem da substituição. Dentro de cada bloco só três coisas são procuradas: "# forces replacement", "(sensitive value)" e o motivo "(because …)" que o Terraform dá, mantido literal.
-
Ordenar pelo que quebra, não pelo que mudou.
Uma tabela de 17 padrões de tipo de recurso em quatro classes — armazém de dados, rota de saída, control plane, chave de criptografia — marca apenas ações destrutivas, com uma frase que nomeia o que exatamente se perde: os dados, o IP público de saída, os kubeconfigs. Um tipo que não está na tabela fica sem classificação, e a página diz isso em vez de insinuar que é seguro.
-
Checar o total e se recusar a errar com confiança.
A lista lida é somada do jeito do Terraform — cada substituição contando uma vez como add e uma vez como destroy — e comparada com a linha "Plan:". A concordância é declarada. A divergência é um aviso que nomeia os dois números e diz para confiar no Terraform. Nada aqui adivinha em silêncio.
Referência
Todos os símbolos que um plano pode imprimir.
Nove glifos e anotações carregam todo o significado de um plano. Seis são ações, três são notas sobre um valor — e dois dos seis diferem apenas na ordem de duas operações, que é a diferença entre uma mudança gradual e uma queda.
| Símbolo | O que significa |
|---|---|
| + create | Um objeto novo. Nada existe ainda, então a maioria dos atributos aparece como (known after apply). |
| ~ update in-place | O objeto existente é modificado. O id sobrevive, e tudo que está guardado nele também. |
| - destroy | O objeto é apagado e não recriado. Procure a linha (because …): ela dá o motivo. |
| -/+ destroy then create | Uma substituição, objeto antigo primeiro. Existe uma janela sem nada — o caso padrão, e o que se deve ler com atenção. |
| +/- create then destroy | Uma substituição com create_before_destroy = true. O objeto novo existe antes de o antigo sair. |
| <= read during apply | Uma data source que não pode ser resolvida no momento do plano. Nunca faz parte de add, change ou destroy. |
| # forces replacement anotação de atributo | Este atributo não pode mudar no lugar, então o objeto inteiro é substituído. O único comentário que vale um grep. |
| (known after apply) anotação de valor | O provider atribui na criação, então realmente ainda não existe. Não é erro. |
| (sensitive value) anotação de valor | Marcado como sensível, e o plano esconde. Repare: no arquivo de state continua em texto claro. |
Por que uma substituição é contada duas vezes
O Terraform conta operações. Esta página conta recursos, e imprime os números do Terraform ao lado para que nenhum seja confundido com o outro.
Plan: 2 to add, 0 to change, 1 to destroy.
what Terraform counted what actually happens
──────────────────────── ─────────────────────
+ aws_iam_role.app one NEW role
-/+ aws_db_instance.primary one database replaced
counted as +1 add
counted as +1 destroy
this page shows them apart:
+ add 1 created outright
~ change 0 updated in place
− destroy 0 destroyed outright
± replace 1 destroyed and recreated Conseguir o arquivo certo
show -json contra um plano salvo é a entrada confiável; a transcrição de texto é a que você já tem. Dois quase-acertos são reconhecidos e nomeados.
# The reliable path: save the plan, then read the machine format
terraform plan -out=tfplan
terraform show -json tfplan > plan.json # paste plan.json above
# The path you already have: the text a pipeline printed
terraform plan -no-color # -no-color if you can; ANSI is fine either way
# What NOT to paste — both are told apart from a plan and named
terraform show -json # this is STATE, it has no resource_changes
terraform validate -json # this is a config check, not a plan Próximo passo
O plano está certo. Agora confira a pipeline que o executa.
Um plano só é tão confiável quanto o workflow que o produziu: o validador do GitHub Actions e o validador do GitLab CI pegam os erros de pipeline que fazem um plano rodar contra o state errado ou as credenciais erradas, e o verificador de .env.example acha a variável que o seu job nunca passou. Todos, como esta página, rodam inteiramente no seu navegador.
+ add 1 ~ change 1 − destroy 0 ± replace 1
read this first — 1 high blast radius
module.data.aws_db_instance.primary data store
forces replacement: engine_version
destroy then create — the database does not exist in between
cross-check: reconciles
Terraform printed: Plan: 2 to add, 1 to change, 1 to destroy.
(the replacement is one of those adds AND the destroy) FAQ
Suas perguntas, respondidas.
Toque em uma pergunta para expandir a resposta.
Quais formatos de plano são aceitos?
Os dois, e o formato colado é detectado para você. O primeiro é a transcrição legível que o Terraform imprime — aquela com +, ~, - e -/+ na margem esquerda — incluindo os códigos de cor ANSI e as quebras de linha CRLF que aparecem ao copiar de um log de CI. O segundo é terraform show -json tfplan, o formato de máquina, que carrega resource_changes, replace_paths, action_reason e output_changes e é uma interface documentada e versionada. O JSON é mais confiável e é o que usar quando você pode salvar um arquivo de plano; o texto é o que você realmente tem depois que a pipeline já rodou. O que NÃO é aceito é terraform show -json do seu state, nem a saída do terraform validate -json — as duas confusões mais comuns, e nos dois casos a ferramenta diz o que aquilo é e qual comando produz a coisa certa.
Qual é a diferença entre -/+ e +/- em um plano?
A ordem das duas operações — e é ela que decide se há indisponibilidade. -/+ significa destruir e depois criar: o objeto antigo desaparece antes de o novo existir, então tudo que depende dele fica quebrado durante essa janela — segundos para uma regra de security group, vinte minutos para uma instância RDS. +/- significa criar e depois destruir, que é exatamente o que lifecycle { create_before_destroy = true } compra: o substituto é construído e só então o objeto antigo é removido. O Terraform escolhe destruir-primeiro por padrão, então +/- só aparece onde alguém pediu. Esta página escreve as duas ordens em palavras em cada linha de substituição, em vez de fazer você decifrar um glifo de três caracteres.
O que "forces replacement" quer dizer, na prática?
Marca o atributo específico cuja mudança não pode ser aplicada no lugar, de modo que o provider tem que apagar o objeto e construir um novo. É por atributo, e aí está a utilidade: engine_version em um aws_db_instance é um upgrade real que você quis fazer, enquanto availability_zone ou name mudando por acidente — por uma variável renomeada, uma tag reformatada, um padrão do provider que se moveu — é a substituição-surpresa clássica. Esta página tira cada um desses nomes de atributo do bloco a que pertence e mostra como chips na linha daquele recurso, para você nunca precisar rolar um diff de 400 linhas caçando o comentário.
Por que uma substituição conta como "add" e como "destroy" ao mesmo tempo?
Porque o Terraform conta operações, não recursos, e uma substituição são duas operações. Então um plano com um create simples e uma substituição imprime "Plan: 2 to add, 0 to change, 1 to destroy": a substituição entra nos dois números. Está correto, e é também a linha mais mal lida de toda a saída do Terraform, porque "2 to add" soa como duas coisas novas. Esta página mostra, em vez disso, quatro cartões disjuntos: add é criado direto, replace é destruído e recriado, e nada é contado duas vezes. A contabilidade do próprio Terraform é impressa embaixo, literal, para que as duas possam ser comparadas em vez de confundidas.
É seguro colar um plano aqui?
Sim — e é justamente por isso que esta página existe nessa forma. Não há servidor atrás dela: o parser é JavaScript que carrega na sua aba e roda ali, então o plano nunca sai da sua máquina — você pode confirmar na aba de rede do navegador, ou carregando a página e ficando offline depois. Isso importa mais com a saída de um plano do que com quase qualquer outra coisa que você colaria em uma ferramenta web: um plano está cheio de IDs de conta, ARNs, faixas de sub-rede e CIDR, documentos de política IAM, regras de security group e nomes DNS internos. Colar um desses num chatbot entrega tudo isso a um terceiro e, nos planos de consumo da maioria dos assistentes, aos dados de treinamento.
Os números não fecham — o que significa o aviso de divergência?
Significa que os recursos que esta página conseguiu ler não somam os totais da própria linha de resumo do Terraform, e nove de cada dez vezes a colagem está incompleta: um visualizador de log de CI dobrou o meio, um buffer de scrollback cortou, ou a cópia começou no meio do caminho. O aviso nomeia os dois conjuntos de números e diz para confiar no Terraform. O motivo de ele existir: a saída legível do Terraform explicitamente não é uma interface estável, então um parser de texto vai acabar divergindo em alguma mudança de formato — e um sumarizador que diverge em silêncio imprimiria um total errado com confiança, o que é pior do que não imprimir nada. Essa checagem cruzada é o que torna defensável fazer o parse de um formato instável.
O que significa "(known after apply)" e por que não há valor?
Significa que o valor ainda não existe. Atributos como um ARN, um id, um nome DNS gerado ou um endereço IP são atribuídos pelo provider na criação, então no momento do plano o Terraform realmente não os conhece e se recusa a adivinhar. Não é erro nem aviso — um plano de algo novo é cheio deles. Tem, sim, uma consequência prática: um recurso cuja entrada depende de um valor desconhecido também não pode ser avaliado por completo, e é por isso que às vezes você vê uma data source marcada como "read during apply" em vez de resolvida, e por isso um apply pode acabar fazendo mais do que o plano mostrou.
Funciona com OpenTofu?
Sim. O OpenTofu foi forkado do Terraform 1.5.x e manteve os dois formatos de saída: a transcrição de texto usa os mesmos símbolos e a mesma linha "Plan: N to add, N to change, N to destroy", e tofu show -json emite a mesma família de format_version com a mesma estrutura de resource_changes. Tudo nesta página se aplica sem mudanças, e a linha de versão é lida conforme o produto que a imprimiu. O mesmo vale para os wrappers que repassam a saída do Terraform sem alterar — Terragrunt, Atlantis, Spacelift — desde que o texto do plano esteja intacto.
Contra quais versões do Terraform isso é testado?
O caminho JSON é escrito contra format_version 0.1 a 1.x, o que cobre Terraform 0.12 a 1.9 e o OpenTofu atual; um documento com versão major desconhecida é aceito, mas carrega um aviso, porque um campo renomeado produziria zeros em silêncio. O caminho de texto é testado contra as formas de 1.5 em diante, onde "N to import" entrou na linha de resumo e onde aparecem os blocos moved e import; saídas mais antigas em boa parte fazem parse, e o que não faz é pego pela checagem cruzada dos números em vez de reportado como fato. A única coisa que esta página nunca vai fazer é estimar custo: preços envelhecem, e um número velho impresso com confiança é exatamente o tipo de resposta que este site existe para substituir.
More free, private DevOps tools.
O sumarizador de plano do Terraform é uma das ferramentas do OpsCanopy — uma copa crescente de validadores, conversores e testers que rodam no navegador e nunca tocam um servidor.
39 ferramentas gratuitas, todas capazes de funcionar offline — o opscanopy.com não exige cadastro e não envia nada.
Ferramentas de infraestrutura relacionadas: o conversor de docker run para Compose, o verificador de .env.example para as variáveis que um deploy esqueceu, e os validadores de GitHub Actions e GitLab CI para a pipeline que executa o seu plano — ou navegue pelo diretório completo de ferramentas.
Fornecido como está, por conveniência. Sem afiliação com a HashiCorp. Esta página resume o que um plano diz; ela não estima custo e não vai estimar — preços envelhecem, e um número velho impresso com confiança é a única resposta que uma ferramenta de dados de verdade não pode dar. Um tipo de recurso ausente da tabela de raio de impacto está sem classificação, não comprovadamente seguro. OpsCanopy é livre e gratuito.