No ecossistema Linux voltado para DevOps, a gestão e validação de pacotes RPM são pilares fundamentais para a resiliência do sistema. Alterações em componentes, sejam elas atualizações de segurança ou novas funcionalidades, carregam riscos intrínsecos de quebra de dependências e conflitos de configuração. Este guia detalha metodologias avançadas para implementar um pipeline de testes de pacotes RPM robusto e escalável.
1. Estruturação do Ambiente de Validação
Para garantir a repetibilidade dos testes, é necessário estabelecer uma infraestrutura padronizada que suporte múltiplas arquiteturas e versões de sistema operacional.
# Configuração de diretórios e permissões para o laboratório
sudo useradd -m -s /bin/bash lab_tester
sudo mkdir -p /var/rpm_lab/{pkgs,logs,reports,staging}
sudo chown -R lab_tester:lab_tester /var/rpm_lab
# Instalação do kit de ferramentas essenciais
sudo dnf install -y createrepo_c mock rpm-build dnf-utils podman virt-install
Matriz de Compatibilidade Sugerida
| Dimensão | Alvos Comuns | Foco do Teste |
|---|---|---|
| OS Distribuição | RHEL 8/9, Rocky Linux, Fedora | APIs do sistema e fluxos DNF |
| Arquitetura | x86_64, aarch64 | Compilação binária e performence |
| Runtime Python | 3.6, 3.9, 3.11 | Scripts de pós-instalação e hooks |
2. Testes em Ambientes Virtualizados
A virtualização permite testar o ciclo de vida do pacote em um ambiente que simula fielmente a produção, incluindo a pilha de rede e o gerenciamento de serviços via Systemd.
#!/bin/bash
# deploy_test_node.sh - Provisionamento automatizado de VM para teste
NODE_ID="rpm-val-$(date +%s)"
OS_IMAGE="/var/lib/libvirt/images/rhel-9-latest.qcow2"
# Criação da instância de teste
virt-install \
--name "${NODE_ID}" \
--memory 2048 \
--vcpus 2 \
--disk size=15,format=qcow2 \
--import \
--os-variant rhel9.0 \
--network network=default \
--graphics none \
--noautoconsole
# Injeção de repositório temporário via SSH
cat <<EOF > ./staging.repo
[internal-staging]
name=Staging RPM Repository
baseurl=http://repo-server.local/repo/staging/
enabled=1
gpgcheck=0
EOF
scp ./staging.repo root@${NODE_ID}:/etc/yum.repos.d/
Gestão de Repositórios Dinâmicos
Utilizar um servidor Nginx para expor os pacotes recém-construídos permite que as instâncias de teste consumam as atualizações via gerenciadores de pacotes padrão.
# Script de sincronização do repositório
REPO_ROOT="/var/www/html/repo"
STAGING_DIR="${REPO_ROOT}/staging"
# Organização por build ID
mkdir -p "${STAGING_DIR}/$(date +%Y%m%d)"
mv /tmp/*.rpm "${STAGING_DIR}/$(date +%Y%m%d)/"
# Regeneração dos metadados
createrepo_c --update "${STAGING_DIR}/$(date +%Y%m%d)/"
ln -sfn "${STAGING_DIR}/$(date +%Y%m%d)" "${REPO_ROOT}/latest"
3. Isolamento com Chroot e DNF Installroot
Para testes rápidos de dependência sem o overhead de uma VM, o recurso --installroot do DNF é extrmeamente eficaz para criar sandboxes isoladas.
#!/bin/bash
# validate_rpm_isolation.sh
CHROOT_PATH="/tmp/rpm_sandbox_$(date +%s)"
TARGET_PKG="app-service-2.5.0.rpm"
mkdir -p "${CHROOT_PATH}"
# Inicialização de um ambiente minimalista
dnf --installroot="${CHROOT_PATH}" --releasever=9 \
--setopt=install_weak_deps=false -y install bash coreutils
# Verificação de Scripts de Pré/Pós Instalação
echo "--- Analisando Scripts do Pacote ---"
rpm -qp --scripts "${TARGET_PKG}"
# Teste de Instalação no Chroot
dnf --installroot="${CHROOT_PATH}" install -y "${TARGET_PKG}" | tee sandbox_install.log
# Verificação de integridade dos arquivos instalados
rpm --root "${CHROOT_PATH}" -V "$(rpm -qp --qf '%{NAME}' ${TARGET_PKG})"
4. Pipelines de Teste em Containers
O uso de containers agiliza os testes de fumaça (smoke tests) e a integração contínua, permitindo a execução paralela em diversas distribuições.
# Dockerfile para validação de pacotes
FROM fedora:38
RUN dnf install -y dnf-plugins-core rpmdevtools && dnf clean all
WORKDIR /val
COPY . /val/
# Script de entrada para execução dos testes
ENTRYPOINT ["/bin/bash", "-c", "dnf install -y ./testing/*.rpm && /val/run_smoke_tests.sh"]
Para fluxos complexos, o podman-compose pode ser utilizado para orquestrar o pacote sob teste junto com suas dependências de infraestrutura, como bancos de dados.
# compose-validation.yml
services:
app-under-test:
image: rpm-validator:latest
volumes:
- ./rpms:/val/testing:ro
depends_on:
- mock-db
mock-db:
image: postgres:14-alpine
environment:
- POSTGRES_PASSWORD=test_pass
5. Cenários de Teste de Regressão e Performance
Além da instalação, é crucial validar se a atualização a partir de versões anteriores mantém a entegridade dos dados e configurações.
#!/usr/bin/env python3
# rpm_perf_analyzer.py
import subprocess
import time
import json
def measure_package_impact(package_path):
metrics = {}
# Início do monitoramento de tempo
start_time = time.time()
try:
subprocess.run(["dnf", "install", "-y", package_path],
check=True, capture_output=True)
metrics['install_duration'] = time.time() - start_time
# Coleta de métricas de ocupação de disco
du_output = subprocess.check_output(["du", "-sh", "/usr/local/app"],
text=True)
metrics['disk_usage'] = du_output.split()[0]
except subprocess.CalledProcessError as e:
metrics['error'] = str(e.stderr)
return metrics
if __name__ == "__main__":
result = measure_package_impact("./build/output.rpm")
print(json.dumps(result, indent=2))
6. Integração com Servidores de CI (Jenkins/GitLab)
Um estágio de teste RPM em um Jenkinsfile deve abranger desde a lintagem do arquivo SPEC até a validação funcional em múltiplos nós.
pipeline {
agent any
stages {
stage('Análise Estática') {
steps {
sh 'rpmlint build/SPECS/*.spec'
}
}
stage('Build Mock') {
steps {
sh 'mock -r fedora-38-x86_64 --rebuild build/SRPMS/*.src.rpm'
}
}
stage('Validação em Container') {
steps {
sh 'podman build -t test-runner -f Dockerfile.test .'
sh 'podman run --rm test-runner'
}
}
}
post {
always {
archiveArtifacts artifacts: 'build/RPMS/**/*.rpm'
}
}
}
7. Checkpoint de Qualidade
- Scripts %pre e %post: Garantir que falhas nestes scripts não deixem o banco de dados RPM em estado inconsistente.
- Atributos %config: Validar o uso de
(noreplace)para evitar a perda de customizações do usuário durante upgrades. - SELinux: Verificar se os arquivos instalados possuem os contextos de segurança corretos para evitar bloqueios de serviço.
- Limpeza: Confirmar que o
dnf removeremove todos os arquivos criados, exceto os dados de usuário explicitamente protegidos.