ANSIBLE SERIES: h.t.wrt* … tasks, plays e books: blocks
UPDATE! / DISCLAIMER: Depois de muitas idas e vindas ao banco … buscas e mais buscas à procura de documentos pessoais que não via há tanto tempo … cópias, xerox, pdf’s, assinaturas … e por fim, infinitas caixas/pacotes para organizar, mofo/poeira para limpar, caminhão da mudança, lavar o piso novo, desempacotar e remontar 😫😓 (…) Estou vivo, de volta e escrevendo da minha própria casa, cujo foi comprada em JUN/2021, também conhecido como ‘mês passado’. Esse foi o real motivo para o BLOG ter ficado tão parado nessas últimas semanas, caros e estimados leitores. Sendo assim, peço desculpas a todos! Espero que não fiquem chateados comigo 😥 MAS, é como dizem por aí: o show não pode parar! Então, retomando do ponto exato aonde paramos, a seguir, +1 capítulo da série ANSIBLE:
CONT. 🔝
🔙 ANTERIOR: CONDITIONALS
Analogamente (ou equivalente, se preferir) a um grupo de linhas dentro do código-fonte, blocos no contexto ‘ansible’ são formas/maneiras de lidar/tratar dois tipos de elemento básico: (a) tasks e (b) erros! Na prática, blocos acabam criando grupos lógicos, sejam micro tarefas que partilham determinado objetivo maior, sejam erros advindos de uma tarefa mal executada, displicentemente planejada. Em ambos os casos, podemos fazer um paralelo com o tratamento de exceções, observadas em outras linguagens de programação.
- Agrupando tasks com blocos;
- Tratando erros com blocos;
05-a. Agrupando tasks com blocos
A herança de dados, diretivas, ocorre e se aplica a todas as tarefas comuns (aninhadas) em um mesmo nível de bloco. Ou seja, a diretiva propriamente dita não afeta o bloco em si, mas sim as tasks delimitadas (contidas) por ele. Para exemplificar: uma vez validada e satisfeita a condição imposta pelo when
, aplica-se a mesma numa única tacada para as diversas tarefas presentes no bloco em questão. O que é bem diferente de aplicar a ele mesmo, como pode ser levado a crer, e assim, induzido ao erro. A única exceção aqui são os loops. Esteja sempre atento!
tasks: - name: Install, configure, and start Apacheblock:
- name: Install httpd and memcached ansible.builtin.yum: name: - httpd - memcached state: present - name: Apply the foo config template ansible.builtin.template: src: templates/src.j2 dest: /etc/foo.conf - name: Start service bar and enable it ansible.builtin.service: name: bar state: started enabled: True
when:
ansible_facts['distribution']
=='CentOS'
become: true become_user: root ignore_errors: yes
Resumidamente: a condição é avaliada ANTES e TODA VEZ que “alcançamos” um host diferente. Se passar, aí sim serão executadas as três tarefas informadas no bloco, para aquele node específico (e aprovado). O escalonamento e privilégio de root também são herdados, e por tabela, executados na sequência. Por fim, a última linha ignore_errors: yes
serve apenas para que o Ansible dê continuidade ao playbook em casos de falhas nas tasks.
**Names for blocks have been available since Ansible 2.3. We recommend using names in all tasks, within blocks or elsewhere, for better visibility into the tasks being executed when you run the playbook.
05-b. Tratando erros com blocos
Trechos do código identificados como blocos, e marcados com as palavras rescue
e always
, são chamados (igualmente definidos) de sessões. Elas são peças-chave, fundamentais para controlar as respostas direcionadas a possíveis erros de tarefa.
Blocos rescue
ditam novas tasks a serem executadas quando uma task anterior (do mesmo bloco) falhar. Tal abordagem é muito parecida com o tratamento de exceções presente em diversas outras linguagens de programação. É importante frisar aqui a seguinte informação: o Ansible somente executa blocos de resgate após uma tarefa retornar estado de FALHA (failed). Tasks definidas incorretamente ou hosts inacessíveis não irão disparar/acionar nenhum bloco de resgate.
tasks: - name: Handle the errorblock:
- name: Print a message ansible.builtin.debug: msg: 'I execute normally' - name: Force a failure ansible.builtin.command: /bin/false - name: Never print this ansible.builtin.debug: msg: 'I never execute, due to the above task failing, :-('rescue:
- name: Print when errors ansible.builtin.debug: msg: 'I caught an error, can do stuff here to fix it, :-)'
Dentro de um bloco também podem haver sessões always. A partir desse ponto, tarefas serão executadas independentemente do status anterior, ou seja, da task anterior.
- name: Always do Xblock:
- name: Print a message ansible.builtin.debug: msg: 'I execute normally' - name: Force a failure ansible.builtin.command: /bin/false - name: Never print this ansible.builtin.debug: msg: 'I never execute :-('always:
- name: Always do this ansible.builtin.debug: msg: "This always executes, :-)"
Misturados, esses dois fornecem um belo tratamento para erros um pouco mais complexos.
- name: Attempt and graceful roll back demoblock:
- name: Print a message ansible.builtin.debug: msg: 'I execute normally' - name: Force a failure ansible.builtin.command: /bin/false - name: Never print this ansible.builtin.debug: msg: 'I never execute, due to the above task failing, :-('rescue:
- name: Print when errors ansible.builtin.debug: msg: 'I caught an error' - name: Force a failure in middle of recovery! >:-) ansible.builtin.command: /bin/false - name: Never print this ansible.builtin.debug: msg: 'I also never execute :-('always:
- name: Always do this ansible.builtin.debug: msg: "This always executes"
As tarefas do bloco são executadas normalmente. Se alguma tarefa no bloco retornar failed
, a seção de resgate executa tarefas para se recuperar do erro. A seção always
é executada independentemente dos resultados das seções block
e rescue
.
Se ocorrer um erro no bloco e a tarefa de resgate for bem-sucedida, o Ansible reverterá o status de falha da tarefa original para a execução e continuará a executar a reprodução como se a tarefa original tivesse sido bem-sucedida. A tarefa resgatada é considerada bem-sucedida e não aciona configurações max_fail_percentage
ou any_errors_fatal
. No entanto, Ansible ainda relata uma falha nas estatísticas do playbook.
Use blocos com flush_handlers
em uma tarefa de resgate para garantir que todos os manipuladores sejam executados mesmo se ocorrer um erro:
tasks: - name: Attempt and graceful roll back demoblock:
- name: Print a message ansible.builtin.debug: msg: 'I execute normally' changed_when: yes notify: run me even after an error - name: Force a failure ansible.builtin.command: /bin/falserescue:
- name: Make sure all handlers run meta: flush_handlershandlers:
- name: Run me even after an error ansible.builtin.debug: msg: 'This handler runs even on error'
**New in version 2.1
**Ansible provides a couple of variables for tasks in the rescue
portion of a block:
ansible_failed_task
The task that returned ‘failed’ and triggered the rescue. For example, to get the name use ansible_failed_task.name
.
ansible_failed_result
The captured return result of the failed task that triggered the rescue. This would equate to having used this var in the register
keyword.
REFERÊNCIAS:
https://docs.ansible.com/ansible/latest/user_guide/playbooks_blocks.html#playbooks-blocks