Using ansible local facts to make your playbooks more declarative
Sometimes you need to declaratively manage packages on your target system but absense of state in ansible makes it inconvinient
For example you want a certain variable/list to represent a set of installed packages on your system, but when you remove package from the list it still is present on your target machine
Here is the simple pattern based on ansible_local facts that i found on the internet that may help you
Basically it holds state information in a file /etc/ansible/facts.d/*.fact on your target machine in a json/ini format and to reference it u can use {{ ansible_local.* }}
In this example we manage package creation but you can adapt it to yout own needs like maybe managing ssh authorized_keys file, etc.
- name: Defining packages to install
set_fact:
packages_to_install:
- curl
- git
- vim
- name: Installing a bunch of packages
apt:
name: "{{ packages_to_install }}"
state: present
- name: Checking if state has changed
apt:
name: "{{ item }}"
state: absent
loop: "{{ ansible_local.packages | default(packages_to_install) | difference(packages_to_install) }}"
register: removed_packages
- name: Ensuring that facts.d directory exists
file:
state: directory
path: /etc/ansible/facts.d
recurse: true
owner: root
mode: "0644"
- name: Adding current state to packages.fact
copy:
content: "{{ packages_to_install | to_json }}"
dest: /etc/ansible/facts.d/packages.fact
owner: root
mode: "0644"
when: removed_packages.changed
References
- Discovering variables: facts and magic variables # adding custom facts - https://docs.ansible.com/projects/ansible/latest/playbook_guide/playbooks_vars_facts.html#adding-custom-facts