Post

Estação de Trabalho como Código (Parte 9): Testando e Validando Imagens com Testes Automatizados

Aprenda a testar e validar as imagens criadas com Packer antes de usá-las em produção. Este tutorial cobre como criar máquinas virtuais de teste, executar suites de testes automatizados, validar configurações de segurança e funcionalidade, e gerar relatórios de validação.

Estação de Trabalho como Código (Parte 9): Testando e Validando Imagens com Testes Automatizados

Tutorial Anterior: Estação de Trabalho como Código (Parte 8): Criando Imagens com Packer

Introdução

Criar imagens com Packer é apenas metade da história. A outra metade é garantir que essas imagens funcionem conforme esperado. Antes de usar uma imagem em produção ou em um laboratório crítico, você deve testá-la e validá-la. Isso envolve iniciar máquinas virtuais a partir da imagem, executar testes de funcionalidade, verificar configurações de segurança e garantir que tudo está funcionando corretamente.

Neste tutorial, vamos aprender a criar um framework de testes para validar nossas imagens. Vamos usar Terraform para provisionar máquinas virtuais de teste, scripts Bash para executar testes de funcionalidade e segurança, e colecionar os resultados em um relatório estruturado.

Observação: Esta parte é essencial para garantir qualidade das imagens antes de usar em produção. Se você preferir apenas provisionar VMs sem testes, pode pular para a Parte 10. No entanto, recomendamos completar esta parte para entender boas práticas de QA.

Objetivos desta Parte

  • Entender a importância de testes em infraestrutura como código
  • Criar estrutura de testes para validar imagens
  • Usar Terraform para provisionar máquinas virtuais de teste
  • Desenvolver scripts de teste automatizados
  • Executar testes de funcionalidade e segurança
  • Gerar relatórios de validação
  • Integrar testes com fluxo de CI/CD
  • Documentar e versionar testes

Pré-requisitos

  • Conclusão da Parte 8 desta série
  • Imagens Packer construídas com sucesso
  • Terraform funcionando corretamente
  • Conhecimento básico de Bash scripting

A quem se destina

Este tutorial é ideal para:

  • DevOps Engineers: Que precisam validar imagens antes de produção
  • SysAdmins: Que querem garantir qualidade de infraestrutura
  • QA Engineers: Que trabalham com infraestrutura
  • Profissionais de TI: Que querem implementar boas práticas

Pré-conhecimento: Conhecimento básico de Terraform, Bash e testes (coberto nas partes anteriores) é recomendado.

Tempo Estimado

90-120 minutos

Isso inclui:

  • Leitura e compreensão: ~15 min
  • Preparação de estrutura: ~10 min
  • Criação de testes: ~30 min
  • Execução de testes: ~20 min
  • Análise de resultados: ~15 min

Dica Útil: Testes podem ser reutilizados para múltiplas imagens, economizando tempo no futuro.


Entendendo Testes em Infraestrutura

Antes de começar, é importante entender por que testes são importantes.

Por que Testar Imagens?

Razões principais:

  1. Garantir Funcionalidade - Verificar que todos os pacotes estão instalados
  2. Validar Segurança - Confirmar que hardening foi aplicado
  3. Detectar Problemas Cedo - Antes de usar em produção
  4. Documentar Comportamento - Deixar claro o que a imagem faz
  5. Facilitar Manutenção - Testes ajudam a identificar regressões

Tipos de Testes

TipoDescriçãoExemplos
FuncionalidadeVerifica se recursos funcionamPacotes instalados, serviços rodando
SegurançaValida configurações de segurançaPermissões, hardening, atualizações
PerformanceMede desempenhoTempo de boot, uso de recursos
CompatibilidadeTesta com diferentes ambientesDiferentes hipervisores, redes
RegressãoDetecta mudanças indesejadasComparação com versão anterior

Verificando Pré-Requisitos

Antes de começar, certifique-se de que seu ambiente está pronto.

Passo 1: Verificar Imagem Packer

1
2
3
4
5
# Verifique se a imagem foi criada
$ ls -lh ~/workspace-as-code/kvm/templates/debian12-packer.qcow2

# Você deve ver:
# -rw-r--r-- debian12-packer.qcow2 (~ 500 MB)

