← RHCE in Ansible: automação e operação
23 / 23 · 85 MIN

Contratos de dados e validação antes da alteração

Valida tipos, estrutura, cardinalidade e condições antes de consumir dados de automação.

Definir o contrato antes de transformar

Num caso fictício de APS, um formulário entrega parâmetros para preparar o batch de pagamentos. feature_enabled decide se a tarefa pode executar; retries indica um inteiro permitido; cada serviço tem uma porta autorizada. Começa por escrever os tipos, limites e associações exigidos. O laboratório fornece feature_enabled=false e retries=3 como pares key=value: ambos chegam como strings. Com um objeto JSON que contém false e 3 sem aspas, as asserções reconhecem booleano e inteiro. A aparência no formulário não é evidência do tipo recebido pelo play. Usa testes de tipo para os contratos e type_debug para diagnóstico quando necessário. Uma conversão deve ser deliberada e seguir uma política de entradas aceites. O texto 3x convertido com int devolveu zero no ensaio. Se zero significa não repetir, uma tentativa de corrigir o tipo pode esconder uma alteração operacional importante.

Separar ausência, vazio, zero e null

O ensaio compara quatro entradas. Uma variável ausente recebe 30 através de default(30). Uma string vazia continua vazia com o mesmo filtro. Zero continua zero, mas default(30,true) substitui-o por 30. Um null definido passa por mandatory e continua null. Estes resultados não decidem a política do serviço: tens de a definir. Para pause_seconds, zero pode ser um valor válido que não deve desaparecer. Para service_name, null e vazio podem ser erros a rejeitar antes de qualquer alteração. No laboratório, a asserção de string não vazia falha e a tarefa seguinte, marcada APPLY_SENTINEL, não é executada. O lookup de uma variável de ambiente ausente devolve vazio, que também não é corrigido pelo default normal. Só usa fallback para vazio quando isso corresponde ao requisito. Documenta as diferenças na entrega a RUN para que um override não altere silenciosamente o significado de zero.

Compor objetos com uma política de listas explícita

A base tem limits={timeout:30,retries:2}; o patch tem limits={timeout:45}. Uma composição simples substitui o objeto limits e perde retries. A composição recursiva observada conserva retries=2 e aplica timeout=45. No entanto, recursão não define a política de listas. Com ports=[8080,8080] na base e [9090] no patch, a opção recursiva por si só produz [9090]. Ao usar append_rp, o resultado é [8080,8080,9090]: os duplicados exclusivos da base continuam presentes. Se o consumidor exige portas únicas, valida essa regra de forma independente. Decide também se um duplicado é erro ou se pode ser normalizado; a remoção automática pode ocultar duas definições concorrentes. Compara sempre o objeto efetivo com o contrato do consumidor, incluindo chaves irmãs que não foram alteradas pelo pedido. A intenção de mudar apenas timeout não basta para provar que retries foi preservado.

Preservar identidade e cardinalidade

Três nomes e duas portas produzem apenas dois pares com zip. O laboratório acrescenta uma asserção de comprimento e rejeita os dados antes da transformação. Mesmo com comprimentos iguais, verifica as associações: ordenar nomes e portas de forma independente não prova que cada serviço recebeu a porta aprovada. Uma lista de registos com nome e porta juntos torna essa relação explícita. Outra experiência converte duas entradas com a mesma chave batch em dicionário; apenas o último valor permanece. Verifica unicidade antes dessa perda de informação, se o contrato proíbe duplicados. Finalmente, a seleção de port igual ao inteiro 8080 inclui batch_a e exclui batch_b quando a segunda porta é a string "8080". Normaliza tipos antes de selecionar, segundo a política de entrada, e conserva evidência das rejeições. Um filtro executado sem erro pode produzir um conjunto incompleto.

Controlar nomes e estrutura à entrada

