loading...

Ansible: check if a package is installed on a remote system

setevoy profile image Arseny Zinchenko Originally published at rtfm.co.ua on ・2 min read

Have a self-written letsencrypt role (see the Prometheus: RTFM blog monitoring set up with Ansible – Grafana, Loki, and promtail post).

Before running the Let’s Encrypt client to obtain a new certificate – need to check if NGINX is installed on a remote host.

Let’s use the package_facts module:

...
- name: "Check if NGINX is installed"
  package_facts:
    manager: "auto"
...

And add a conditional check with when using the ansible_facts.packages array:

...
- name: "NGINX test result"
  debug: 
    msg: "NGINX found"
  when: "'nginx' in ansible_facts.packages"

- name: "NGINX test result"
  debug: 
    msg: "NGINX NOT found"
  when: "'nginx' not in ansible_facts.packages"

Check:

...
TASK [test : Check if NGINX is installed] ****
ok: [ssh.dev.rtfm.co.ua]

TASK [test : NGINX test result] ****
ok: [ssh.dev.rtfm.co.ua] => {
  "msg": "NGINX found"
}

TASK [test : NGINX test result] ****
skipping: [ssh.dev.rtfm.co.ua]

PLAY RECAP ****
ssh.dev.rtfm.co.ua      : ok=3    changed=0    unreachable=0    failed=0
...

Remove NGINX:

root@rtfm-do-dev:~# apt purge nginx

Run again:

...
TASK [test : Check if NGINX is installed] ****
ok: [ssh.dev.rtfm.co.ua]

TASK [test : NGINX test result] ****
skipping: [ssh.dev.rtfm.co.ua]

TASK [test : NGINX test result] ****
ok: [ssh.dev.rtfm.co.ua] => {
  "msg": "NGINX NOT found"
}

PLAY RECAP ****

ssh.dev.rtfm.co.ua      : ok=3    changed=0    unreachable=0    failed=0

Done.

Similar posts

Discussion

pic
Editor guide
Collapse
pfuntner profile image
John Pfuntner

Nice! I came up with a playbook that has a single debug task:

$ cat is-package-installed.yml
- name: Check to see if a package is installed
  hosts: "{{ hosts | default('localhost') }}"
  tasks:

  - name: Gather the packager facts
    package_facts:

  - name: Package status
    debug:
      msg: "{{ item }} {{ 'installed' if item in ansible_facts.packages else 'not installed' }}"
    loop: "{{ pkgs | default([]) }}"
$ ansible-playbook -e '{ "pkgs": ["foo", "zip"] }' is-package-installed.yml

PLAY [Check to see if a package is installed] ***********************************************************************************************************************************************************************************************

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

TASK [Gather the packager facts] ************************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Package status] ***********************************************************************************************************************************************************************************************************************
ok: [localhost] => (item=foo) => {
    "msg": "foo not installed"
}
ok: [localhost] => (item=zip) => {
    "msg": "zip installed"
}

PLAY RECAP **********************************************************************************************************************************************************************************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

$
Collapse
pfuntner profile image
John Pfuntner

Be aware of this requirement for the the package_facts module:

For Debian-based systems python-apt package must be installed on targeted hosts.

Otherwise, ansible_facts.packages is an empty dictionary. Reminder: Ubuntu is Debian-based.

Collapse
jeffersfp profile image
Jefferson F. Pires

Hey man! Which version of Ansible are you using? I'm using 2.8 and the packages key of facts are not being filled in :( I'm getting an empty dict {}.