Passo 2: Verificar Terraform

1
2
3
4
5
# Verifique se Terraform está instalado
$ terraform --version

# Você deve ver:
# Terraform v1.14.5

Passo 3: Verificar LIBVIRT

1
2
3
4
5
# Verifique se libvirtd está rodando
$ systemctl is-active libvirtd

# Você deve ver:
# active

Criando Estrutura de Testes

Passo 1: Criar Diretórios

1
2
3
4
5
6
7
# Crie a estrutura de diretórios
$ mkdir -p ~/workspace-as-code/tests/image-validation/{terraform,scripts,reports}
$ cd ~/workspace-as-code/tests/image-validation

# Verifique
$ pwd
# /home/ubuntu/workspace-as-code/tests/image-validation

Passo 2: Criar Arquivos

1
2
3
4
5
6
7
# Crie os arquivos necessários
$ touch terraform/{main.tf,variables.tf,outputs.tf}
$ touch scripts/{test-functionality.sh,test-security.sh,test-performance.sh,run-all-tests.sh}
$ touch reports/.gitkeep

# Verifique
$ ls -la

Configurando Terraform para Testes

Passo 1: Criar main.tf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
$ cat > ~/workspace-as-code/tests/image-validation/terraform/main.tf << 'EOF'
terraform {
  required_version = ">= 1.7.0"
  required_providers {
    libvirt = {
      source  = "dmacvicar/libvirt"
      version = "~> 0.9.2"
    }
  }
}

provider "libvirt" {
  uri = "qemu:///system"
}

# Volume base da imagem
resource "libvirt_volume" "test_image_base" {
  name   = "debian12-test-base.qcow2"
  pool   = "templates"
  source = var.image_path
  format = "qcow2"
}

# Volume da VM de teste (cópia da imagem base)
resource "libvirt_volume" "test_image_disk" {
  name           = "debian12-test-${var.test_id}.qcow2"
  pool           = "images"
  base_volume_id = libvirt_volume.test_image_base.id
  format         = "qcow2"
}

# Cloud-Init para configuração de teste
resource "libvirt_cloudinit_disk" "test_cloudinit" {
  name           = "debian12-test-${var.test_id}-cloudinit.iso"
  user_data      = base64encode(templatefile("${path.module}/../cloud-init.yml", { ssh_key = file("~/.ssh/terraform-vms.pub") }))
  pool           = "images"
}

# Máquina Virtual de Teste
resource "libvirt_domain" "test_vm" {
  name   = "test-debian12-${var.test_id}"
  memory = var.vm_memory
  vcpu   = var.vm_cpus

  cpu {
    mode = "host-passthrough"
  }

  cloudinit = libvirt_cloudinit_disk.test_cloudinit.id

  network_interface {
    network_name   = var.network_name
    wait_for_lease = true
  }

  console {
    type        = "pty"
    target_port = "0"
    target_type = "serial"
  }

  disk {
    volume_id = libvirt_volume.test_image_disk.id
  }

  graphics {
    type        = "spice"
    listen_type = "none"
  }

  depends_on = [libvirt_volume.test_image_base]
}

# Output com informações da VM
output "vm_ip" {
  value       = libvirt_domain.test_vm.network_interface[0].addresses[0]
  description = "IP da máquina virtual de teste"
}

output "vm_name" {
  value       = libvirt_domain.test_vm.name
  description = "Nome da máquina virtual de teste"
}
EOF

# Verifique
$ cat ~/workspace-as-code/tests/image-validation/terraform/main.tf

Passo 2: Criar variables.tf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
$ cat > ~/workspace-as-code/tests/image-validation/terraform/variables.tf << 'EOF'
variable "image_path" {
  type        = string
  default     = "/home/ubuntu/workspace-as-code/kvm/templates/debian12-packer.qcow2"
  description = "Caminho da imagem Packer para teste"
}

variable "test_id" {
  type        = string
  default     = "001"
  description = "ID único para esta execução de testes"
}

variable "vm_memory" {
  type        = number
  default     = 2048
  description = "Memória em MB"
}

variable "vm_cpus" {
  type        = number
  default     = 2
  description = "Número de vCPUs"
}

