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
# 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'] }}"
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
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'] }}"
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
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'] }}"
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
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!
Top comments (1)
Excelente post @stefanomartins !