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:

  1. Collections, caso faça uso destas
  2. Diretório roles/ do arquivo playbook.yml
  3. Roles_path ~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles
  4. 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

ASSINE O BLOG PARA NOVOS POSTS !!!!

1 Comment

Deixe uma resposta

Este site utiliza o Akismet para reduzir spam. Saiba como seus dados em comentários são processados.