variable "network_name" {
  type        = string
  default     = "lab-network"
  description = "Nome da rede"
}
EOF

# Verifique
$ cat ~/workspace-as-code/tests/image-validation/terraform/variables.tf

Passo 3: Criar outputs.tf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ cat > ~/workspace-as-code/tests/image-validation/terraform/outputs.tf << 'EOF'
output "test_vm_ip" {
  value       = libvirt_domain.test_vm.network_interface[0].addresses[0]
  description = "IP da máquina virtual de teste"
}

output "test_vm_name" {
  value       = libvirt_domain.test_vm.name
  description = "Nome da máquina virtual de teste"
}

output "test_image_path" {
  value       = var.image_path
  description = "Caminho da imagem testada"
}
EOF

# Verifique
$ cat ~/workspace-as-code/tests/image-validation/terraform/outputs.tf

Passo 4: Criar Cloud-Init

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
$ cat > ~/workspace-as-code/tests/image-validation/cloud-init.yml << 'EOF'
#cloud-config

# Gerenciar /etc/hosts
manage_etc_hosts: true

# Hostname
hostname: test-debian12
fqdn: test-debian12.lab

# Usuários
users:
  - name: debian
    gecos: "Debian User"
    sudo: "ALL=(ALL) NOPASSWD:ALL"
    groups: users, sudo
    shell: /bin/bash
    lock_passwd: false
    ssh_authorized_keys:
      - ${ssh_key}

# Permitir SSH com senha
ssh_pwauth: true

# Comandos a executar
runcmd:
  - echo "Cloud-Init concluído" > /var/log/cloud-init-custom.log

# Pacotes a instalar
packages:
  - curl
  - wget
EOF

# Verifique
$ cat ~/workspace-as-code/tests/image-validation/cloud-init.yml

Criando Scripts de Teste

Passo 1: Teste de Funcionalidade

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
$ cat > ~/workspace-as-code/tests/image-validation/scripts/test-functionality.sh << 'EOF'
#!/bin/bash
set -e

# Cores para output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

# Variáveis
TEST_REPORT="reports/functionality-test-$(date +%Y%m%d-%H%M%S).txt"
PASSED=0
FAILED=0

# Função para registrar resultado
test_result() {
    local test_name=$1
    local result=$2
    local message=$3
    
    if [ "$result" -eq 0 ]; then
        echo -e "${GREEN}${NC} $test_name: $message" | tee -a "$TEST_REPORT"
        ((PASSED++))
    else
        echo -e "${RED}${NC} $test_name: $message" | tee -a "$TEST_REPORT"
        ((FAILED++))
    fi
}

# Inicializar relatório
echo "Teste de Funcionalidade - $(date)" > "$TEST_REPORT"
echo "========================================" >> "$TEST_REPORT"
echo "" >> "$TEST_REPORT"

# Obter IP da VM
VM_IP=$(terraform -chdir=terraform output -raw test_vm_ip)
SSH_KEY="$HOME/.ssh/terraform-vms"

echo "Testando VM em $VM_IP..."

# Teste 1: Conectividade SSH
echo -e "${YELLOW}[1/8]${NC} Testando conectividade SSH..."
if ssh -i "$SSH_KEY" -o ConnectTimeout=5 -o StrictHostKeyChecking=no debian@"$VM_IP" "echo 'SSH OK'" &> /dev/null; then
    test_result "SSH Connectivity" 0 "Conectado com sucesso"
else
    test_result "SSH Connectivity" 1 "Falha na conexão SSH"
    exit 1
fi

# Teste 2: Verificar Debian
echo -e "${YELLOW}[2/8]${NC} Verificando versão do Debian..."
DEBIAN_VERSION=$(ssh -i "$SSH_KEY" debian@"$VM_IP" "cat /etc/os-release | grep VERSION_ID | cut -d= -f2 | tr -d '\"'")
if [ ! -z "$DEBIAN_VERSION" ]; then
    test_result "Debian Version" 0 "Debian $DEBIAN_VERSION detectado"
else
    test_result "Debian Version" 1 "Não foi possível detectar versão"
fi

