also sprach Brian Coca <briancoca@gmail.com> [2013.06.14.2255 +0200]:
Ansible only substitutes variables it knows about, since you can have
${var} in shell/command/raw/etc and not have it be an ansible var.
Of course, but no shell/command/raw/environment/whatever variable
could ever make it into a playbook and be interpolated there.
The behaviour in Ansible is unique, to my knowledge, and as such
confusing and difficult to deal with. Every other software or tool
I know will either expand undefined variables with nothing, or emit
an error. Simply not expanding the variable and leaving the sentinel
in place is new to me.
We recently picked up the topic of variable precedence again[0], and
many have since suggested what David proposes in
https://groups.google.com/d/msg/ansible-project/Gd_7P3Ei_Vs/vqTB1BvrqEUJ
which is to treat roles as imperative constructs and to pass
variables to them, like so:
{ role: foo, x: 42, ntp_server: $my_url }
Now, if $my_url isn't defined anywhere, the role will get "$my_url"
verbatim, which makes it rather hard to catch an error and alert the
user about forgetting to specify this "required" parameter.
This is even worse in case when you want to support optional
parameters, e.g. imagine a role assembling /etc/motd from parts. You
might want to provide a way for a single host to override the entire
file with a message, e.g.
{ role: motd, override: $motd_override }
In this case, it wouldn't be an error to leave the variable
$motd_override undefined, but the result would be… yes:
echo \$motd_override > /etc/motd
which is surely not what anyone wants.
Let's recap:
1. The only way to override defaults set in roles in vars/main.yml
is by passing parameters to the role, like above;
2. If a non-existent variable is referenced, the reference itself
is echoed, e.g. "$motd_override" in the above;
3. Therefore it is not possible to export optional parameters from
roles, which would be tested inside the role or jinja2
template, e.g. {% if override is defined %} — this will always
yield true, because if $motd_override is undefined, the role
parameter 'override' will end up being defined to be verbatim
"$motd_override".
Michael, is this also behaviour in Ansible that some people want and
thus you won't change?