Atualize os dois cardápios

AnsibleBeginner
Pratique Agora

Introdução

A Juniper & Oat precisa dos mesmos preços aprovados de bebidas em dois cafés, sem perder a identidade, os horários ou o especial de cada filial. Você usará um modelo e um playbook do Ansible para atualizar dois alvos reais gerenciados por SSH e depois corrigirá um desvio intencional no cardápio.

Você precisa saber navegar no terminal e já ter praticado a leitura de um pequeno inventário e playbook do Ansible. Variáveis de host, renderização JSON, prévia segura e a diferença entre conteúdo gerenciado e local são explicados durante o uso. As ferramentas e os sites preparados permitem concentrar-se na automação em vez da instalação.

Separe preços compartilhados dos detalhes das filiais

Nesta etapa, você identificará o que os dois cafés compartilham e o que deve continuar diferente, depois declarará os dados aprovados para um único modelo reutilizável.

A Juniper & Oat tem dois cafés de bairro. Ambos usam as mesmas bebidas e preços cotidianos; cada um tem seus horários, especial e aviso local. Sua tarefa é atualizar o cardápio compartilhado sem substituir esses detalhes locais. Os hosts preparados web1 e web2 são dois contêineres gerenciados por SSH que compartilham o kernel da VM de treinamento, e não VMs separadas. O Controller executa o Ansible; cada alvo executa seu próprio serviço real de cardápio.

Abra Menu Preview, selecione First branch e leia o cardápio, os horários e o especial. Use o botão Voltar do navegador para retornar à lista de filiais e selecione Second branch. Ambos mostram o preço antigo do Flat white; Park Café também mostra horários incorretos. O especial e o aviso local de cada página já estão corretos. Visit abre as informações de visita da mesma filial; Download menu baixa seu CSV real atual. Esses são links de página, não abas do LabEx.

Mude para a aba Controller. O terminal começa no diretório do projeto; este comando explícito também permite voltar após um erro de diretório:

cd /home/labex/project

Os nomes web1 e web2 no inventário apontam para alvos SSH preparados distintos. Veja o inventário e as entradas aprovadas das filiais com cat, que lê arquivos sem alterá-los:

cat inventory.ini
cat host_vars/web1.yml host_vars/web2.yml

Harbor Café deve abrir das 07:00–16:00; Park Café, das 08:00–18:00. O diretório host_vars fornece variáveis ao host de inventário correspondente. Não altere essas entradas nem as configurações SSH preparadas. Essa diferença é intencional, não um erro a eliminar.

O cardápio compartilhado aprovado é fornecido como dado do cenário. Leia-o antes de escrever as variáveis:

cat approved-menu.json

Ele lista Espresso a 3.20, Flat white a 4.20 e Tea a 3.00. Um preço é armazenado como string entre aspas para preservar as duas casas decimais na formatação. menu_items será uma lista YAML de objetos nome/preço compartilhada pelos dois hosts.

Os diretórios preparados group_vars e templates estão vazios. Um arquivo chamado group_vars/all.yml fornece variáveis a todos os hosts do inventário. O próximo here-document escreve um arquivo completo: > substitui exatamente esse destino, e o delimitador YAML entre aspas impede a expansão do conteúdo pelo shell. O delimitador de fechamento deve aparecer sozinho no início de uma linha. Se digitar o conteúdo incorretamente, execute o bloco inteiro novamente; ele substitui apenas seu arquivo de variáveis.

cat > group_vars/all.yml <<'YAML'
menu_items:
  - name: Espresso
    price: "3.20"
  - name: Flat white
    price: "4.20"
  - name: Tea
    price: "3.00"
YAML

Um modelo Jinja insere valores resolvidos em um arquivo gerenciado. Chaves duplas avaliam uma expressão; a barra vertical aplica um filtro. Aqui, to_nice_json serializa o objeto inteiro como JSON válido e legível, incluindo caracteres não ASCII. Isso evita colocar aspas manualmente em cada valor inserido. É o mesmo modelo para as duas filiais: branch_name e opening_hours vêm das respectivas entradas dos hosts, enquanto menu_items é compartilhado.