# Teste 3: Verificar pacotes essenciais
echo -e "${YELLOW}[3/8]${NC} Verificando pacotes essenciais..."
PACKAGES=("curl" "wget" "git" "vim" "htop")
for pkg in "${PACKAGES[@]}"; do
    if ssh -i "$SSH_KEY" debian@"$VM_IP" "which $pkg" &> /dev/null; then
        test_result "Package: $pkg" 0 "Instalado"
    else
        test_result "Package: $pkg" 1 "Não encontrado"
    fi
done

# Teste 4: Verificar espaço em disco
echo -e "${YELLOW}[4/8]${NC} Verificando espaço em disco..."
DISK_USAGE=$(ssh -i "$SSH_KEY" debian@"$VM_IP" "df -h / | tail -1 | awk '{print $5}' | tr -d '%'")
if [ "$DISK_USAGE" -lt 80 ]; then
    test_result "Disk Space" 0 "Uso: ${DISK_USAGE}%"
else
    test_result "Disk Space" 1 "Uso crítico: ${DISK_USAGE}%"
fi

# Teste 5: Verificar memória
echo -e "${YELLOW}[5/8]${NC} Verificando memória..."
MEMORY=$(ssh -i "$SSH_KEY" debian@"$VM_IP" "free -h | grep Mem | awk '{print $2}'")
test_result "Memory" 0 "Total: $MEMORY"

# Teste 6: Verificar CPUs
echo -e "${YELLOW}[6/8]${NC} Verificando CPUs..."
CPUS=$(ssh -i "$SSH_KEY" debian@"$VM_IP" "nproc")
test_result "CPUs" 0 "Total: $CPUS"

# Teste 7: Verificar hostname
echo -e "${YELLOW}[7/8]${NC} Verificando hostname..."
HOSTNAME=$(ssh -i "$SSH_KEY" debian@"$VM_IP" "hostname")
if [ "$HOSTNAME" = "test-debian12" ]; then
    test_result "Hostname" 0 "Correto: $HOSTNAME"
else
    test_result "Hostname" 1 "Incorreto: $HOSTNAME"
fi

# Teste 8: Verificar conectividade de rede
echo -e "${YELLOW}[8/8]${NC} Verificando conectividade de rede..."
if ssh -i "$SSH_KEY" debian@"$VM_IP" "ping -c 1 8.8.8.8" &> /dev/null; then
    test_result "Network Connectivity" 0 "Conectado à internet"
else
    test_result "Network Connectivity" 1 "Sem conectividade"
fi

# Resumo
echo "" >> "$TEST_REPORT"
echo "========================================" >> "$TEST_REPORT"
echo "Resumo: $PASSED passaram, $FAILED falharam" >> "$TEST_REPORT"
echo "========================================" >> "$TEST_REPORT"

echo ""
echo -e "${GREEN}Testes de funcionalidade concluídos!${NC}"
echo "Relatório: $TEST_REPORT"

exit $FAILED
EOF

# Tornar executável
$ chmod +x ~/workspace-as-code/tests/image-validation/scripts/test-functionality.sh

# Verifique
$ ls -la ~/workspace-as-code/tests/image-validation/scripts/

Passo 2: Teste de Segurança

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
$ cat > ~/workspace-as-code/tests/image-validation/scripts/test-security.sh << 'EOF'
#!/bin/bash
set -e

# Cores para output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

# Variáveis
TEST_REPORT="reports/security-test-$(date +%Y%m%d-%H%M%S).txt"
PASSED=0
FAILED=0

# Função para registrar resultado
test_result() {
    local test_name=$1
    local result=$2
    local message=$3
    
    if [ "$result" -eq 0 ]; then
        echo -e "${GREEN}${NC} $test_name: $message" | tee -a "$TEST_REPORT"
        ((PASSED++))
    else
        echo -e "${RED}${NC} $test_name: $message" | tee -a "$TEST_REPORT"
        ((FAILED++))
    fi
}

# Inicializar relatório
echo "Teste de Segurança - $(date)" > "$TEST_REPORT"
echo "========================================" >> "$TEST_REPORT"
echo "" >> "$TEST_REPORT"

# Obter IP da VM
VM_IP=$(terraform -chdir=terraform output -raw test_vm_ip)
SSH_KEY="$HOME/.ssh/terraform-vms"

