Condicionais e Loops no Ansible

AnsibleBeginner
Pratique Agora

Introdução

Neste laboratório, você explorará duas funcionalidades poderosas do Ansible: condicionais e loops. Esses conceitos permitem que você crie playbooks mais dinâmicos e eficientes, controlando a execução de tarefas com base em condições específicas e repetindo tarefas para múltiplos itens. Ao final deste laboratório, você entenderá como usar condicionais para tomar decisões em seus playbooks e como implementar loops para realizar tarefas repetitivas de forma eficiente. Este conhecimento o ajudará a criar playbooks Ansible mais flexíveis e poderosos para gerenciar sua infraestrutura.

Este é um Lab Guiado, que fornece instruções passo a passo para ajudá-lo a aprender e praticar. Siga as instruções cuidadosamente para completar cada etapa e ganhar experiência prática. Dados históricos mostram que este é um laboratório de nível iniciante com uma taxa de conclusão de 93%. Recebeu uma taxa de avaliações positivas de 100% dos estudantes.

Configurando o Ambiente

Antes de mergulharmos em condicionais e loops do Ansible, vamos configurar nosso ambiente de trabalho. Esta etapa é crucial, pois prepara a base para todas as nossas tarefas subsequentes.

Primeiramente, vamos navegar para o diretório do projeto. No terminal, digite:

cd ~/project

Este comando altera seu diretório atual para ~/project, que é nosso espaço de trabalho designado para este laboratório.

Agora, criaremos um arquivo de inventário. No Ansible, um arquivo de inventário define os hosts e grupos de hosts nos quais comandos, módulos e tarefas em um playbook operam. Para este laboratório, usaremos um inventário simples que inclui apenas o localhost.

Crie um novo arquivo chamado inventory.ini:

nano inventory.ini

Este comando abre o editor de texto nano. Se você não estiver familiarizado com o nano, não se preocupe - é um editor de texto simples e fácil de usar. O cursor será posicionado no arquivo, pronto para você digitar.

Agora, vamos adicionar o seguinte conteúdo ao arquivo:

[local]
localhost ansible_connection=local

Vamos detalhar isso:

  • [local] define um grupo chamado "local"
  • localhost é o nome do host
  • ansible_connection=local diz ao Ansible para executar comandos localmente em vez de via SSH

Para salvar o arquivo e sair do nano:

  1. Pressione Ctrl + X
  2. Você será perguntado se deseja salvar o buffer modificado. Pressione Y para sim.
  3. Pressione Enter para confirmar o nome do arquivo.

Em seguida, vamos criar um diretório para nossos playbooks:

mkdir playbooks
cd playbooks

O comando mkdir cria um novo diretório chamado "playbooks", e então usamos cd para entrar neste novo diretório.

Por que estamos fazendo isso? Organizar seus arquivos Ansible em diretórios é uma prática recomendada. Ele mantém seu projeto organizado, especialmente à medida que ele cresce e se torna mais complexo.

Ao seguir estas etapas, você configurou um ambiente Ansible básico. Você tem um arquivo de inventário que diz ao Ansible com quais hosts trabalhar e um diretório dedicado para seus playbooks. Essa estrutura facilitará o gerenciamento de seus projetos Ansible à medida que você aprende e experimenta recursos mais complexos.

Introdução aos Condicionais

Os condicionais no Ansible permitem que você controle a execução de tarefas com base em certas condições. Isso é incrivelmente útil quando você precisa realizar ações diferentes dependendo do estado do seu sistema ou do valor de certas variáveis.

Vamos criar um playbook simples que demonstra o uso de condicionais:

nano conditional_example.yml

Este comando abre o editor de texto nano para criar um novo arquivo chamado conditional_example.yml. Agora, vamos adicionar o seguinte conteúdo:

---
- name: Exemplo Condicional
  hosts: localhost
  gather_facts: yes
  tasks:
    - name: Verificar família do SO
      debug:
        msg: "Este é um sistema baseado em Debian"
      when: ansible_os_family == "Debian"

    - name: Verificar família do SO (alternativo)
      debug:
        msg: "Este não é um sistema baseado em Debian"
      when: ansible_os_family != "Debian"

Vamos detalhar isso:

  1. --- no topo do arquivo indica o início de um documento YAML.
  2. name: Exemplo Condicional dá um nome ao nosso playbook.
  3. hosts: localhost especifica que este playbook será executado na máquina local.
  4. gather_facts: yes diz ao Ansible para coletar informações sobre o sistema antes de executar as tarefas. Isso é importante porque usaremos esses fatos em nossas condições.
  5. tasks: inicia a lista de tarefas a serem executadas.

Cada tarefa usa o módulo debug para imprimir uma mensagem, mas a execução é controlada pela cláusula when:

  • A primeira tarefa só será executada se o sistema for baseado em Debian (ansible_os_family == "Debian").
  • A segunda tarefa só será executada se o sistema não for baseado em Debian (ansible_os_family != "Debian").

