Use variables from host_vars and if not existent fall back to role vars

Hi guys

I have a role that installs Python on the target host ([0]). Different hosts require different Python libraries (some only need the basic set of libraries, others need completely different ones). My idea was to define a list of default packages in the role vars [1] and then provide the custom packages in the host_vars [2] whenever required. Unfortunately according to [3] the role vars have higher precedence over the host_vars so this explains why the custom packages in host_vars never got picked up.

My next approach was to just have an additional task in the role that installs the host specific packages after the default ones. This works as long as all hosts have those variables defined. My goal however is to only specify a list of libraries for those hosts that differ from the default list. As you can see in [4] I tried two different things to work around missing host_vars for certain hosts: either try to fall back to an empty list via default() ) or use a when statement to check whether the variable is defined in host_vars or not. Both didn’t work.

Apart from that I also tried to move the content of python.pip.pkgs from ./roles/python/vars/main.yml to ./roles/python/defaults/main.yml but that didn’t work either. Can defaults have hirarchical variables at all? It seemed like Ansible just ignored whatever I put in there.

One last thing I was looking into is include_vars but I got stuck here with two issues: I have different environments (./inventories/{prod,staging,test}) and therefore the path to the host_vars is based on the inventory I provide when calling the playbook however I couldn’t get the path or name of the selected inventory. The second issue is that I don’t know how I can skip this include when the file doesn’t exist.

Could somebody shed some light on how I can define host specific variables that can overwrite role variables for a use case as described above. I googled for this but either it is so simple that nobody cares to write about it or I’m just bad at finding the solution.

Any help is appreciated.
Cheers

[0] https://pastebin.com/raw/1XSk1t8Z
[1] https://pastebin.com/raw/R0USFkEw
[2] https://pastebin.com/raw/kTDF3zuS
[3] http://docs.ansible.com/ansible/latest/playbooks_variables.html
[4] https://pastebin.com/raw/Emmb49qL

Hi guys

Ok it seems that I found the solution for the issue even though I don’t understand why it didn’t work before.

At [1] in my previous post I posted the content of my ./roles/python/vars/main.yml file. There I have a hierarchical variable ‘python.pip.pkgs’. When using it like this in the roles vars it works and I can reference it in [0] however as soon as I move this to ./roles/python/defaults/main.yml it didn’t work anymore (“‘dict object’ has no attribute ‘pkgs’”). As soon as I change python.pip.pkgs to _python.pip.pkgs (basically anything but python in the beginning) it works.

I don’t understand why I can use python as a variable name in role vars but not in default vars. Is this a known limitation? If so shouldn’t it be mentioned in [5]? I’m using Ansible 2.3.1.0 in case it is important.

Cheers
Frieder

[5] http://docs.ansible.com/ansible/latest/playbooks_variables.html#what-makes-a-valid-variable-name

Hi guys

Sorry to spam the mailing list. It seems that my previous assumption was wrong and I can indeed use python in defaults. If I understand it correctly the issue was that when I have a hierarchical variable in defaults that gets overwritten by host_vars then the whole block must be provided in host_vars and not only a part of it. Is this correct? Anyways I moved the pip part out of the python block and now it works. For those interested in this I put the stuff at [6], [7] and [8].

Cheers

[6] https://pastebin.com/raw/r0snPDhh
[7] https://pastebin.com/raw/USkxraMG
[8] https://pastebin.com/raw/k5RiDJcg

Yes, variables in Ansible get overwritten, not merged.
(Just for completeness, it's possible to set hashes/arays to be merged.)

Variables in role defaults/ has the lowest presidency and can therefor be overwritten many places.