ANSIBLE SERIES: h.t.wrt* … tasks, plays e books: conditionals
CONT. ☝
👈 ANTERIOR: WHERE TASKS RUN ?
Condicionais, em bom português, são aquelas famosas palavrinhas que aprendemos (lógica da programação) com o intuito de:
- parar momentaneamente o fluxo do programa;
- desviar a sequência ou conteúdo de variável para um bloco de código que faz checagem;
- chamar uma função ou sub-rotina;
- capturar exceções e tratá-las;
- exibir informações ou mensagens ao usuário;
- dentre outras tarefas.
Pois bem, alguns exemplos dessas palavras que normalmente usamos para tais propósitos: SE, SENÃO, ENTÃO, ENQUANTO, PARA, E, OU, NÃO (!not) …
No casos dos playbooks, nossos objetivos vão desde: (a) executar diferentes tasks que dependem do valor de um fato (dado de um host remoto), variável ou resultado anterior (b) atribuir valor a uma variável baseando-se em outra variável precedente (c) definir e criar novos grupos de hosts em cima de alguns critérios de correspondência.
Uma pequena ressalva da documentação oficial:
Ansible usa testes e filtros
https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html#playbooks-conditionalsJinja2
em condicionais. O Ansible oferece suporte a todos os testes e filtros padrão e também adiciona alguns exclusivos
E uma pequena nota de rodapé:
Existem muitas opções para controlar o fluxo de execução no Ansible. Você pode encontrar mais exemplos de condicionais com suporte em https://jinja.palletsprojects.com/en/master/templates/#comparisons
https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html#playbooks-conditionals
Devido ao sumário de tamanho “razoável” que esta seção apresenta na wiki oficial, tentarei ao máximo fazer breves explanações dos códigos e talvez pule algumas delas, seja porque são muito raras de utilizar ou porque fogem muito dos nossos objetivos, ok?

04-a. Condicionais básicas com WHEN
A unidade mais básica para uma condicional, chamada por alguns de “declaração mais simples”, é essencialmente aplicada a uma única tarefa por vez. Na prática, isso quer dizer que, quando se cria uma tarefa, seguida de uma declaração when
, um teste será executado. Essa cláusula when
na verdade é uma expressão Jinja2
bruta e sem chaves duplas. Quando se roda uma task ou playbook o que acontece é que o Ansible valida esse teste para todos os hosts remotos. Se qualquer um deles “passar na prova”, o valor retornado é true
, e então a task é executada. Para ilustrar, um exemplo:
tasks: - name: Configure SELinux to start mysql on any port ansible.posix.seboolean: name: mysql_connect_any state: true persistent: yeswhen:
ansible_selinux.status
=="enabled"
# all variables can be used directly in conditionals without double curly braces
! ! ! BASEADAS EM ANSIBLE_FACTS ! ! !
Às vezes, ao invés de executar tarefas, simplesmente queremos o oposto. Em outras palavras, desejamos pulá-las e passar adiante. Isso pode ser feito através dos fatos, ou melhor, por meio dos atributos (dados) de um node específico. IP, SO, filesystem, status, são apenas alguns para citar.
Com as condicionais baseadas em fatos, é possível:
- instalar pacotes somente para determinadas versões ou famílias de um sistema operacional
- pular configurações de firewall para hosts internos à rede
- fazer uma limpeza em sistemas de arquivos muito cheios
Veja quais fatos estão disponíveis em cada host, acrescentando uma simples tarefa do tipo debug:
- name: Show facts available on the systemansible.builtin.debug:
var:ansible_facts
Exemplo 1 x 1: uma condicional para um fato
tasks: - name: Shut down Debian flavored systems ansible.builtin.command: /sbin/shutdown -t nowwhen:
ansible_facts['os_family'
] =="Debian"
Exemplo N x N: múltiplas condicionais para múltiplos fatos
tasks: - name: Shut down CentOS 6 and Debian 7 systems ansible.builtin.command: /sbin/shutdown -t nowwhen:
(ansible_facts['distribution'
] =="CentOS"
and ansible_facts['distribution_major_version'
] =="6"
) or (ansible_facts['distribution'
] =="Debian"
and ansible_facts['distribution_major_version'
] =="7"
)
Outra forma, um pouco mais abreviada:
tasks: - name: Shut down CentOS 6 systems ansible.builtin.command: /sbin/shutdown -t nowwhen:
- ansible_facts['distribution'
] =="CentOS"
- ansible_facts['distribution_major_version'
] =="6"
https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html#commonly-used-facts
! ! ! BASEADAS EM VARIÁVEIS ! ! !
Você também pode criar condicionais com base em variáveis definidas nos playbooks ou inventários. Como as condicionais requerem entrada booleana (um teste deve ser avaliado como True para acionar a condição), você deve aplicar o
https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html#conditionals-based-on-variables|
Filtro booleano
para variáveis não booleanas, como variáveis de string com conteúdo como‘sim’
,‘ativado’
,‘1’
ou‘verdadeiro’
.
Defina suas variáveis exatamente assim:
vars:
epic: true
monumental: "yes"
Agora execute o código a seguir:
tasks: - name: Run the command if "epic" or "monumental" is true ansible.builtin.shell: echo "This certainly is epic!"when:
epic
or
monumental
|
bool
- name: Run the command if "epic" is false ansible.builtin.shell: echo "This certainly isn't epic!"when:
not
epic
Verá que o Ansible roda uma delas e pula a outra!
! ! ! BASEADAS EM LOOPS ! ! !
Processa a condição separadamente para cada item presente no laço. Isso ocorre para que você possa executar a tarefa em alguns elementos e ignorá-la em outros. Por exemplo:
tasks: - name: Run with items greater than 5 ansible.builtin.command: echo {{ item }} loop: [ 0, 2, 4, 6, 8, 10 ] when: item > 5
Sobre uma lista:
- name: Skip the whole task when a loop variable is undefined ansible.builtin.command: echo {{ item }} loop: "{{ mylist|default([]) }}" when: item > 5
Sobre um dicionário:
- name: The same as above using a dict ansible.builtin.command: echo {{ item.key }} loop: "{{ query('dict', mydict|default({})) }}" when: item.value > 5