ansible_os_family é um fato coletado pelo Ansible sobre o sistema de destino. Ele é usado aqui para demonstrar como os condicionais funcionam.

Salve e saia do editor nano (Ctrl+X, depois Y, depois Enter).

Agora, vamos executar o playbook:

ansible-playbook -i ../inventory.ini conditional_example.yml

Este comando diz ao Ansible para executar nosso playbook. A opção -i ../inventory.ini especifica o arquivo de inventário que criamos anteriormente.

Você deve ver a saída indicando se seu sistema é baseado em Debian ou não. Apenas uma das mensagens de depuração será exibida, dependendo da família do SO do seu sistema.

Este exemplo demonstra como os condicionais podem ser usados para tornar seus playbooks adaptáveis a diferentes ambientes. Em cenários do mundo real, você pode usar condicionais para instalar pacotes diferentes em diferentes tipos de SO ou para pular certas tarefas se um arquivo já existir.

Lembre-se, o poder dos condicionais reside em sua capacidade de tornar seus playbooks flexíveis e capazes de lidar com vários cenários sem a necessidade de playbooks separados para cada caso.

Trabalhando com Múltiplas Condições

Em cenários do mundo real, você frequentemente precisa verificar múltiplas condições antes de executar uma tarefa. O Ansible permite que você combine múltiplas condições usando operadores lógicos. Vamos criar outro playbook para demonstrar este uso mais avançado de condicionais.

Crie um novo arquivo chamado multiple_conditions.yml:

nano multiple_conditions.yml

Agora, vamos adicionar o seguinte conteúdo ao arquivo:

---
- name: Exemplo de Múltiplas Condições
  hosts: localhost
  gather_facts: yes
  vars:
    check_memory: true
  tasks:
    - name: Verificar SO e Memória
      debug:
        msg: "Este é um sistema baseado em Debian com mais de 1GB de memória"
      when:
        - ansible_os_family == "Debian"
        - ansible_memtotal_mb > 1024
        - check_memory | bool

    - name: Imprimir Informações do Sistema
      debug:
        msg: "SO: {{ ansible_distribution }}, Memória: {{ ansible_memtotal_mb }} MB"
      when: ansible_distribution == "Ubuntu" or ansible_memtotal_mb < 2048

Vamos detalhar este playbook:

  1. Definimos uma variável check_memory no nível do playbook. Isso pode ser definido dinamicamente ou passado como uma variável extra ao executar o playbook.

  2. A primeira tarefa usa múltiplas condições:

    • Verifica se a família do SO é Debian
    • Verifica se a memória total é maior que 1024 MB (1 GB)
    • Verifica se a variável check_memory é verdadeira

    Todas essas condições devem ser verdadeiras para que a tarefa seja executada. O | em check_memory | bool é um filtro que converte o valor em um booleano.

  3. A segunda tarefa demonstra o uso do operador or. Ela será executada se a distribuição for Ubuntu OU a memória total for menor que 2048 MB (2 GB).

  4. Estamos usando mais fatos do Ansible aqui: ansible_distribution fornece o nome específico da distribuição e ansible_memtotal_mb fornece a memória total do sistema em megabytes.

Salve e saia do editor nano.

Agora, vamos executar este playbook:

ansible-playbook -i ../inventory.ini multiple_conditions.yml

Observe a saída. Dependendo das características do seu sistema, você pode ver uma ou ambas as mensagens de depuração.

Este exemplo mostra como você pode criar condições complexas para tornar seus playbooks altamente adaptáveis a diferentes cenários. Você pode combinar vários fatos do sistema, variáveis personalizadas e operadores lógicos para ajustar quando suas tarefas devem ser executadas.

Introdução aos Loops

Loops no Ansible permitem que você repita uma tarefa várias vezes com valores diferentes. Isso é extremamente útil quando você precisa realizar a mesma ação com múltiplos itens, como criar vários usuários, instalar múltiplos pacotes ou criar vários diretórios.

Vamos criar um playbook para demonstrar o uso de loops. Crie um novo arquivo chamado loop_example.yml:

nano loop_example.yml

Agora, adicione o seguinte conteúdo:

---
- name: Exemplo de Loop
  hosts: localhost
  vars:
    fruits:
      - apple
      - banana
      - cherry
  tasks:
    - name: Imprimir nomes de frutas
      debug:
        msg: "Fruta atual: {{ item }}"
      loop: "{{ fruits }}"

    - name: Criar diretórios
      file:
        path: "/tmp/{{ item }}"
        state: directory
      loop:
        - dir1
        - dir2
        - dir3

Vamos detalhar isso:

  1. Definimos uma variável fruits como uma lista de nomes de frutas.

  2. A primeira tarefa usa um loop para iterar sobre a lista fruits. Para cada iteração, o valor atual está disponível como {{ item }}.

  3. A segunda tarefa demonstra como usar um loop com o módulo file para criar múltiplos diretórios. Estamos criando três diretórios na pasta /tmp.

  4. Observe que podemos usar o loop diretamente na tarefa (como na segunda tarefa) ou referenciar uma variável (como na primeira tarefa).