cat > templates/menu.json.j2 <<'JINJA'
{{ {'branch': branch_name, 'hours': opening_hours, 'items': menu_items} | to_nice_json }}
JINJA

Leia as duas fontes criadas para detectar aspas ausentes, recuo incorreto ou problemas no delimitador antes de executar o Ansible:

cat group_vars/all.yml templates/menu.json.j2

O site ainda não mudou. Você declarou os dados desejados, mas não os aplicou. Na próxima etapa, o Ansible renderizará essa fonte no contexto de variáveis de cada host.

Aplique um playbook aos dois cafés

Nesta etapa, você visualizará e implantará a mesma declaração nos dois alvos SSH reais e depois usará seus cardápios e downloads reais.

Permaneça em Controller, em /home/labex/project. Um play seleciona os hosts; as tarefas declaram o estado gerenciado. become: true solicita a elevação de privilégios autorizada do alvo preparado para que os arquivos pertençam a root. Isso não altera a conta de login do LabEx. O módulo file declara o diretório; o módulo template renderiza a fonte compartilhada e substitui apenas menu.json. A propriedade explícita e as permissões entre aspas tornam previsíveis o acesso ao diretório e a leitura pública do cardápio: 0755 para o diretório, 0644 para o cardápio.

Os arquivos locais local-special.txt, local-notice.txt e o privado staff-notes.txt estão fora da declaração do cardápio gerenciado. Não substitua o conteúdo do diretório nem modifique esses arquivos. Preserve os bytes, a propriedade de root e as permissões originais: 0644 para o especial/aviso e 0600 para as notas privadas. O serviço lê menu.json em cada requisição; portanto, uma atualização apenas de dados não precisa de reinício artificial nem handler.

Escreva um playbook completo. Itens de lista YAML usam -, e espaços aninham os argumentos de cada módulo. Os caminhos em src referem-se às fontes no controlador; dest fica em cada alvo gerenciado.

cat > menus.yml <<'YAML'
- name: Keep both branch menus current
  hosts: all
  gather_facts: false
  become: true
  tasks:
    - name: Keep the menu directory available
      ansible.builtin.file:
        path: /srv/branch-menu
        state: directory
        owner: root
        group: root
        mode: "0755"

    - name: Render the shared menu with each branch's inputs
      ansible.builtin.template:
        src: templates/menu.json.j2
        dest: /srv/branch-menu/menu.json
        owner: root
        group: root
        mode: "0644"
YAML

Primeiro, use --syntax-check para validar a sintaxe do playbook sem aplicá-lo:

ansible-playbook menus.yml --syntax-check

Se houver erro YAML, leia o arquivo e a linha indicados. Compare o recuo com o bloco completo acima, reescreva esse bloco e repita a verificação. Erros de sintaxe do Ansible não exigem reiniciar a VM.

--check prevê alterações dos módulos compatíveis; --diff mostra o conteúdo proposto antes/depois. Isso é útil para estes arquivos de cardápio sem segredos, mas uma prévia não é um teste real de funcionamento. Execute as duas opções juntas:

ansible-playbook menus.yml --check --diff

Ambos os hosts devem prever uma alteração no cardápio. O diff deve corrigir os preços e os horários de Park Café, preservando identidades distintas. Nenhum arquivo dos alvos foi alterado. Mude para Menu Preview, abra ou atualize as filiais e confirme que os valores antigos continuam visíveis. Volte a Controller para aplicar a mesma declaração sem as opções de prévia:

ansible-playbook menus.yml

O resumo de cada host não deve mostrar tarefas com falha nem alvos inacessíveis. Os números exatos de changed podem diferir porque cada host precisava de correções diferentes. Leia os dados reais gerenciados com um comando ad hoc: all seleciona os dois hosts do inventário, -m indica o módulo e -a passa seus argumentos. O módulo command executa cat em cada alvo, não no controlador.

ansible all -m ansible.builtin.command -a 'cat /srv/branch-menu/menu.json'

Ambos devem conter as bebidas e os preços cotidianos aprovados. Harbor Café e Park Café devem preservar seus nomes e horários distintos.

