ANSIBLE SERIES: h.t.wrt* … ROLES
Se pudéssemos sintetizar o que é uma ROLE? num brevíssimo punhado de palavras, estes seriam excelentes candidatos:
Basicamente são a automação em torno das diretivas include, possuindo algumas melhorias quanto ao seu processamento, com o intuito de localizar mais rápido arquivos referenciados.
RED HAT, https://aap2.demoredhat.com/exercises/ansible_rhel/1.7-role/README.pt-br.html
Em teoria, uma estrutura pré-definida na forma de árvore de diretórios … Na prática, um mecanismo para reduzir a complexidade de escrever playbooks inteiros e transformá-la na simplicidade de pequenos e múltiplos arquivos: fáceis de elaborar, fáceis de reutilizar.
THETIPS4YOU, https://www.youtube.com/watch?v=DpdTT4d3U1I
Trata-se de um conceito para trabalhar as coisas como se fossem ideias e não eventos. Isso quer dizer que aos invés de enxergá-los como mera casualidade ou acasos infortúnios, os mesmos serão abstraídos e elevados a um novo patamar, maior e melhor otimizado para lidar com playbooks e outros artefatos.
EDUREKA!, https://www.youtube.com/watch?v=Or6k2UcKeN4
Eu sei, eu sei 😓 Consigo imaginar o que está pensando (…) Ainda assim complicado demais para fazer qualquer sentido? 🤕 Tudo bem, não estamos aqui para julgar ninguém. Do contrário, queremos ajudar uns aos outros … Correto? 😊 Bom, então segue a minha contribuição:
Uma ROLE nada mais é do que um esqueleto de pastas e arquivos organizados de tal maneira que faça sentido seu uso, reuso, e existência independente uns dos outros. Portanto, conclui-se que uma ROLE não é, e nunca será, considerado um PLAYBOOK. Mas sim uma funcionalidade dentro do ANSIBLE passível de uso avulso/solo, contudo nunca ou jamais vista fora de playbooks, formando assim um semi paradoxo: “seres” independentes entre si mas confinados a pairar em uma eterna existência, quase limbo, aguardando sua hora chegar, o momento em que serão necessários e por isso chamados/acionados por um playbook qualquer.
Deixemos a filosofia para grandes nomes e pensadores, e passemos agora para os tópicos que quero abordar com vocês 😄 Ok?
>_ ROLE DIRECTORY
Toda role apresenta o que chamamos de estrutura de diretórios, sendo esta composta por oito principais pastas, e que obedece necessariamente tanto um padrão hierárquico quanto de nomenclatura bastante definidos. Para ser considerado minimamente válido, sempre devemos declarar ou incluir pelo menos um dos itens em cada role proposta, e que está sendo escrita naquele momento. A omissão dos demais também é permitida, desde que não haja prejuízo ou dano por falta desses elementos. Por exemplo:
# playbooks
site.yml
webservers.yml
fooservers.yml
roles/
common/
tasks/
handlers/
library/
files/
templates/
vars/
defaults/
meta/
webservers/
tasks/
defaults/
meta/
O comportamento padrão esperado é que o Ansible procure dentro da raiz (pasta) de uma ROLE um arquivo chamado main.yml
, ou ainda main.yaml
, ou até mesmo somente main
. Isso acontece porque o conteúdo dito “relevante” encontra-se justamente aí, ou seja, é nele que reside todas as chamadas para se trabalhar com variáveis, tarefas, modelos, manipuladores e demais arquivos que compõem uma determinada função (ROLE quando traduzido livremente)
Cada item em particular conta, desempenhando um papel único, sendo que muitas vezes ocorre de um depender do resultado do outro, formando assim uma complexa cadeia. A seguir, breves descrições de pastas e arquivos para melhor ilustrar:
tasks/main.yml
– a lista de tarefas que a ROLE executa.handlers/main.yml
– manipuladores que podem ser usados dentro ou fora da ROLE.library/my_module.py
– módulos que podem ser usados dentro da ROLE (consulte Embedding modules and plugins in roles para obter maiores detalhes).defaults/main.yml
– valores padrão para a ROLE (consulte Using Variables para informações). Essas variáveis têm a prioridade mais baixa de todas as variáveis disponíveis e podem ser facilmente substituídas por qualquer outra variável, incluindo variáveis de inventário.vars/main.yml
– outras variáveis de natureza sortida para a ROLE (consulte Using Variables para instruções).files/main.yml
– arquivos estáticos que a ROLE é capaz de implantar.templates/main.yml
– modelos dinâmicos que a ROLE é capaz de implantar.meta/main.yml
– metadados sobre a ROLE, incluindo dependências para instalação.
Você também pode adicionar outros arquivos YAML em alguns diretórios. Por exemplo, colocar tarefas específicas da plataforma em arquivos separados e consultá-las no arquivo tasks/main.yml
:
# roles/example/tasks/main.yml
- name: Install the correct web server for RHEL
import_tasks: redhat.yml
when: ansible_facts['os_family']|lower == 'redhat'
- name: Install the correct web server for Debian
import_tasks: debian.yml
when: ansible_facts['os_family']|lower == 'debian'
# roles/example/tasks/redhat.yml
- name: Install web server
ansible.builtin.yum:
name: "httpd"
state: present
# roles/example/tasks/debian.yml
- name: Install web server
ansible.builtin.apt:
name: "apache2"
state: present
As ROLES também podem incluir módulos e outros tipos de plugins em um diretório chamado library
. Para obter mais informações, consulte Embedding modules and plugins in roles.
>_ ARMAZENANDO E RESGATANDO ROLES
Tão logo devidamente escritas, a próxima etapa lógica seria salvá-las em algum lugar. E pensando nisso, o Ansible sempre irá percorrer uma ordem pré-estabelecida em busca dessas ROLES, constituída em sua maioria por locais, mapeamentos ou unidades de pasta. Sendo que deve ser respeitada a seguinte precedência:
Collections
, caso faça uso destas- Diretório
roles/
do arquivo playbook.yml - Roles_path
~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles
- Pasta local onde o arquivo encontra-se armazenado
Outra opção seria descrever o caminho completo para aquela ROLE:
---
- hosts: webservers
roles:
- role: '/path/to/my/roles/common'
>_ COMO USAR ROLES
Podemos utilizá-las em três níveis possíveis. São eles:
- uma jogada (play) com a opção
roles
: Este é o método clássico de usar roles em um playbook. - uma tarefa (task) com a opção
include_role
: Você pode reutilizar roles dinamicamente em qualquer lugar na seção de tarefas de um playbook usando include_role. - uma tarefa (task) com a opção
import_role
: Você pode reutilizar roles estaticamente em qualquer lugar na seção de tarefas de um playbook usando import_role.
À nível de play …
---
- hosts: webservers
roles:
- common
- webservers
À nível de task: reuso dinâmico …
---
- hosts: webservers
tasks:
- name: Print a message
ansible.builtin.debug:
msg: "this task runs before the example role"
- name: Include the example role
include_role:
name: example
- name: Print a message
ansible.builtin.debug:
msg: "this task runs after the example role"
À nível de task: reuso estático …
---
- hosts: webservers
tasks:
- name: Print a message
ansible.builtin.debug:
msg: "before we run our role"
- name: Import the example role
import_role:
name: example
- name: Print a message
ansible.builtin.debug:
msg: "after we ran our role"
>_ EXECUTANDO UMA ROLE MÚLTIPLAS VEZES NO PLAYBOOK
Mesmo que referenciada duas ou mais vezes dentro de um playbook, o Ansible executa qualquer ROLE somente uma única vez. Por exemplo:
---
- hosts: webservers
roles:
- foo
- bar
- foo
Para forçá-lo a rodar múltiplas execuções de uma mesma ROLE, existem dois caminhos possíveis: ou você transmite diferentes argumentos (parâmetros) para cada chamada, ou você usa a palavra-chave reservada allow_duplicates: true
No primeiro caso teríamos algo mais ou menos assim:
---
- hosts: webservers
roles:
- { role: foo, message: "first" }
- { role: foo, message: "second" }
Já o segundo seria parecido com esse:
# playbook.yml
---
- hosts: webservers
roles:
- foo
- foo
# roles/foo/meta/main.yml
---
allow_duplicates: true
>_ COMO USAR DEPENDÊNCIAS
As dependências nos permitem extrair automaticamente outras ROLES ao usar uma dada específica. O Ansible não as executa simplesmente porque você incluiu ou importou uma ROLE. Não é bem assim. Você deve usar primeiro a palavra-chave roles
se quiser que o mesmo execute dependências de função.
As dependências na verdade são consideradas pré-requisitos, e não exatamente dependências verdadeiras. As ROLES não têm um relacionamento pai/filho. O Ansible carrega todas as funções listadas, depois executa essas na forma de dependências e só então, em seguida, executa a ROLE que as trouxe. O objeto play é o pai de todas as funções, incluindo as que foram chamadas por uma lista de dependências.
As dependências de uma ROLE são armazenadas no arquivo meta/main.yml
no diretório da função. Esse arquivo deve conter uma lista de funções e parâmetros a serem inseridos antes da função especificada. Por exemplo:
# roles/myapp/meta/main.yml
---
dependencies:
- role: common
vars:
some_parameter: 3
- role: apache
vars:
apache_port: 80
- role: postgres
vars:
dbname: blarg
other_parameter: 12
>_ REFERÊNCIAS:
https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html
[…] que já sabemos como escrever nossas próprias roles (você pode conferir aqui e aqui), será que não existe um meio mais fácil de disponibilizá-las para outras pessoas? Sim! […]