echo "Testando segurança da VM em $VM_IP..."

# Teste 1: Verificar atualizações disponíveis
echo -e "${YELLOW}[1/6]${NC} Verificando atualizações de segurança..."
UPDATES=$(ssh -i "$SSH_KEY" debian@"$VM_IP" "sudo apt list --upgradable 2>/dev/null | wc -l")
if [ "$UPDATES" -le 5 ]; then
    test_result "Security Updates" 0 "$UPDATES atualizações disponíveis"
else
    test_result "Security Updates" 1 "$UPDATES atualizações pendentes"
fi

# Teste 2: Verificar SSH hardening
echo -e "${YELLOW}[2/6]${NC} Verificando SSH hardening..."
SSH_CONFIG=$(ssh -i "$SSH_KEY" debian@"$VM_IP" "grep '^PermitRootLogin' /etc/ssh/sshd_config || echo 'not found'")
if [[ "$SSH_CONFIG" == *"no"* ]]; then
    test_result "SSH Root Login" 0 "Desabilitado"
else
    test_result "SSH Root Login" 1 "Habilitado (risco de segurança)"
fi

# Teste 3: Verificar permissões de arquivo
echo -e "${YELLOW}[3/6]${NC} Verificando permissões de arquivo..."
SUDOERS_PERMS=$(ssh -i "$SSH_KEY" debian@"$VM_IP" "stat -c '%a' /etc/sudoers")
if [ "$SUDOERS_PERMS" = "440" ]; then
    test_result "Sudoers Permissions" 0 "Correto: $SUDOERS_PERMS"
else
    test_result "Sudoers Permissions" 1 "Incorreto: $SUDOERS_PERMS"
fi

# Teste 4: Verificar firewall
echo -e "${YELLOW}[4/6]${NC} Verificando firewall..."
if ssh -i "$SSH_KEY" debian@"$VM_IP" "sudo ufw status" &> /dev/null; then
    test_result "Firewall" 0 "UFW disponível"
else
    test_result "Firewall" 1 "UFW não disponível"
fi

# Teste 5: Verificar fail2ban
echo -e "${YELLOW}[5/6]${NC} Verificando fail2ban..."
if ssh -i "$SSH_KEY" debian@"$VM_IP" "which fail2ban-client" &> /dev/null; then
    test_result "Fail2ban" 0 "Instalado"
else
    test_result "Fail2ban" 1 "Não instalado"
fi

# Teste 6: Verificar logs
echo -e "${YELLOW}[6/6]${NC} Verificando logs de segurança..."
LOGS=$(ssh -i "$SSH_KEY" debian@"$VM_IP" "sudo tail -5 /var/log/auth.log | wc -l")
if [ "$LOGS" -gt 0 ]; then
    test_result "Security Logs" 0 "Logs disponíveis"
else
    test_result "Security Logs" 1 "Sem logs"
fi

# Resumo
echo "" >> "$TEST_REPORT"
echo "========================================" >> "$TEST_REPORT"
echo "Resumo: $PASSED passaram, $FAILED falharam" >> "$TEST_REPORT"
echo "========================================" >> "$TEST_REPORT"

echo ""
echo -e "${GREEN}Testes de segurança concluídos!${NC}"
echo "Relatório: $TEST_REPORT"

exit $FAILED
EOF

# Tornar executável
$ chmod +x ~/workspace-as-code/tests/image-validation/scripts/test-security.sh

Passo 3: Script Principal de Testes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
$ cat > ~/workspace-as-code/tests/image-validation/scripts/run-all-tests.sh << 'EOF'
#!/bin/bash
set -e

# Cores para output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}Suite de Testes de Validação de Imagens${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""

# Passo 1: Provisionar VM de teste
echo -e "${YELLOW}[1/4] Provisionando máquina virtual de teste...${NC}"
cd terraform
terraform init
terraform validate
terraform plan
terraform apply -auto-approve
cd ..

# Aguardar VM estar pronta
echo -e "${YELLOW}Aguardando VM ficar pronta...${NC}"
sleep 30

# Passo 2: Executar testes de funcionalidade
echo ""
echo -e "${YELLOW}[2/4] Executando testes de funcionalidade...${NC}"
./scripts/test-functionality.sh

