DEV Community

Stefano Martins
Stefano Martins

Posted on

Recarregando o inventário do Ansible durante a execução

Introdução

Esta dica surgiu a partir de uma dúvida no Telegram da LINUXtips e é ótima para quem precisa trabalhar com inventários dinâmicos ou realiza modificações em seu arquivo de inventário.

Imagine o seguinte cenário: Você possui um playbook que realiza modificações no seu inventário como adicionar um novo host, e durante a mesma execução do playbook precisa que este host recém-adicionado seja levado em consideração para uma próxima task ou role.

Para melhor ilustrar, criei abaixo um arquivo de inventário e um playbook que simplesmente irá imprimir todos os hosts do inventário, adicionar um novo host chamado host-03 e depois imprimir novamente os hosts:

# hosts
[all]
host-01
host-02
Enter fullscreen mode Exit fullscreen mode
# playbook.yml
--- 
- hosts: localhost
  become: true
  connection: local
  tasks:

    - name: Print list of hosts in inventory
      ansible.builtin.debug:
        msg: "{{ item }}"
      loop: "{{ groups['all'] }}"

    - name: Add host to inventory
      ansible.builtin.lineinfile:
        line: host-03
        path: ./hosts
        regexp: "^host-03"
        state: present

    - name: Print list of hosts in inventory
      ansible.builtin.debug:
        msg: "{{ item }}"
      loop: "{{ groups['all'] }}"
Enter fullscreen mode Exit fullscreen mode

Vamos executar o nosso playbook com ansible-playbook -i hosts playbook.yml, obtendo o seguinte resultado:

PLAY [localhost] ************************************************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************************************
ok: [localhost]

TASK [Print list of hosts in inventory] *************************************************************************************************************************************
ok: [localhost] => (item=host-01) => {
    "msg": "host-01"
}
ok: [localhost] => (item=host-02) => {
    "msg": "host-02"
}

TASK [Add host to inventory] ************************************************************************************************************************************************
changed: [localhost]

TASK [Print list of hosts in inventory] *************************************************************************************************************************************
ok: [localhost] => (item=host-01) => {
    "msg": "host-01"
}
ok: [localhost] => (item=host-02) => {
    "msg": "host-02"
}

PLAY RECAP ******************************************************************************************************************************************************************
localhost                  : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
Enter fullscreen mode Exit fullscreen mode

Percebe que foi adicionado um novo host host-03 (inclusive, você perceberá a nova entrada no arquivo hosts), porém na segunda impressão, ele continua não sendo impresso? O motivo disso é devido ao fato de que o Ansible apenas carrega na memória o inventário durante o início da execução do playbook, ignorando eventuais alterações no mesmo (inclusive para inventários dinâmicos).

Mas a pergunta que fica é: OK, e se eu precisar que alterações no meu inventário sejam à quente, para continuidade na execução? Bom, aí temos principalmente duas opções:

Opção A: utilize o módulo add_host

O módulo add_host serve para adicionarmos hosts dinamicamente à execução do Ansible, porém não persistidas no arquivo de inventário. Podemos utilizá-lo, adicionando uma task extra ao nosso playbook, carregando o host host-03 também na memória:

--- 
- hosts: localhost
  become: true
  connection: local
  tasks:

    - name: Print list of hosts in inventory
      ansible.builtin.debug:
        msg: "{{ item }}"
      loop: "{{ groups['all'] }}"

    - name: Add host to inventory file
      ansible.builtin.lineinfile:
        line: host-03
        path: ./hosts
        regexp: "^host-03"
        state: present

    - name: Add host to inventory (memory)
      ansible.builtin.add_host:
        name: host-03

    - name: Print list of hosts in inventory
      ansible.builtin.debug:
        msg: "{{ item }}"
      loop: "{{ groups['all'] }}"
Enter fullscreen mode Exit fullscreen mode

O resultado da execução é o seguinte:

PLAY [localhost] ************************************************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************************************
ok: [localhost]

TASK [Print list of hosts in inventory] *************************************************************************************************************************************
ok: [localhost] => (item=host-01) => {
    "msg": "host-01"
}
ok: [localhost] => (item=host-02) => {
    "msg": "host-02"
}

TASK [Add host to inventory file] *******************************************************************************************************************************************
changed: [localhost]

TASK [Add host to inventory (memory)] ***************************************************************************************************************************************
changed: [localhost]

TASK [Print list of hosts in inventory] *************************************************************************************************************************************
ok: [localhost] => (item=host-01) => {
    "msg": "host-01"
}
ok: [localhost] => (item=host-02) => {
    "msg": "host-02"
}
ok: [localhost] => (item=host-03) => {
    "msg": "host-03"
}

PLAY RECAP ******************************************************************************************************************************************************************
localhost                  : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
Enter fullscreen mode Exit fullscreen mode

Opção B: utilize a metatask refresh_inventory

Metatasks são basicamente tasks que alteram o comportamento do Ansible durante sua execução. Vamos adicionar uma delas no nosso playbook após a adição do nosso host ao arquivo de inventário para que o mesmo seja recarregado antes da nova impressão:

--- 
- hosts: localhost
  become: true
  connection: local
  tasks:

    - name: Print list of hosts in inventory
      ansible.builtin.debug:
        msg: "{{ item }}"
      loop: "{{ groups['all'] }}"

    - name: Add host to inventory file
      ansible.builtin.lineinfile:
        line: host-03
        path: ./hosts
        regexp: "^host-03"
        state: present

    - meta: refresh_inventory

    - name: Print list of hosts in inventory
      ansible.builtin.debug:
        msg: "{{ item }}"
      loop: "{{ groups['all'] }}"
Enter fullscreen mode Exit fullscreen mode
PLAY [localhost] ************************************************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************************************
ok: [localhost]

TASK [Print list of hosts in inventory] *************************************************************************************************************************************
ok: [localhost] => (item=host-01) => {
    "msg": "host-01"
}
ok: [localhost] => (item=host-02) => {
    "msg": "host-02"
}

TASK [Add host to inventory file] *******************************************************************************************************************************************
changed: [localhost]

TASK [Print list of hosts in inventory] *************************************************************************************************************************************
ok: [localhost] => (item=host-01) => {
    "msg": "host-01"
}
ok: [localhost] => (item=host-02) => {
    "msg": "host-02"
}
ok: [localhost] => (item=host-03) => {
    "msg": "host-03"
}

PLAY RECAP ******************************************************************************************************************************************************************
localhost                  : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
Enter fullscreen mode Exit fullscreen mode

 Conclusão

Neste breve artigo nós vimos como o Ansible lê seu inventário, e como podemos adicionar novos hosts durante sua execucão para novas tasks e roles, este conhecimento sendo aplicável tanto para inventários dinâmicos quanto estáticos (ou quando nós queremos manipular o nosso arquivo hosts).

Espero que tenham curtido!

Latest comments (1)

Collapse
 
welkson profile image
Welkson Renny de Medeiros • Edited

Excelente post @stefanomartins !