Introdução
Neste laboratório, você explorará duas funcionalidades poderosas do Ansible: condicionais e laços de repetição (loops). Esses conceitos permitem criar playbooks mais dinâmicos e eficientes, controlando a execução de tarefas com base em condições específicas e repetindo tarefas para vários itens. Ao final deste laboratório, você entenderá como usar condicionais para tomar decisões em seus playbooks e como implementar loops para executar tarefas repetitivas de forma eficiente. Esse conhecimento ajudará você a criar playbooks do Ansible mais flexíveis e potentes para gerenciar sua infraestrutura.
Configurando o Ambiente
Nesta etapa, você configurará o ambiente de trabalho para os exercícios de condicionais e loops do Ansible. Esta preparação fornece os arquivos e diretórios utilizados em todas as tarefas subsequentes.
Primeiro, vamos navegar até o diretório do projeto. No terminal, digite:
cd ~/project
Este comando altera seu diretório atual para ~/project, que é o 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 sobre os quais os 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 está 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 analisar o que isso significa:
[local]define um grupo chamado "local"localhosté o nome do hostansible_connection=localinstrui o Ansible a executar os comandos localmente em vez de via SSH
Para salvar o arquivo e sair do nano, pressione Ctrl+X, pressione Y para salvar o buffer modificado e, em seguida, pressione Enter para confirmar o nome do arquivo.
Em seguida, vamos criar um diretório para os nossos playbooks:
mkdir playbooks
cd playbooks
O comando mkdir cria um novo diretório chamado "playbooks", e então usamos cd para entrar nesse novo diretório.
Por que estamos fazendo isso? Organizar seus arquivos do Ansible em diretórios é uma boa prática. Isso mantém seu projeto organizado, especialmente à medida que ele cresce e se torna maior e mais complexo.
Seguindo esses passos, você configurou um ambiente básico do Ansible. Você tem um arquivo de inventário que diz ao Ansible quais hosts utilizar e um diretório dedicado para os seus playbooks. Essa estrutura facilitará o gerenciamento dos seus projetos Ansible à medida que você aprende e experimenta recursos mais complexos.
Introdução às Condicionais
Nesta etapa, você usará condicionais do Ansible para controlar a execução de tarefas com base em condições específicas. Isso é ú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, adicione o seguinte conteúdo:
---
- name: Conditional Example
hosts: localhost
gather_facts: yes
tasks:
- name: Check OS family
debug:
msg: "This is a Debian-based system"
when: ansible_os_family == "Debian"
- name: Check OS family (alternative)
debug:
msg: "This is not a Debian-based system"
when: ansible_os_family != "Debian"
Vamos analisar este código:
---no topo do arquivo indica o início de um documento YAML.name: Conditional Exampleatribui um nome ao nosso playbook.hosts: localhostespecifica que este playbook será executado na máquina local.gather_facts: yesinstrui o Ansible a coletar informações sobre o sistema antes de executar as tarefas. Isso é importante porque usaremos esses fatos em nossas condições.tasks:inicia a lista de tarefas a serem executadas.
Cada tarefa usa o módulo debug para exibir uma mensagem, mas a execução é controlada pela cláusula when:
- A primeira tarefa será executada apenas se o sistema for baseado em Debian (
ansible_os_family == "Debian"). - A segunda tarefa será executada apenas 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 as 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 instrui o Ansible a executar nosso playbook. A opção -i ../inventory.ini especifica o arquivo de inventário que criamos anteriormente.
Você deverá ver uma saída indicando se o seu sistema é baseado em Debian ou não. Apenas uma das mensagens de depuração será exibida, dependendo da família do sistema operacional do seu sistema.
Este exemplo demonstra como as condicionais podem ser usadas para tornar seus playbooks adaptáveis a diferentes ambientes. Em cenários do mundo real, você pode usar condicionais para instalar diferentes pacotes em diferentes tipos de SO, ou para ignorar certas tarefas se um arquivo já existir.
Lembre-se de que o poder das condicionais reside na 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
Nesta etapa, você combinará várias condições usando operadores lógicos antes de executar uma tarefa. Esse padrão dá suporte a um comportamento condicional mais avançado em playbooks do mundo real.
Crie um novo arquivo chamado multiple_conditions.yml:
nano multiple_conditions.yml
Agora, adicione o seguinte conteúdo ao arquivo:
---
- name: Multiple Conditions Example
hosts: localhost
gather_facts: yes
vars:
check_memory: true
tasks:
- name: Check OS and Memory
debug:
msg: "This is a Debian-based system with more than 1GB of memory"
when:
- ansible_os_family == "Debian"
- ansible_memtotal_mb > 1024
- check_memory | bool
- name: Print System Information
debug:
msg: "OS: {{ ansible_distribution }}, Memory: {{ ansible_memtotal_mb }} MB"
when: ansible_distribution == "Ubuntu" or ansible_memtotal_mb < 2048
Vamos analisar este playbook:
Definimos uma variável
check_memoryno nível do playbook. Ela poderia ser definida dinamicamente ou passada como uma variável extra ao executar o playbook.A primeira tarefa usa múltiplas condições:
- Ela verifica se a família do SO é Debian
- Ela verifica se a memória total é superior a 1024 MB (1 GB)
- Ela verifica se a variável
check_memoryé verdadeira
Todas essas condições devem ser verdadeiras para que a tarefa seja executada. O caractere
|emcheck_memory | boolé um filtro que converte o valor para booleano.A segunda tarefa demonstra o uso do operador
or. Ela será executada se a distribuição for Ubuntu OU se a memória total for inferior a 2048 MB (2 GB).Estamos usando mais fatos do Ansible aqui:
ansible_distributionfornece o nome específico da distribuição, eansible_memtotal_mbfornece 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ê poderá 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 com precisão quando suas tarefas devem ser executadas.
Introdução aos Loops
Nesta etapa, você usará loops do Ansible para repetir uma tarefa com valores diferentes. Isso é útil quando você precisa realizar a mesma ação com vários 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: Loop Example
hosts: localhost
vars:
fruits:
- apple
- banana
- cherry
tasks:
- name: Print fruit names
debug:
msg: "Current fruit: {{ item }}"
loop: "{{ fruits }}"
- name: Create directories
file:
path: "/tmp/{{ item }}"
state: directory
loop:
- dir1
- dir2
- dir3
Vamos analisar este código:
Definimos uma variável
fruitscomo uma lista de nomes de frutas.A primeira tarefa usa um loop para iterar sobre a lista
fruits. Para cada iteração, o valor atual fica disponível como{{ item }}.A segunda tarefa demonstra como usar um loop com o módulo
filepara criar múltiplos diretórios. Estamos criando três diretórios na pasta/tmp.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, verá que a primeira tarefa imprime o nome de cada fruta e a segunda tarefa cria três diretórios em /tmp.
Os 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
Nesta etapa, você usará técnicas avançadas de loop do Ansible para trabalhar com estruturas de dados complexas e controlar o processo de repetição.
Crie um novo arquivo chamado advanced_loops.yml:
nano advanced_loops.yml
Agora, adicione o seguinte conteúdo:
---
- name: Advanced Loop Techniques
hosts: localhost
vars:
users:
- name: alice
groups: ["developers", "testers"]
- name: bob
groups: ["managers", "developers"]
tasks:
- name: Create users with groups
debug:
msg: "Creating user {{ item.name }} with groups: {{ item.groups | join(', ') }}"
loop: "{{ users }}"
- name: Demonstrate loop_control
debug:
msg: "Processing item {{ index }} - {{ item }}"
loop: ["a", "b", "c", "d"]
loop_control:
index_var: index
- name: Loop over dictionary
debug:
msg: "{{ key }}: {{ value }}"
loop: "{{ {'x': 1, 'y': 2, 'z': 3} | dict2items }}"
vars:
key: "{{ item.key }}"
value: "{{ item.value }}"
Vamos analisar estas técnicas avançadas:
Fazendo loop sobre uma lista de dicionários: A primeira tarefa percorre 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).Usando o
loop_control: A segunda tarefa demonstra oloop_control, que nos permite alterar o nome da variável de loop (o padrão éitem) e acessar o índice atual do loop. Aqui, usamosindex_var: indexpara criar uma variávelindexque acompanha o número da iteração atual.Fazendo loop sobre um dicionário: A última tarefa mostra como percorrer um dicionário. Usamos o filtro
dict2itemspara converter o dicionário em uma lista de pares chave-valor que podem ser iterados. Em seguida, usamositem.keyeitem.valuepara 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, verá como essas técnicas avançadas de loop funcionam. A saída mostrará:
- Mensagens de criação de usuários com seus respectivos grupos
- Itens sendo processados juntamente com seus índices
- Pares de chave-valor extraídos do dicionário
Essas técnicas avançadas permitem trabalhar com estruturas de dados mais complexas e oferecem um controle mais refinado sobre os seus loops. Elas são particularmente úteis ao lidar com dados aninhados, quando você precisa acompanhar o índice do loop ou quando trabalha com dicionários.
Resumo
Neste laboratório, você aprendeu sobre condicionais e loops no Ansible, duas funcionalidades poderosas que permitem criar playbooks mais dinâmicos e eficientes. Aqui estão os principais aprendizados:
- As condicionais (cláusula
when) permitem controlar 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. - Você pode combinar várias condições usando operadores lógicos como
andeorpara criar declarações condicionais mais complexas. - Os loops (palavra-chave
loop) permitem repetir tarefas com valores diferentes, aumentando a eficiência e reduzindo a complexidade do playbook. - O Ansible oferece suporte a vários tipos de loops, incluindo iteração sobre listas, dicionários e estruturas de dados mais complexas.
- Técnicas avançadas de loop, como
loop_controle a iteração sobre dicionários, proporcionam ainda mais flexibilidade no tratamento de tarefas repetitivas.
Esses recursos são essenciais para criar playbooks do Ansible flexíveis e potentes, capazes de se adaptar a diferentes cenários e gerenciar eficientemente múltiplos itens. À medida que você continuar trabalhando com Ansible, pratique incorporar condicionais e loops em seus playbooks para torná-los mais dinâmicos e eficientes.
Lembre-se de sempre considerar a legibilidade e a manutenibilidade dos seus playbooks ao usar esses recursos. Embora eles possam simplificar muito o seu código, o uso excessivo ou condições e loops excessivamente complexos podem dificultar a compreensão e a manutenção dos playbooks.