Agora mude para Menu Preview e atualize cada filial. Leia os três preços, o nome, os horários, o especial e o aviso local. Abra Visit e retorne por Menu. Selecione Download menu e abra o CSV: ele deve conter os três itens aprovados dessa filial, com o nome dela em cada linha. Apenas ver uma página inicial funcionando não basta.

Harbor Café mostra os preços compartilhados aprovados junto de seus próprios horários e especial local.

Compare os preços compartilhados à esquerda com o especial local à direita. Park Café mantém seus horários e especial ao usar a mesma lista aprovada de bebidas.

Se o navegador mostrar erro de cardápio ausente/inválido, volte ao Controller, leia a saída do comando e compare seu modelo JSON com a etapa 1. Corrija a fonte no controlador e execute novamente o playbook. Se um alvo estiver inacessível, leia inventory.ini e compare com a saída original; não desative a verificação de confiança SSH nem altere contas da plataforma.

Volte a Controller. Uma repetição sem mudanças não deve ter alterações pendentes:

ansible-playbook menus.yml

Procure as duas linhas do resumo:

web1 ... changed=0 ... unreachable=0 ... failed=0 ...
web2 ... changed=0 ... unreachable=0 ... failed=0 ...

Essa é uma configuração idempotente: os arquivos desejados já correspondem, então o Ansible não os reescreve. Isso não significa que requisições comuns ou registros do serviço deixam de ocorrer.

Corrija o desvio sem apagar conteúdo local

Nesta etapa, você danificará deliberadamente um valor gerenciado do cardápio e usará a fonte inalterada do controlador para restaurá-lo, preservando o conteúdo local.

Permaneça em Controller. Desvio de configuração significa que o estado real gerenciado já não corresponde à intenção declarada. Horários aprovados diferentes entre filiais não são desvio. Um preço compartilhado alterado manualmente é.

A ação seguinte é uma falha intencional restrita a web1. -b solicita become para essa tarefa ad hoc. O content de copy substitui exatamente o JSON do cardápio indicado, não seu diretório. A estrutura está correta, mas o preço de Espresso, 0.01, não é aprovado. Esse arquivo temporário está errado de propósito; não copie seu preço para group_vars.

ansible web1 -b -m ansible.builtin.copy -a 'dest=/srv/branch-menu/menu.json content={"branch":"Harbor Café","hours":"07:00–16:00","items":[{"name":"Espresso","price":"0.01"},{"name":"Flat white","price":"4.20"},{"name":"Tea","price":"3.00"}]} owner=root group=root mode=0644'

Mude para Menu Preview, atualize First branch e veja o preço errado de Espresso. A segunda filial e os dois especiais locais não devem ser afetados. Trata-se de uma alteração real no arquivo do alvo, não de uma luz vermelha simulada.

Volte a Controller. Não edite as fontes originais. Visualize o estado desejado existente:

ansible-playbook menus.yml --check --diff

Apenas web1 deve prever uma alteração. Web2 já corresponde ao estado aprovado. Aplique o mesmo playbook para restaurar o cardápio gerenciado:

ansible-playbook menus.yml

Mude para Menu Preview e atualize as duas filiais. Espresso deve voltar a custar 3.20. Os dois especiais, avisos, horários e downloads dos cardápios devem continuar corretos. Sua automação controla um arquivo de configuração; ela não controla todos os arquivos locais do diretório.

Volte a Controller e faça uma última repetição:

ansible-playbook menus.yml

Os dois resumos devem voltar a mostrar changed=0, unreachable=0 e failed=0. Uma correção bem-sucedida vem da intenção reutilizável nos dados do controlador e de um modelo compartilhado, não de corrigir o alvo manualmente uma vez. O mesmo modelo também deve continuar utilizável quando um item compartilhado aprovado mudar no futuro.

Resumo

Você separou preços compartilhados, entradas de cada filial e conteúdo local; visualizou e aplicou um modelo a dois alvos SSH; usou páginas reais e downloads CSV; e corrigiu um desvio real de configuração sem apagar diferenças legítimas entre filiais. A repetição sem mudanças confirmou a convergência dos cardápios declarados.