the precedence of var_files includes when path is constructed from vars

92 views
Skip to first unread message

Nick

unread,
Oct 27, 2014, 2:24:03 PM10/27/14
to ansible...@googlegroups.com
Hello,

Something I discovered about ansible this morning surprised me.
Essentially: when loading vars files, anything loaded with a
*dynamically constructed name depending on the host* seems to be lower
precedence than those files with fixed names, or even dynamic names not
depending on the host. I'd have expected the opposite? (My ansible
version is a recent development one, specific information appended below.)

To elaborate, I was trying to override some variables like this:

---
- name: test
hosts: all
user: root

vars:
myhost: my.host.name

vars_files:

# defines xxx.yyydefault value
- vars.yml

# overrides xxx.yyy(I thought! Apparently it cannot.)
- "{{inventory_hostname}}.yml"

tasks:
- debug: msg="my var is {{ xxx.yyy }}"

This playbook uses two included vars files, vars.yml and
my.host.name.yml (where the playbook is being applied to a host named
"my.host.name" in the inventory).

I had expected the order of inclusion to define the precedence, in the
absence of any other information in the documentation:

http://docs.ansible.com/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable

However, whatever order I used, vars.yml won. It wasn't a mistake in my
naming, as

- If a variable was named in my.host.name.yml but not vars.yml, that
got set fine.
- If I removed vars.yml from the includes entirely, xxx.yyy got set
from my.host.name.yml fine.

Interestingly, "{{myhost}}.yml" still wins over
"{{inventory_hotname}}.yml", when "myhost" is set to "my.host.name", and
the order still doesn't seem to affect this.

To conclude, if I'm right, there seems to be an implicit order of
preference which means that paths constructed with "inventory_hostname"
(and maybe other built-in variables?) are evaluated first, but later
includes override them. Apparently it isn't possible to override
non-host specific vars depending on the host this way. To be clear, I
know there are other ways including using host_vars, the include task
module, etc., but that's a different point and not what I want to ask about.

The documentation seems to have nothing to say on this behaviour, so I
thought I'd:

a) point that out, assuming it is intentional...

but also:

b) ask for clarification of the details, and whether it really is
intentional, since it seems to preclude overriding vars as in this use case?

Are the are any other special variables?
What precedence is intended when ordinary vars like "myhost" are used
instead of ones like "inventory_host"?

c) ask if is it something which may be changed at a later date, or
relied on not to change?


Thanks,


Nick

---

ansible --version
ansible 1.8 (devel 2eda9a3a47) last updated 2014/10/10 18:43:36 (GMT +100)
lib/ansible/modules/core: (detached HEAD 5af8d55b03) last updated
2014/10/10 18:43:44 (GMT +100)
lib/ansible/modules/extras: (detached HEAD 681db4ce2c) last updated
2014/10/10 18:43:45 (GMT +100)
v2/ansible/modules/core: (detached HEAD cb69744bce) last updated
2014/10/08 10:13:54 (GMT +100)
v2/ansible/modules/extras: (detached HEAD 8a4f07eecd) last updated
2014/10/08 10:14:38 (GMT +100)
configured module search path = library/modules

Nick

unread,
Oct 30, 2014, 5:13:55 AM10/30/14
to ansible...@googlegroups.com
For the record, currently I am working around the aforementioned var
precedence behaviour with a diabolical hack, as follows:

---
- name: test
hosts: all
user: root

vars_files:

# Defines xxx.yyy default value. Diabolical hack, inserts
inventory_hostname and then removes it.
- "vars.yml{{inventory_hostname| inventory_hostname|truncate(0,
end='') }}"

# This can now override xxx.yyy
- "{{inventory_hostname}}.yml"

tasks:
- debug: msg="my var is {{ xxx.yyy }}"

This tricks Ansible into putting the variables from vars.yml into the
same precedence level as those from "{{inventory_hostname}}.yml"
include. I think it would make far more sense to the user if the
precedence of included vars were simply dependent on the order of
vars_files inclusion, whether the path is fixed or generated with
"inventory_hostname", but for now this means I can actually make progress.

Cheers,

Nick

Michael DeHaan

unread,
Oct 30, 2014, 4:48:31 PM10/30/14
to ansible...@googlegroups.com
inventory scoped variables have less priority than globally scoped things.

This is expected, yes.




--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-project+unsubscribe@googlegroups.com.
To post to this group, send email to ansible-project@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/54520149.8070608%40letterboxes.org.

For more options, visit https://groups.google.com/d/optout.

Nick

unread,
Oct 30, 2014, 6:08:27 PM10/30/14
to ansible...@googlegroups.com
On 30/10/14 20:48, Michael DeHaan wrote:
> inventory scoped variables have less priority than globally scoped things.
>
> This is expected, yes.

Thanks for confirming. This case didn't appear to be inventory scoped, as it
wasn't taking information from host_vars or group_vars, but I see why it is
logically the same.
Even so, the precedence seems backward: less specific globals beat more specific
inventory vars. Is there a reason for this or is it purely historical? If you
can tell me I'll attempt a documentation patch.

Assuming I'm not a weirdo and it is indeed a common case to want global defaults
which can be over-ridden on specific hosts, then I don't see a way to do that at
a playbook level rather than using role defaults or follownig the docs'
recommendation that "Site wide defaults should be defined as a ‘group_vars/all’
setting". These both force me to move playbook specific information into a
location where they lose context or may be swamped by unrelated definitions.
Task includes and the set_fact module might be another option, but they set vars
at "task time", which I believe is too late for the values to be seen in roles
the playbook might include.

Would playbook default vars be considered a reasonable feature request?

N

Michael DeHaan

unread,
Nov 1, 2014, 10:45:13 AM11/1/14
to ansible...@googlegroups.com
I'm happy with things as documented today.

Please refer to 

Variables — Ansible Documentation 


We have several thousands of users here and can't change behavior based on a particular request to do it differently, unfortunately.

If you want defaults, look at "defaults" in roles, which have lower power than even inventory.




N

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/5452B6B9.3020605%40letterboxes.org.
Reply all
Reply to author
Forward
0 new messages