Can we rely on play variables being re-calculated/re-templated for each host in a play?

26 views
Skip to first unread message

Jonathan Strootman

unread,
Jul 25, 2016, 4:09:02 PM7/25/16
to Ansible Project
Hello,

I know that you can, but it seems ambiguous on whether one should.

For example:
There is a role named "role_1", which has templated variables in both "defaults/main.yml" and "vars/main.yml". 
I could create a playbook which prints those variables for a set of hosts, and the variables would change for each host.
For the sake of discussion, here is what those role variables could be:
---
# defaults file for role_1
my_default_inventory
: "{{inventory_hostname}}-sample"

---
# vars file for role_1
some_var
: "{{ansible_hostname}}"

However, many examples from documentation and from around the web seem to place all non-templated role variables in either the roles vars or defaults. 
This seems especially true if the variables are templated from facts.

Instead, these examples will often use the "set_fact" module to set these variables. 

The ambiguity seems to rise from the understanding of "variable scope". The documentation does not clearly state when role variables are re-templated. So, if you have a variable that you know will change from host to host but only needs to be set once per role, it seems that people rely on explicitly placing variables into the "facts". I'm guessing that the use of "set_fact" is used under the assumption that authors are unclear on whether they can rely on role variables being in the "host" scope. 
 
So, please help me clear up my guesses and speculations! 
Does the example stated above work by design, or by accident? Specifically, can I rely on role variables being re-templated within the "host" scope?

Please let me know if you need more clarification.

Thank you.


Brian Coca

unread,
Feb 28, 2017, 11:19:29 AM2/28/17
to Ansible Project
Variables are lazily evaluated and computed per host. The issues with
set_fact are that the evaluation is happening before setting the
variable as ansible evaluates the expression to pass it to the task:

so

vars:
varname: "{{expression}}" # this is lazy


- set_facts: varname={{expression}} #var is set to result of
'expression' as it is evaluated for the task.

I hope that clarifies the issue.
----------
Brian Coca
Reply all
Reply to author
Forward
0 new messages