Salve e saia do editor nano.

Agora, vamos executar este playbook:

ansible-playbook -i ../inventory.ini loop_example.yml

Quando você executar este playbook, você verá que a primeira tarefa imprime cada nome de fruta e a segunda tarefa cria três diretórios em /tmp.

Loops são um recurso poderoso no Ansible que pode reduzir significativamente a quantidade de código repetitivo em seus playbooks. Eles são especialmente úteis ao trabalhar com listas de itens como usuários, pacotes ou arquivos.

Técnicas Avançadas de Loop

O Ansible fornece técnicas de loop mais avançadas que permitem que você trabalhe com estruturas de dados complexas e tenha mais controle sobre o processo de loop. Vamos explorar algumas dessas técnicas criando um novo playbook.

Crie um novo arquivo chamado advanced_loops.yml:

nano advanced_loops.yml

Agora, adicione o seguinte conteúdo:

---
- name: Técnicas Avançadas de Loop
  hosts: localhost
  vars:
    users:
      - name: alice
        groups: ["developers", "testers"]
      - name: bob
        groups: ["managers", "developers"]
  tasks:
    - name: Criar usuários com grupos
      debug:
        msg: "Criando usuário {{ item.name }} com grupos: {{ item.groups | join(', ') }}"
      loop: "{{ users }}"

    - name: Demonstrar loop_control
      debug:
        msg: "Processando item {{ index }} - {{ item }}"
      loop: ["a", "b", "c", "d"]
      loop_control:
        index_var: index

    - name: Loop sobre dicionário
      debug:
        msg: "{{ key }}: {{ value }}"
      loop: "{{ {'x': 1, 'y': 2, 'z': 3} | dict2items }}"
      vars:
        key: "{{ item.key }}"
        value: "{{ item.value }}"

Vamos detalhar essas técnicas avançadas:

  1. Loop sobre uma lista de dicionários:
    A primeira tarefa faz um loop sobre a lista users, onde cada item é um dicionário contendo um nome e uma lista de grupos. Podemos acessar esses elementos aninhados usando a notação de ponto (item.name, item.groups).

  2. Usando loop_control:
    A segunda tarefa demonstra loop_control, que nos permite alterar o nome da variável de loop (o padrão é item) e acessar o índice do loop atual. Aqui, usamos index_var: index para criar uma variável index que acompanha o número da iteração atual.

  3. Loop sobre um dicionário:
    A última tarefa mostra como fazer um loop sobre um dicionário. Usamos o filtro dict2items para converter o dicionário em uma lista de pares chave-valor que podem ser iterados. Em seguida, usamos item.key e item.value para acessar as chaves e os valores do dicionário.

Salve e saia do editor nano.

Agora, vamos executar este playbook:

ansible-playbook -i ../inventory.ini advanced_loops.yml

Quando você executar este playbook, você verá como essas técnicas avançadas de loop funcionam. A saída mostrará:

  • Mensagens de criação de usuário com seus respectivos grupos
  • Itens sendo processados com seus índices
  • Pares chave-valor do dicionário

Essas técnicas avançadas permitem que você trabalhe com estruturas de dados mais complexas e fornecem um controle mais preciso sobre seus loops. Elas são particularmente úteis ao lidar com dados aninhados, quando você precisa acompanhar o índice do loop ou ao trabalhar com dicionários.

Resumo

Neste laboratório, você aprendeu sobre condicionais e loops do Ansible, dois recursos poderosos que permitem criar playbooks mais dinâmicos e eficientes. Aqui estão os principais pontos:

  1. Condicionais (cláusula when) permitem que você controle a execução de tarefas com base em condições específicas, como fatos sobre o sistema de destino ou variáveis definidas pelo usuário.
  2. Você pode combinar múltiplas condições usando operadores lógicos como and e or para criar declarações condicionais mais complexas.
  3. Loops (palavra-chave loop) permitem que você repita tarefas com valores diferentes, aumentando a eficiência e reduzindo a complexidade do playbook.
  4. O Ansible suporta vários tipos de loop, incluindo loop sobre listas, dicionários e estruturas de dados mais complexas.
  5. Técnicas avançadas de loop, como loop_control e loop sobre dicionários, fornecem ainda mais flexibilidade no tratamento de tarefas repetitivas.

Esses recursos são essenciais para criar playbooks Ansible flexíveis e poderosos que podem se adaptar a diferentes cenários e gerenciar eficientemente múltiplos itens. Ao continuar trabalhando com o Ansible, pratique a incorporação de condicionais e loops em seus playbooks para torná-los mais dinâmicos e eficientes.

Lembre-se de sempre considerar a legibilidade e a capacidade de manutenção de seus playbooks ao usar esses recursos. Embora eles possam simplificar muito seu código, o uso excessivo ou condições e loops excessivamente complexos podem tornar os playbooks mais difíceis de entender e manter.