Repository navigation
Conversation
ansible-core 2.19 changed how cache plugins store entries. Before 2.19
the redis cache plugin stores a host's facts as plain JSON under
ansible_facts<host>. From 2.19 on, ansible-core puts a schema prefix
inside the plugin's key prefix and wraps the value, so the same host's
facts land under ansible_factss1_<host> as {"__payload__": "<JSON>"}.
Values set with set_fact cacheable keep their data tags in the payload,
as {"value": ..., "tags": [...], "__ansible_type": ...}.
The runtimes OSISM ships straddle that line: kolla-ansible (2.20)
writes the new key, osism-ansible (2.18) and ceph-ansible (2.16) write
the old one, and both coexist on a running cluster. Every reader in
python-osism used only the old key:
- osism get facts / osism dump facts and osism get states
(commands/get.py)
- GET /v1/inventory/hosts/{host}/facts and .../facts/{fact} (api.py)
- the RabbitMQ node address lookup (utils/rabbitmq.py), used by the
RabbitMQ commands in commands/migrate.py and commands/status.py
- osism reset facts --limit (commands/reset.py), which deleted only
the old key
- the facts freshness check run by osism apply (check_ansible_facts),
which derived the host name "s1_<host>" from new keys and then
skipped their entries as malformed
Once osism-ansible moves to ansible-core 2.19 or later, the facts it
gathers land under the new key as well, and only ceph-ansible keeps the
old one current. Tried on an OSISM 11.0.3 cluster with an image derived
from osism-ansible 0.20261111.0 that only replaces ansible-core with
2.19.15: after `osism apply facts`, redis held fresh facts under
ansible_factss1_<host> while ansible_facts<host> was a day old, and
osism dump facts showed the old data.
Add osism/utils/fact_cache.py and route all of these readers through
it:
- decode() parses an entry in either schema, unwraps __payload__ and
strips data tags. It does this itself rather than with ansible-core's
private _cache_persistence decoder, so it returns plain JSON data and
does not depend on ansible-core internals or on which ansible-core
the reading image ships.
- get_host_facts() reads both keys and returns the newer entry by
ansible_date_time.epoch, since which key is current depends on which
runtime gathered last; on a tie, or without timestamps, the
schema-prefixed entry wins.
- scan_host_keys() groups the keys of both schemas by host; the
freshness check judges each host by its newest entry.
- delete_host_facts() deletes both keys and also removes <host> and
s1_<host> from the ansible_cache_keys sorted set the redis cache
plugin maintains. osism reset facts without --limit now deletes that
set too and reports the number of distinct hosts.
The API facts endpoints catch ValueError instead of JSONDecodeError,
since decode() also rejects entries that are not a mapping. The
freshness check now logs "unusable ansible_date_time.epoch" for a
well-formed entry with a non-numeric epoch instead of calling it
malformed; the host is still skipped.
Tests: tests/unit/utils/test_fact_cache.py covers the module against
fakeredis, and new tests cover the freshness check and the API with
new-format entries. Existing tests that pinned the exact redis calls
now expect both keys.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Roger Luethi <luethi@osism.tech>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ansible-core 2.19 changed how cache plugins store entries. Before 2.19 the redis cache plugin stores a host's facts as plain JSON under
ansible_facts<host>. From 2.19 on they land underansible_factss1_<host>as{"__payload__": "<JSON>"}, and values set withset_fact: cacheablekeep data tags ({"value": ..., "tags": [...], "__ansible_type": ...}).kolla-ansible (2.20) already writes the new key, osism-ansible (2.18) and ceph-ansible (2.16) write the old one, and both coexist on a running cluster. Every reader in python-osism used only the old key:
osism get facts/osism dump factsandosism get states(commands/get.py)GET /v1/inventory/hosts/{host}/factsand.../facts/{fact}(api.py)utils/rabbitmq.py), used by the RabbitMQ commands incommands/migrate.pyandcommands/status.pyosism reset facts --limit(commands/reset.py), which deleted only the old keyosism apply(check_ansible_facts), which derived the host names1_<host>from new keys and then skipped those entries as malformedChange
New module
osism/utils/fact_cache.py, and all of the readers above go through it:decode()parses an entry in either schema, unwraps__payload__and strips data tags itself rather than with ansible-core's private decoder, so it does not depend on which ansible-core the reading image ships.get_host_facts()reads both keys and returns the newer entry byansible_date_time.epoch.scan_host_keys()groups both schemas' keys by host; the freshness check judges each host by its newest entry.delete_host_facts()deletes both keys and removes<host>/s1_<host>from theansible_cache_keyssorted set the redis cache plugin maintains.osism reset factswithout--limitalso deletes that set and reports distinct hosts.The API facts endpoints catch
ValueError(whichdecode()also raises for a non-mapping entry). The freshness check logs "unusable ansible_date_time.epoch" for a well-formed entry with a non-numeric epoch instead of calling it malformed; the host is still skipped.Testing
tests/unit/utils/test_fact_cache.py(fakeredis): both schemas alone and together, either one newer, entries without a timestamp, tagged values, corrupt entries, the sorted-set cleanup. New freshness-check and API tests with new-format entries; existing tests that pinned the exact redis calls now expect both keys. Unit suite: 3539 passed, 3 xfailed.osismimage: the newer entry is returned for every host,osism dump factsshows it where the current code shows the older one, and the freshness check names each host once.osismimage, both carrying this change (Ceph via cephadm, so no runtime writes the old key): redis held 0 old-format and 8 new-format keys;osism dump factsreturned current facts andGET /v1/inventory/hosts/<host>/facts/<fact>answered 200.🤖 Generated with Claude Code