Marcio Cunha

Orquestração de Testes de Fumaça em Infraestrutura Efêmera com Terraform e Terratest

Aprenda a provisionar ambientes temporários e validar a integridade de sistemas distribuídos antes do deploy utilizando Terraform e Terratest em fluxos de integração contínua.

Marcio Cunha•5 min
Também disponível em:EnglishEspañol
Resumo
  • Infraestruturas efêmeras eliminam o problema do estado corrompido ao destruir o ambiente logo após a validação.
  • Terratest permite escrever testes automatizados em linguagem Go para infraestrutura como código de forma programática.
  • Testes de fumaça garantem que os serviços essenciais respondem corretamente logo após o provisionamento inicial.
  • A integração contínua executa validações completas sem poluir o cluster de produção com recursos órfãos.
  • O uso combinado de Terraform e testes integrados reduz drasticamente o tempo médio de detecção de falhas em deploy.

O Desafio de Validar Ambientes que Nascem e Morrem

Na engenharia de software moderna, provisionar servidores manualmente virou coisa do passado. Hoje usamos a infraestrutura como código, ou IaC, que significa escrever arquivos de texto para descrever servidores, redes e bancos de dados. Com isso, criamos o conceito de infraestrutura efêmera: ambientes inteiros que nascem sob demanda para um propósito específico, como rodar testes automatizados, e depois desaparecem sem deixar rastros.

Na prática, isso evita que um teste falhe porque sobrou lixo de uma execução anterior. No entanto, surge um novo desafio: como garantir que o ambiente recém-criado realmente funciona antes de liberar o tráfego de produção? É aqui que entram os testes de fumaça, um conceito empregado originalmente na eletrônica para verificar se um circuito fumegava ao ser ligado pela primeira vez, indicando um curto-circuito grave.

No desenvolvimento de software, um teste de fumaça é uma verificação rápida e superficial das funcionalidades mais críticas de um sistema. Quando aplicados à infraestrutura efêmera, eles verificam se os servidores responderam, se os bancos de dados aceitam conexões e se as rotas de rede estão ativas. Sem essa automação, equipes perdem horas investigando falhas que poderiam ser evitadas com validações programáticas logo na primeira inicialização.

A Escolha das Ferramentas: Terraform e Terratest

Para colocar essa estratégia em prática, escolhemos duas ferramentas consagradas no ecossistema corporativo: o Terraform e o Terratest. O Terraform, criado pela HashiCorp, é a ferramenta líder para gerenciar recursos em nuvem de forma declarativa, permitindo construir e destruir toda a arquitetura com comandos simples no terminal. Ele lê nossos arquivos de configuração e conversa com provedores como AWS, Google Cloud ou Azure.

Por outro lado, o Terratest é uma biblioteca escrita em Go, desenvolvida pela Gruntwork, especializada em testar código de infraestrutura. Enquanto o Terraform apenas cria os recursos, o Terratest consegue executar comandos de verificação logo em seguida. Na prática, ele age como um inspetor de obras rigoroso que entra no prédio recém-construído para testar se as portas abrem e se a água corre pelas torneiras antes de entregar as chaves ao morador.

O uso conjunto dessas ferramentas forma um ciclo virtuoso de segurança e velocidade. O pipeline de integração contínua dispara a criação do ambiente temporário via Terraform, o Terratest valida se tudo está no lugar e respondendo, e logo em seguida o próprio pipeline destrói o ambiente para economizar custos. Se qualquer etapa falhar, o processo é interrompido imediatamente, impedindo que alterações incorretas avancem para os ambientes compartilhados.

Escrevendo o Código de Provisionamento e Validação

Para entender o fluxo na prática, precisamos estruturar nosso projeto dividindo-o entre os arquivos de infraestrutura e os scripts de teste. Começamos criando um módulo Terraform básico que sobe uma instância de servidor isolada em nuvem com uma aplicação web simples instalada. Esse arquivo define o tipo de máquina, as regras de segurança da rede e o script inicial que inicializa o serviço.

Em seguida, escrevemos o código de teste utilizando a linguagem Go e a biblioteca Terratest. O teste precisa seguir uma sequência lógica rigorosa de execução para garantir que o ambiente esteja totalmente pronto antes de realizar as requisições HTTP de validação. Abaixo está um exemplo funcional de como essa estrutura se comporta no diretório de testes do projeto.

package test

import (
	"testing"
	"time"
	"github.com/gruntwork-io/terratest/modules/terraform"
	"github.com/gruntwork-io/terratest/modules/http-helper"
)

func TestTerraformAwsWebExample(t *testing.T) {
	terraformOptions := &terraform.Options{
		TerraformDir: "../examples/terraform-basic",
	}

	defer terraform.Destroy(t, terraformOptions)

	terraform.InitAndApply(t, terraformOptions)

	publicIp := terraform.Output(t, terraformOptions, "public_ip")
	url := "http://" + publicIp + ":80"

	http-helper.HttpGetWithRetry(t, url, nil, 200, "Hello, World!", 30, 5*time.Second)
}

Neste trecho de código, a função de teste inicializa o Terraform, aplica a configuração para subir o servidor, captura o endereço IP público gerado e utiliza um auxiliar HTTP para tentar acessar a página web repetidas vezes até obter um código de status duzentos. O comando para destruir os recursos é garantido ao final da execução por meio de um comando de adiamento, o que assegura que nenhum servidor fique rodando e gerando custos indevidos.

Integrando o Ciclo de Vida no Pipeline de CI/CD

Criar o código de teste localmente é apenas o primeiro passo; o verdadeiro valor dessa abordagem aparece quando inserimos o processo em um pipeline de integração contínua, como GitHub Actions ou GitLab CI. O servidor de automação precisa ter instaladas as ferramentas necessárias, como o interpretador da linguagem Go, a CLI do Terraform e credenciais válidas de acesso à nuvem.

Durante cada envio de código para o repositório, o pipeline executa o comando de testes automatizados. Na prática, isso significa que qualquer alteração nas configurações de rede, nas políticas de segurança ou nas versões do sistema operacional passará pelo crivo do Terratest antes de ser aceita no branch principal. Isso elimina o fator humano de esquecer de testar uma alteração crítica de infraestrutura.

Além da segurança, essa prática transforma a documentação do projeto. Como o código de teste descreve exatamente o comportamento esperado da infraestrutura, novos engenheiros conseguem entender rapidamente quais portas devem estar abertas e quais respostas HTTP a aplicação precisa retornar. O código passa a ser a única fonte da verdade, unindo desenvolvimento, operações e garantia de qualidade em um fluxo unificado.

Considerações Finais sobre Resiliência Operacional

A adoção de infraestrutura efêmera combinada com testes automatizados via Terraform e Terratest representa uma mudança profunda na maturidade operacional das equipes de tecnologia. Ao tratar a infraestrutura com o mesmo rigor de código aplicado ao desenvolvimento de software tradicional, eliminamos a famosa desculpa de que o sistema funcionava apenas na máquina do desenvolvedor.

Embora exista uma curva de aprendizado inicial para dominar a linguagem Go e a sintaxe dos testes, o retorno sobre o investimento se paga rapidamente com a redução drástica de incidentes em produção. Sistemas que nascem testados e morrem logo em seguida garantem um ciclo de entrega contínua muito mais seguro, previsível e escalável para empresas de qualquer porte.