Alternative to the global `vars` dictionnary as a "null namespace" for vars
Summary
I'm trying to define a variable which should resolve correctly independently of delegation context, and has a different defaults depending on host context. By correctly, I mean that for a normal task on host A, the variable should be hostvars[A]['my-var'] (or the role default) and on a delegated task to B (from A), the variable should be hostvars['B']['my-var'] (or the role defaults) (The defaults also depend on host variables.)
I'm currently using vars for this and I'm looking for an alternative to access the global var namespace in a programmatic way.
This is my current implementation:
# my_role/vars/main.yml
# resolve variables across delegation
#
# this should point to the correct bin_dir in all contexts,
_var_ns: "{{ hostvars[ansible_delegated_vars.keys()[0]] if ansible_delegated_vars is defined else vars }}"
delegated_bin_dir: "{{ _var_ns['bin_dir'] | d(default_bin_dir) }}"
# the default filter is only useful in the delegation case and when bin_dir is not explicitely set in inventory for the delegated to host.
# Reused for bin_dir, but needs to be a separate variable to allow
# inventory override without mangling delegated_bin_dir
default_bin_dir: "{{(
'/usr/local/bin'
if _var_ns['ansible_facts']['os_family'] != 'Flatcar'
else '/opt/bin'
)
if _var_ns['ansible_facts']['user_id'] == (_var_ns['ansible_become_user'] | d('root'))
else
(_var_ns['ansible_facts']['env'].HOME + '/.local/bin')
}}"
# my_role/defaults/main.yml
bin_dir: {{ default_bin_dir }} # this one is supposed to be overriden (if necessary) in inventory.Unfortunately, vars is deprecated and set for removal.
Alternatives:
- the lookup plugin
varsonly resolves top level variable, so AFAIU it's not suitable for this.. ansible.utils.get_pathwould work if if'svarparameters was nullable, but that's not the case.- inlining _var_ns into every usage site (and using the target variable directly). This works but is not very practical or DRY.
- custom lookup plugin. I'm not sure if they do have access to the necessary data though. => probably the solution we'll try once
varsis removed. - using set_fact before to materialize defaults into hostvars -> but set_fact for big inventories has a certain overhead.
Issue Type
Feature Idea
Component Name
vars
Additional Information
See above for the example.
The context of this is Kubespray (Kubernetes installer) where a number of tasks are delegated, and needs to use the delegated host context for several things (file location, etc).
Code of Conduct
- I agree to follow the Ansible Code of Conduct
Source: ansible/ansible