# Passo 3: Executar testes de segurança
echo ""
echo -e "${YELLOW}[3/4] Executando testes de segurança...${NC}"
./scripts/test-security.sh

# Passo 4: Limpar recursos
echo ""
echo -e "${YELLOW}[4/4] Limpando recursos...${NC}"
cd terraform
terraform destroy -auto-approve
cd ..

echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}Suite de testes concluída com sucesso!${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
echo "Relatórios disponíveis em: reports/"
ls -lh reports/
EOF

# Tornar executável
$ chmod +x ~/workspace-as-code/tests/image-validation/scripts/run-all-tests.sh

Executando Testes

Passo 1: Preparar Ambiente

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Navegue para o diretório de testes
$ cd ~/workspace-as-code/tests/image-validation

# Verifique estrutura
$ tree .

# Você deve ver:
# .
# ├── terraform/
# │   ├── main.tf
# │   ├── variables.tf
# │   └── outputs.tf
# ├── scripts/
# │   ├── test-functionality.sh
# │   ├── test-security.sh
# │   └── run-all-tests.sh
# ├── cloud-init.yml
# └── reports/

Passo 2: Validar Terraform

1
2
3
4
5
6
7
8
9
10
# Valide a configuração Terraform
$ cd terraform
$ terraform init
$ terraform validate
$ terraform fmt

# Você deve ver:
# Success! The configuration is valid.

$ cd ..

Passo 3: Executar Testes Manualmente (Opcional)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Se preferir executar passo a passo:

# 1. Provisionar VM
$ cd terraform
$ terraform apply -auto-approve
$ cd ..

# 2. Aguardar VM estar pronta
$ sleep 30

# 3. Executar testes
$ ./scripts/test-functionality.sh
$ ./scripts/test-security.sh

# 4. Destruir VM
$ cd terraform
$ terraform destroy -auto-approve
$ cd ..

Passo 4: Executar Suite Completa

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Execute a suite completa de testes
$ ./scripts/run-all-tests.sh

# Você verá progresso como:
# ========================================
# Suite de Testes de Validação de Imagens
# ========================================
# 
# [1/4] Provisionando máquina virtual de teste...
# [2/4] Executando testes de funcionalidade...
# [3/4] Executando testes de segurança...
# [4/4] Limpando recursos...
# 
# ========================================
# Suite de testes concluída com sucesso!
# ========================================

Analisando Resultados

Passo 1: Verificar Relatórios

1
2
3
4
5
6
# Liste os relatórios gerados
$ ls -lh reports/

# Você deve ver:
# -rw-r--r-- functionality-test-20260228-120000.txt
# -rw-r--r-- security-test-20260228-120015.txt

Passo 2: Examinar Relatório de Funcionalidade

1
2
3
4
5
6
7
8
9
10
11
12
13
# Veja o relatório de funcionalidade
$ cat reports/functionality-test-*.txt

# Você deve ver:
# Teste de Funcionalidade - Fri Feb 28 12:00:00 UTC 2026
# ========================================
# ✓ SSH Connectivity: Conectado com sucesso
# ✓ Debian Version: Debian 12 detectado
# ✓ Package: curl: Instalado
# ...
# ========================================
# Resumo: 8 passaram, 0 falharam
# ========================================

Passo 3: Examinar Relatório de Segurança

1
2
3
4
5
6
7
8
9
10
11
12
13
# Veja o relatório de segurança
$ cat reports/security-test-*.txt

# Você deve ver:
# Teste de Segurança - Fri Feb 28 12:00:15 UTC 2026
# ========================================
# ✓ Security Updates: 3 atualizações disponíveis
# ✓ SSH Root Login: Desabilitado
# ✓ Sudoers Permissions: Correto: 440
# ...
# ========================================
# Resumo: 6 passaram, 0 falharam
# ========================================

Exemplos Práticos

Exemplo 1: Adicionar Teste Customizado

1
2
3
4
5
6
7
8
9
10
11
12
13
# Crie um novo teste
$ cat > ~/workspace-as-code/tests/image-validation/scripts/test-custom.sh << 'EOF'
#!/bin/bash

VM_IP=$(terraform -chdir=terraform output -raw test_vm_ip)
SSH_KEY="$HOME/.ssh/terraform-vms"

# Seu teste customizado aqui
ssh -i "$SSH_KEY" debian@"$VM_IP" "your-command-here"
EOF

# Tornar executável
$ chmod +x ~/workspace-as-code/tests/image-validation/scripts/test-custom.sh

Exemplo 2: Testar Múltiplas Imagens

1
2
3
4
5
6
7
8
9
10
# Crie um loop para testar múltiplas imagens
for image in debian12-packer debian12-custom; do
    echo "Testando $image..."
    terraform -chdir=terraform apply -auto-approve \
      -var "image_path=/home/ubuntu/workspace-as-code/kvm/templates/$image.qcow2"
    
    ./scripts/test-functionality.sh
    
    terraform -chdir=terraform destroy -auto-approve
done

Exemplo 3: Integrar com CI/CD

1
2
3
4
5
6
7
8
9
# Adicione ao seu pipeline CI/CD (ex: GitLab CI)
test_image:
  stage: test
  script:
    - cd tests/image-validation
    - ./scripts/run-all-tests.sh
  artifacts:
    paths:
      - tests/image-validation/reports/

Tabela de Testes

TesteTipoDescriçãoEsperado
SSH ConnectivityFuncionalidadeConectar via SSHSucesso
Debian VersionFuncionalidadeVerificar versãoDebian 12
PacotesFuncionalidadeVerificar instalaçãoTodos presentes
Espaço em DiscoFuncionalidadeVerificar uso< 80%
MemóriaFuncionalidadeVerificar disponível> 0
CPUsFuncionalidadeVerificar quantidadeCorreto
HostnameFuncionalidadeVerificar nometest-debian12
RedeFuncionalidadeConectividadeOK
AtualizaçõesSegurançaVerificar patchesMínimas
SSH HardeningSegurançaRoot loginDesabilitado
PermissõesSegurançaSudoers440
FirewallSegurançaUFWDisponível
Fail2banSegurançaProteçãoInstalado
LogsSegurançaAuth logsPresentes

Troubleshooting

Erro: “SSH connection timeout”

Problema: Não consegue conectar via SSH.

Solução:

1
2
3
4
5
# Aguarde mais tempo
$ sleep 60

# Ou verifique se a VM está rodando
$ virsh list

Erro: “Terraform not found”

Problema: Terraform não está no PATH.

Solução:

1
2
3
4
5
# Instale Terraform
$ sudo apt install -y terraform

# Ou use caminho completo
$ /usr/bin/terraform --version

Testes falhando

Problema: Testes estão falhando.

Solução:

1
2
3
4
5
# Verifique os logs da VM
$ ssh -i ~/.ssh/terraform-vms debian@<ip> "sudo tail -50 /var/log/syslog"

# Ou execute teste manualmente
$ ssh -i ~/.ssh/terraform-vms debian@<ip> "curl --version"

VM não inicia

Problema: VM não consegue iniciar.

Solução:

1
2
3
4
5
# Verifique se há espaço em disco
$ df -h ~/workspace-as-code/kvm/

# Ou verifique logs do LIBVIRT
$ sudo tail -50 /var/log/libvirt/libvirtd.log

Dicas e Boas Práticas

Dica 1: Use Variáveis para Reutilização

1
2
3
4
# Defina variáveis comuns
TEST_ID=$(date +%s)
VM_IP=$(terraform -chdir=terraform output -raw test_vm_ip)
SSH_KEY="$HOME/.ssh/terraform-vms"

Dica 2: Organize Relatórios por Data

1
2
# Use timestamp em nomes
REPORT="reports/test-$(date +%Y%m%d-%H%M%S).txt"

Dica 3: Use Cores para Melhor Legibilidade

1
2
3
4
5
6
7
# Defina cores
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'

# Use em outputs
echo -e "${GREEN}Sucesso!${NC}"

Dica 4: Documente Testes

1
2
3
# Adicione comentários explicativos
# Teste 1: Verificar conectividade SSH
# Este teste valida se a VM está acessível via SSH

Dica 5: Versione Testes

1
2
3
# Adicione ao Git
$ git add tests/
$ git commit -m "feat: add comprehensive test suite"

Integrando com workspace-as-code

Passo 1: Organizar Estrutura

1
2
3
4
5
6
7
8
9
10
# Verifique a estrutura
$ tree ~/workspace-as-code/tests/

# Você deve ver:
# ~/workspace-as-code/tests/
# └── image-validation/
#     ├── terraform/
#     ├── scripts/
#     ├── cloud-init.yml
#     └── reports/

Passo 2: Criar .gitignore

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Crie arquivo .gitignore
$ cat > ~/workspace-as-code/tests/.gitignore << 'EOF'
# Terraform
terraform/.terraform/
terraform/.terraform.lock.hcl
terraform/terraform.tfstate*

# Reports
reports/*
!reports/.gitkeep

# Logs
*.log
EOF

# Verifique
$ cat ~/workspace-as-code/tests/.gitignore

Passo 3: Versionar no Git

1
2
3
4
5
6
7
8
# Adicione ao Git
$ cd ~/workspace-as-code
$ git add tests/
$ git commit -m "feat: add image validation test suite"
$ git push origin main

# Verifique
$ git log --oneline | head -5

Script de Validação

Para verificar se tudo foi configurado corretamente:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/bin/bash
# Script de validação de testes

echo "Validando estrutura de testes..."

# Verificar diretórios
if [ -d "terraform" ] && [ -d "scripts" ] && [ -d "reports" ]; then
    echo "✓ Diretórios criados"
else
    echo "✗ Diretórios não encontrados"
    exit 1
fi

# Verificar arquivos Terraform
if [ -f "terraform/main.tf" ] && [ -f "terraform/variables.tf" ]; then
    echo "✓ Arquivos Terraform existem"
else
    echo "✗ Arquivos Terraform não encontrados"
    exit 1
fi

# Verificar scripts de teste
if [ -f "scripts/test-functionality.sh" ] && [ -f "scripts/test-security.sh" ]; then
    echo "✓ Scripts de teste existem"
else
    echo "✗ Scripts de teste não encontrados"
    exit 1
fi

# Validar Terraform
if terraform -chdir=terraform validate &> /dev/null; then
    echo "✓ Configuração Terraform válida"
else
    echo "✗ Configuração Terraform inválida"
    exit 1
fi

echo ""
echo "Validação concluída com sucesso!"

Conclusão

Você aprendeu a criar um framework de testes para validar imagens antes de usar em produção. Com testes automatizados, você pode garantir qualidade, consistência e confiabilidade em seu ambiente de infraestrutura.

O Que Você Alcançou

✓ Entendimento da importância de testes em infraestrutura ✓ Criação de estrutura de testes ✓ Uso de Terraform para provisionar VMs de teste ✓ Desenvolvimento de scripts de teste automatizados ✓ Execução de testes de funcionalidade e segurança ✓ Geração de relatórios de validação ✓ Integração com workspace-as-code

Próximos Passos Imediatos

  1. Verifique pré-requisitos:
    1
    2
    
    $ systemctl is-active libvirtd
    $ terraform --version
    
  2. Crie estrutura:
    1
    2
    
    $ mkdir -p ~/workspace-as-code/tests/image-validation/{terraform,scripts,reports}
    $ cd ~/workspace-as-code/tests/image-validation
    
  3. Configure Terraform:
    1
    2
    
    $ terraform -chdir=terraform init
    $ terraform -chdir=terraform validate
    
  4. Execute testes:
    1
    
    $ ./scripts/run-all-tests.sh
    
  5. Verifique relatórios:
    1
    2
    
    $ cat reports/functionality-test-*.txt
    $ cat reports/security-test-*.txt
    
  6. Versione no Git:
    1
    2
    3
    4
    
    $ cd ~/workspace-as-code
    $ git add tests/
    $ git commit -m "feat: add image validation test suite"
    $ git push origin main
    

Próximo Tutorial

Com imagens testadas e validadas, o próximo passo é aprender a provisionar máquinas virtuais com configurações específicas usando Ansible, um orquestrador de configuração poderoso.


Recursos Adicionais


Fim da Parte 9

Próxima: Provisionamento com Ansible e Docker

This post is licensed under CC BY 4.0 by the author.