I almost missed that Ansible 2.24 will be defaulting INJECT_FACTS_AS_VARS to False in future, meaning that facts like {{ ansible_os_distribution }} will stop working.
Instead, we’ll have to write {{ ansible_facts['distribution'] }}.
As somebody on the Fediverse amusingly wrote:
Happy (careful) search & replace day through all your roles and playbooks to those who celebrate.
The original behavior can be brought back (until that is deprecated) with an ansible.cfg setting:
The good thing is that with ansible-core 2.20+, it will tell you when you run the role/playbook/task file which places use the old way to access facts. So it’s not that hard to find these places. Or at least most of them…
The bad thing is that you have to pay careful attention if you’re using plugins such as community.sops.load_vars, since you should better not change “facts” they created since they will change to real variables once ansible-core finally allows it (hopefully in 2.21). It would have been nicer if the deprecation would have only be done after allowing plugins to set variables (and not just facts)…
Maybe the idea is to make it easier to distinguish between facts and variables. Right now their relationship is quite confusing. (And ansible.builtlin.set_fact’s name implying that it “sets facts” while it usually sets variables is not helping…)
Is there an ansible.builtin.set_var in our future? If I’m going to have to examine all my existing set_facts and make syntax changes, would much rather change to a module that actually does what I want rather than uglyfy the syntax to reference “facts” that aren’t actually facts.
In all my years of Ansible use (and accumulated code), I don’t believe I have a single instance of using set_fact to set a fact rather than a variable.
If I understand the discussion above, I’d strongly encourage the core team to reconsider the timing / ordering of these changes. We need a set_var before the current behavior of set_fact wrt variables is taken away.
ansible.builtin.set_fact is already setting variables, you need to provide cacheable: true to make it also set facts. It does make sense to split up these two things though IMO.
This only deprecates the default value of ‘injection’, so we can turn it off by default.
There is a plan on eventually deprecating the injection itself, but that will come later, after the revamp of register to add projections (probably in next version) and adding a way for actions to cleanly and purposefully set variables.
Long story about set_fact: set_fact was initially named set_var but this was misleading and set_host_scoped_var was … too long. So after many discussions set_fact was the name of compromise, misleading one as it did not ‘set a fact’, but a higher priority hope scoped variable with higher priority than facts. Eventually cacheable was added to allow for it also to be stored in the cache … but what really happens under the hood is that 2 variables get created, the aforementioned host scoped variable with higher precedence AND an actual fact, both set to the same value. The fact, gets cached and has ‘fact level precedence’ once retrieved from the cache, in subsequent runs, as in the ‘current’ run the host scoped variable will still exist and have the higher precedence.