Q: "I think ansible_os_family is a reasonable choice ... If you have a definitive reference, please add it as an answer."
Variable ansible_local
A: Create such a 'definitive' reference on your own. The setup module provides the parameter fact_path for this purpose. For example, test it on the localhost first. Create JSON file
shell> cat /etc/ansible/facts.d/misc.fact
{"run_setup": false}
The playbook
shell> cat pb.yml
- hosts: localhost
gather_facts: true
tasks:
- debug:
var: ansible_local
gives (abridged)
ansible_local:
misc:
run_setup: false
In your use case, you'll have to copy the file misc.fact to the remote hosts. Create a project for testing
shell> tree .
.
├── ansible.cfg
├── hosts
├── misc.fact
└── pb.yml
shell> cat ansible.cfg
[defaults]
gathering = explicit
collections_path = $HOME/.local/lib/python3.9/site-packages/
inventory = $PWD/hosts
roles_path = $PWD/roles
remote_tmp = ~/.ansible/tmp
retry_files_enabled = false
stdout_callback = yaml
shell> cat hosts
test_11
test_13
shell> cat misc.fact
{"run_setup": false}
Test it in a single play here to demonstrate the idea. In your use case, keep the block to manage the files either in the playbook or put it into the roles. Put the conditional setup into the roles.
shell> cat pb.yml
- hosts: all
gather_facts: false
pre_tasks:
- name: Manage ansible_local.misc facts
block:
- file:
state: directory
path: /etc/ansible/facts.d
- copy:
src: misc.fact
dest: /etc/ansible/facts.d/misc.fact
mode: 0644
become: true
- setup:
when: ansible_local.misc.run_setup|d(true)
tasks:
- debug:
var: ansible_local.misc.run_setup
gives
shell> ansible-playbook pb.yml
PLAY [all] ************************************************************************************
TASK [file] ***********************************************************************************
changed: [test_11]
changed: [test_13]
TASK [copy] ***********************************************************************************
changed: [test_13]
changed: [test_11]
TASK [setup] **********************************************************************************
ok: [test_13]
ok: [test_11]
TASK [debug] **********************************************************************************
ok: [test_11] =>
ansible_local.misc.run_setup: false
ok: [test_13] =>
ansible_local.misc.run_setup: false
PLAY RECAP ************************************************************************************
test_11: ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
test_13: ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Cache facts
A: I still believe a better solution is to cache facts. Set DEFAULT_GATHERING smart
smart: each new host that has no facts discovered will be scanned, but if the same host is addressed in multiple plays it will not be contacted again in the run.
and enable fact cache plugin. For example,
shell> cat ansible.cfg
[defaults]
gathering = smart
#
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_cache.json
fact_caching_prefix = ansible_facts_
fact_caching_timeout = 86400
#
collections_path = $HOME/.local/lib/python3.9/site-packages/
inventory = $PWD/hosts
roles_path = $PWD/roles
remote_tmp = ~/.ansible/tmp
retry_files_enabled = false
stdout_callback = yaml
Given the project for testing
shell> tree .
.
├── ansible.cfg
├── hosts
├── pb.yml
└── roles
└── roleA
└── tasks
└── main.yml
shell> cat hosts
test_11
test_13
shell> cat roles/roleA/tasks/main.yml
- debug:
var: ansible_os_family
shell> cat pb.yml
- hosts: all
roles:
- roleA
The facts are gathered for the first time
shell> ansible-playbook pb.yml
PLAY [all] ************************************************************************************
TASK [Gathering Facts] ************************************************************************
ok: [test_11]
ok: [test_13]
TASK [roleA : debug] **************************************************************************
ok: [test_11] =>
ansible_os_family: FreeBSD
ok: [test_13] =>
ansible_os_family: FreeBSD
PLAY RECAP ************************************************************************************
test_11: ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
test_13: ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
and cached
shell> tree /tmp/ansible_cache.json/
/tmp/ansible_cache.json/
├── ansible_facts_test_11
└── ansible_facts_test_13
Next time you run a playbook the cache is used
shell> ansible-playbook pb.yml
PLAY [all] ************************************************************************************
TASK [roleA : debug] **************************************************************************
ok: [test_11] =>
ansible_os_family: FreeBSD
ok: [test_13] =>
ansible_os_family: FreeBSD
PLAY RECAP ************************************************************************************
test_11: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
test_13: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Notes:
shell> ansible-doc -t cache -l
- Set CACHE_PLUGIN_TIMEOUT to your needs. The gathered facts will be updated after a timeout or on demand. Please test it
shell> cat roles/roleB/tasks/main.yml
- debug:
var: ansible_date_time.iso8601_micro
shell> cat roles/roleC/tasks/main.yml
- setup:
gather_subset: date_time
- debug:
var: ansible_date_time.iso8601_micro
shell> cat pb.yml
- hosts: all
roles:
- roleB
- roleC
a) Running repeatedly roleB and roleC. The first role uses the cached fact ansible_date_time. The last role updates the cache
shell> ansible-playbook -l test_11 pb.yml
PLAY [all] ************************************************************************************
TASK [roleB : debug] **************************************************************************
ok: [test_11] =>
ansible_date_time.iso8601_micro: '2023-06-20T08:10:56.219945Z'
TASK [roleC : setup] **************************************************************************
ok: [test_11]
TASK [roleC : debug] **************************************************************************
ok: [test_11] =>
ansible_date_time.iso8601_micro: '2023-06-20T08:11:15.289719Z'
PLAY RECAP ************************************************************************************
test_11: ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
shell> ansible-playbook -l test_11 pb.yml
PLAY [all] ************************************************************************************
TASK [roleB : debug] **************************************************************************
ok: [test_11] =>
ansible_date_time.iso8601_micro: '2023-06-20T08:11:15.289719Z'
TASK [roleC : setup] **************************************************************************
ok: [test_11]
TASK [roleC : debug] **************************************************************************
ok: [test_11] =>
ansible_date_time.iso8601_micro: '2023-06-20T08:11:39.579222Z'
PLAY RECAP ************************************************************************************
test_11: ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
b) Set ANSIBLE_CACHE_PLUGIN_TIMEOUT=-1
if you want to update the cache
shell> ANSIBLE_CACHE_PLUGIN_TIMEOUT=-1 ansible-playbook -l test_11 pb.yml
PLAY [all] ************************************************************************************
TASK [roleB : debug] **************************************************************************
ok: [test_11] =>
ansible_date_time.iso8601_micro: '2023-06-20T08:28:40.088411Z'
TASK [roleC : setup] **************************************************************************
ok: [test_11]
TASK [roleC : debug] **************************************************************************
ok: [test_11] =>
ansible_date_time.iso8601_micro: '2023-06-20T08:28:43.891752Z'
PLAY RECAP ************************************************************************************
test_11: ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0