O objeto record contém uma chave items. No ensaio, record.items refere-se a um método, mas record["items"] devolve os nomes guardados. Prefere acesso explícito por chave quando um nome pode colidir com atributos do dicionário. O carregamento de variáveis também pode criar colisões: timeout=30 para uma sonda é substituído por 75 quando include_vars carrega um ficheiro no topo. Com name:application, timeout mantém 30 e application.timeout contém 75. Isso permite escolher o dado de cada consumidor sem depender da ordem para distinguir conceitos. Para resultados externos, separa duas verificações: sintaxe e estrutura. O texto {not-json} falha ao interpretar; o texto JSON 17 é válido mas produz um escalar. A asserção de mapping rejeita esse resultado antes de o consumidor tentar ler service e port. Acrescenta depois validações das chaves, tipos, limites e relações exigidos pelo serviço.

Ensaiar a migração das condições

O mesmo exercício foi executado duas vezes em core 2.16.14 e duas em core 2.19.0, versões fixadas para comparar o comportamento, sem afirmar que são o patch mais recente. Com feature_enabled igual à string "false", when:feature_enabled executa a tarefa na 2.16.14 e falha com exigência de resultado booleano na 2.19.0. Com when: feature_enabled | bool, esta entrada reconhecida produz false e a tarefa é ignorada nas duas versões. Isso não autoriza aceitar texto arbitrário: define os valores permitidos ou exige um booleano na entrada. O guia de migração é uma referência para outros pontos a rever; o ensaio não certifica compatibilidade de todo um projeto. Antes de uma atualização do controlador, identifica as condições relevantes e testa também exemplos negativos. Não atives compatibilidade antiga apenas para transformar uma falha visível numa execução que viola o requisito.

Exercício guiado e critérios de entrega

Prevê os resultados antes de abrir commands.json. Para cada experiência, escreve a entrada, o tipo esperado, a transformação e o critério de aceitação. Executa o runner numa pasta nova e compara as previsões: cada execução faz 14 invocações; as versões 2.16.14 e 2.19.0 passam respetivamente 31 e 32 verificações. A verificação adicional da versão mais recente confirma a mensagem que exige um booleano. As tarefas são executadas no controlador com dados sintéticos, sem módulos remotos, credenciais ou serviços RHEL. Para praticar uma entrega realista, define o contrato de três serviços e prepara entradas inválidas: um nome vazio, uma porta textual inesperada e uma chave duplicada. Explica onde cada entrada deve ser rejeitada e que tarefa deixa de executar. Resume a evidência para RUN e relaciona-a com inventários, contratos de roles e validação de templates. A aceitação funcional do serviço continua a exigir outro ensaio.

ENTRADAS SINTÉTICAS
false em key=value -> string
false em JSON -> booleano
0 | default(30) -> 0
0 | default(30,true) -> 30
null | mandatory -> null
3 nomes zip 2 portas -> 2 pares
when: feature_enabled | bool -> false para a string reconhecida "false"
NA PRÁTICA

Um batch recebe feature_enabled="false", nomes e portas com comprimentos diferentes e uma configuração com uma chave duplicada. Identifica os gates que devem impedir a execução.

Armadilhas comuns

Tratar zero como ausência; aceitar null com mandatory; perder entradas em zip ou items2dict; assumir unicidade com append_rp; usar strings como autorização implícita.

Tópicos relacionados: Inventários e configuração · Contratos de roles · Validação de templates

Leva esta ideia contigo

Transformar dados sem erro não prova que o contrato foi cumprido: valida tipos, conteúdo e relações antes de alterar sistemas.

Criar conta

Referência: Assert input contracts · EX294 current objectives inspected 2026-09-30; RHCE in Ansible framework effective 2026-05-11; booking product version not publicly pinned

Red Hat®, RHCE e Ansible são marcas comerciais ou marcas registadas de Red Hat, Inc. A dr.pt é uma plataforma de preparação independente e não está afiliada, associada, patrocinada, autorizada nem aprovada por Red Hat. Os conteúdos e as perguntas são originais, não são perguntas oficiais de exame, e concluir os nossos testes não atribui nem garante qualquer certificação. Os nomes são usados apenas para identificar o tema. Todas as outras marcas pertencem aos respetivos titulares.