loading...

How to do "if a package is installed, do something" with Ansible

koh_sh profile image koh-sh ・2 min read

When you create Playbook, sometimes you may want to do these kinds of tasks.

  • if a package is installed, do something
  • if a user exists, do something

To only check the existence of packages or users without actually installing them.
For this kind of task, command or shell modules works fine.

  tasks:
    - name: check if httpd is installed
      shell: rpm -qa | grep httpd
      register: httpd_installed
      ignore_errors: True
      check_mode: False
      changed_when: False

    - name: print
      debug:
        msg: "httpd is installed"
      when: httpd_installed.rc == 0

But this is a little bit of trouble when you use it many times.

  • Extra parameters like changed_when or ignore_errors should be set
  • Warnings may be thrown at running Playbook or ansible-lint

So this article introduces some modules which can replace your command modules and make your Playbook simpler.

Test Environment

ansible: v2.9.9

targetOS: CentOS7.7 and Ubuntu 18.04

stat

https://docs.ansible.com/ansible/latest/modules/stat_module.html

stat module gets info of files.
Not only existence, it also checks file type(file/directory/link) or owner/group etc.

  tasks:
    - name: check if /etc/hosts exists
      stat:
        path: /etc/hosts
      register: etchosts

    - name: print
      debug:
        msg: "/etc/hosts exists"
      when: etchosts.stat.exists

    - name: print
      debug:
        msg: "/etc/hosts is directory"
      when: etchosts.stat.isdir # this should be False

package_facts

https://docs.ansible.com/ansible/latest/modules/package_facts_module.html

package_facts module gets installed packages list.
The info is available with ansible_facts.packages

  tasks:
    - name: check packages
      package_facts:
        manager: auto

    - name: print
      debug:
        msg: "Version of NetworkManager is {{ ansible_facts.packages['NetworkManager'][0]['version'] }}"
      when: "'NetworkManager' in ansible_facts.packages"

getent

https://docs.ansible.com/ansible/latest/modules/getent_module.html

getent module is a wrapper of getent command and can get info from passwd or group.
The info is available with getent_*** (*** is the name of database)
*Available databases varies on each OS and version.

  tasks:
    - name: check users
      getent:
        database: passwd

    - name: print
      debug:
        msg: "app1 user exists"
      when: "'app1' in getent_passwd"

service_facts

https://docs.ansible.com/ansible/latest/modules/service_facts_module.html

service_facts module get services list.
The info is available with ansible_facts.services

  tasks:
    - name: check services
      service_facts:

    - name: print
      debug:
        msg: "firewalld is {{ ansible_facts.services['firewalld.service']['status'] }}"
      when: "'firewalld.service' in ansible_facts.services"

Conclusion

By using each module instead of command module makes your Playbooks simpler and more useful for multiple OSs.

Discussion

pic
Editor guide