Estou instalando uma lista de pacotes na variável de registro ansible e gerando-a com debug
:
community.general.homebrew:
name: "{{ package }}"
state: present
register: package_install
until: package_install is succeeded
loop:
- pam-reattach
- pinentry-mac
- jorgelbg/tap/pinentry-touchid
loop_control:
loop_var: package
- debug:
msg: "{{ package_install }}"
A saída é semelhante a esta:
msg:
changed: true
msg: All items completed
results:
- ansible_loop_var: package
attempts: 1
changed: false
changed_pkgs: []
failed: false
invocation:
module_args:
install_options: []
name:
- pam-reattach
path: /usr/local/bin:/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin
state: present
update_homebrew: false
upgrade_all: false
upgrade_options: []
msg: 'Package already installed: pam-reattach'
package: pam-reattach
unchanged_pkgs:
- pam-reattach
- ansible_loop_var: package
attempts: 1
changed: true
changed_pkgs:
- pinentry-mac
failed: false
invocation:
module_args:
install_options: []
name:
- pinentry-mac
path: /usr/local/bin:/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin
state: present
update_homebrew: false
upgrade_all: false
upgrade_options: []
msg: 'Package installed: pinentry-mac'
package: pinentry-mac
unchanged_pkgs: []
- ansible_loop_var: package
attempts: 1
changed: true
changed_pkgs:
- jorgelbg/tap/pinentry-touchid
failed: false
invocation:
module_args:
install_options: []
name:
- jorgelbg/tap/pinentry-touchid
path: /usr/local/bin:/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin
state: present
update_homebrew: false
upgrade_all: false
upgrade_options: []
msg: 'Package installed: jorgelbg/tap/pinentry-touchid'
package: jorgelbg/tap/pinentry-touchid
unchanged_pkgs: []
skipped: false
A var cadastrada package_install.results
contém uma lista de dicionários (ou mapas/hashes - corrija-me se estiver errado) com os dados relativos a cada package
instalação.
Preciso verificar se algum pinentry-mac
dos pinentry-touchid
pacotes foi instalado durante a tarefa anterior (o valor da changed
chave dentro de cada item é igual true
ou false
) e, se sim, execute um comando especificado, por exemplo:
- command: <command>
when: >
`pinentry-mac` item's attribute `changed` is `True` within `package_install.results` \
OR \
`pinentry-touchid` item's attribute `changed` is `True` within `package_install.results`
Como eu faria isso?
Agora eu faço o seguinte:
- command: <command>
when: "'pinentry' in item.package and item.changed"
loop: "{{ macterm_package_install.results }}"
Mas neste caso o comando será executado duas vezes se ambos os pacotes tiverem sido instalados na etapa anterior, embora o comando deva ser executado apenas uma vez.
Existe alguma maneira de fazer isso corretamente? Quaisquer pensamentos são muito apreciados.
ATUALIZAR
A "melhor" maneira que consegui encontrar é esta (em duas etapas):
- name: Check if any of the pinentry packages were installed during previous tasks
set_fact:
pinentry_changed: True
when: "'pinentry-' in item.package and item.changed"
loop: "{{ macterm_package_install.results }}"
- command: <command>
when: pinentry_changed | default(false)
Mas realmente, existe alguma maneira mais elegante de resolver isso?
Responder1
Existem muitas opções. Escolha aquele que melhor se adapta ao seu caso de uso.
- Crie o dicionário
package_changed: "{{ package_install.results|
items2dict(key_name='package', value_name='changed') }}"
dá
package_changed:
jorgelbg/tap/pinentry-touchid: true
pam-reattach: false
pinentry-mac: true
Então as condições são triviais
- command: <command>
when: package_changed['pinentry-mac'] or
package_changed['jorgelbg/tap/pinentry-touchid']
- Crie a lista de pacotes alterados
changed_pkgs: "{{ package_install.results|
map(attribute='changed_pkgs')|flatten }}"
dá
changed_pkgs:
- pinentry-mac
- jorgelbg/tap/pinentry-touchid
Teste cada pacote
- command: <command>
when: ('pinentry-mac' in changed_pkgs) or
('jorgelbg/tap/pinentry-touchid' in changed_pkgs)
, ou intersecte as listas se você puder colocar os pacotes testados em uma lista
- command: <command>
when: changed_pkgs|intersect(test_pkgs)|length > 0
vars:
test_pkgs: [pinentry-mac, jorgelbg/tap/pinentry-touchid]
- Crie a lista e mapeie o nome base
changed_pkgs: "{{ package_install.results|
map(attribute='changed_pkgs')|flatten|
map('basename')|list }}"
dá
changed_pkgs:
- pinentry-mac
- pinentry-touchid
Use apenas os nomes dos pacotes
- command: <command>
when: ('pinentry-mac' in changed_pkgs) or
('pinentry-touchid' in changed_pkgs)