1. Define the observation needed for the decision
A fictional playbook chooses a deployment path from a cached version. The value exists and is valid text, but that does not establish correspondence with software currently installed. Distinguish declared value, collected observation and intended requirement. For a change decision, record host, collection method, time and relevant configuration version. The variable may remain correct or become stale after manual intervention. Do not resolve uncertainty by silently replacing absence with a value that permits progress. Define when new evidence is needed, when an earlier observation is acceptable and which conditions invalidate that acceptance. The lab uses synthetic release markers to make these distinctions visible.
2. Observe the two set_fact copies
The exercise assigns retained_value with cacheable: true. In the setting run, it observes both the host variable and the ansible_facts entry. It then assigns release-8 and executes clear_facts. The report still finds release-8 through the host variable but no longer finds the ansible_facts entry. This does not mean clearing failed: two representations with different behavior were observed. It also does not justify claiming every secret disappeared from memory. Use explicit names and references when diagnosing results, and avoid conditions assuming fact clearing removes any same-named variable. During handover, show the comparison between both references and explain the execution in which each was observed.
3. Demonstrate persistence across processes
Reading a variable in a later task of the same playbook does not prove persistence into the next execution. The lab ends the process that wrote values and starts another to read them. With jsonfile configured in a temporary directory, the second process finds release-7 without setting it again. After clearing, a new process observes absence. A separate trial uses the memory plugin: cacheable remains on the task, but the next process does not recover the value. The experiment therefore compares concrete cache configuration without assuming the parameter alone enables persistent storage. Record the effective plugin and configuration. Platform cache policy can differ from the local setup used while preparing the playbook.
4. Relate validity, scope and exposure
A TTL controls when an entry becomes ineligible for cache use; it does not turn an old observation into a current measurement. Address, version or cluster-membership changes can occur before that interval ends. For critical operations, choose collection or validation suited to the decision instead of merely increasing TTL. Availability of hostvars also does not prove that host’s facts were gathered. Distinguish inventory variables from collected or cached data. When storing results, minimize sensitive information, control access and define retention. This example stores only synthetic markers; it does not establish credential protection and should not be adapted to put passwords in a cache file without a separate security design.
5. Prepare a reproducible diagnosis
When two executions differ, retain enough context to reproduce the situation: Ansible version, selected inventory, configuration, relevant extra variables and value sources. In the lab, each process records an exit code, recap and output hash alongside the results supporting assertions. Credentials and business data are not published. To investigate an unexpected value, first locate the representation read and the order in which it was written, cleared or overwritten. Repeat the needed collection in an authorized environment copy and confirm the final condition before resuming. A local macOS test establishes the exercised Ansible 2.16.14 behavior; it does not validate SSH, privileges, reboot, RHEL services or a real AAP environment.
# Local teaching example. Run: ansible-playbook facts.yml
# This snippet observes same-run copies, not cross-process persistence.
---
- hosts: localhost
connection: local
gather_facts: false
tasks:
- name: Create two representations
ansible.builtin.set_fact:
retained_value: release-8
cacheable: true
- name: Observe before clearing
ansible.builtin.debug:
msg:
host_value: "{{ retained_value }}"
fact_value: "{{ ansible_facts.retained_value }}"
- name: Clear facts
ansible.builtin.meta: clear_facts
- name: Observe the remaining host variable
ansible.builtin.debug:
msg:
host_value: "{{ retained_value }}"
fact_exists: "{{ 'retained_value' in ansible_facts }}"
# Expected: host_value remains release-8; fact_exists is false.
# The full lab compares jsonfile and memory in separate playbook processes.
After clear_facts, the host variable retains release-8 in the same run; the next process no longer finds the value in the cleared cache.
Common pitfalls
Existing variable treated as recent observation; cacheable treated as automatic persistence; clear_facts treated as removal of all variables; TTL treated as proof of validity.
Related topics: Delegation, batches and shared effects
Explain where the value came from, who owns it and how long it supports the intended decision.
Reference: set_fact copies and cacheable behavior · EX294 current objectives inspected 2026-09-30; RHCE in Ansible framework effective 2026-05-11; booking product version not publicly pinned