WIP: Ensure bare & full Jinja var give the same result#45719
WIP: Ensure bare & full Jinja var give the same result#45719pilou- wants to merge 3 commits intoansible:develfrom
Conversation
|
i'm not sure this is a good fix since it can force double interpolation when it is not wanted. Also, you should not hardcode |
|
I'm in agreement with bcoca here too. We warn when people use I don't think we should double eval the conditional. This could cause us to end up with even more of a problem with the string |
|
The fix might be not the right but I don't find any reason to have the first task executed while the other two are skipped: How can |
|
This happens very specifically because the results are templated at different times. In the first example, we template In the second, we template it at task parsing, and then use the evaluated expression in the conditional. So the first is evaluated as: The second, because of how we construct the conditional, just becomes: Notice that the So because you templated it early, you got an unexpected result. Which is typically why |
|
With the above outlined, I would say that your change is actually causing the wrong thing to happen even more than it already does. |
This patch doesn't change how string
I meant: AFAIK this behavior isn't documented and is unexpected. |
I would consider what happens when you use explicit jinja templating in the when statement to be what is unexpected. So the current behavior is acceptable for me. We warn users to not use explicit templating, for these reasons, but you are correct that it isn't really documented. I believe we should probably expand the warning and potentially add documentation to this affect. |
|
Note that this one: doesn't generate a warning and have the same behavior than Moreover, it is very confusing that the recommended format is: while the following task doesn't work as expected: What is the recommended way to write the task above ? |
That is complicated, and the amount of indirection doesn't really make it feasible. I'm not saying we don't have a problem, but it needs to be addressed in the opposite direction. Instead of making bare expressions work like expressions with explicit jinja, we need to make explicit jinja expressions work like bare expressions. This involves ensuring that we don't always insert "bare" strings into the jinja template. I've played around with something this morning, although I am positive it has bugs: diff --git a/lib/ansible/playbook/conditional.py b/lib/ansible/playbook/conditional.py
index 90c213bde3..e41b82d9ab 100644
--- a/lib/ansible/playbook/conditional.py
+++ b/lib/ansible/playbook/conditional.py
@@ -29,6 +29,7 @@ from ansible.errors import AnsibleError, AnsibleUndefinedVariable
from ansible.module_utils.six import text_type
from ansible.module_utils._text import to_native
from ansible.playbook.attribute import FieldAttribute
+from ansible.utils.vars import isidentifier
try:
from __main__ import display
@@ -39,7 +40,6 @@ except ImportError:
DEFINED_REGEX = re.compile(r'(hostvars\[.+\]|[\w_]+)\s+(not\s+is|is|is\s+not)\s+(defined|undefined)')
LOOKUP_REGEX = re.compile(r'lookup\s*\(')
-VALID_VAR_REGEX = re.compile("^[_A-Za-z][_a-zA-Z0-9]*$")
class Conditional:
@@ -129,7 +129,7 @@ class Conditional:
# - item
# with_items:
# - 1 == 1
- if conditional in all_vars and VALID_VAR_REGEX.match(conditional):
+ if conditional in all_vars and isidentifier(conditional):
conditional = all_vars[conditional]
# make sure the templar is using the variables specified with this method
@@ -188,8 +188,11 @@ class Conditional:
except Exception as e:
raise AnsibleError("Invalid conditional detected: %s" % to_native(e))
+ if conditional != original or (not isidentifier(conditional) and len(conditional.split()) == 1):
+ conditional = repr(to_native(conditional))
+
# and finally we generate and template the presented string and look at the resulting string
- presented = "{%% if %s %%} True {%% else %%} False {%% endif %%}" % conditional
+ presented = u"{%% if %s %%} True {%% else %%} False {%% endif %%}" % conditional
val = templar.template(presented, disable_lookups=disable_lookups).strip()
if val == "True":
return TrueIn your initial example, this creates templates like the following for The notable difference is the 2nd, that shows a string of |
Behavior should not differ when bare variable is used with 'when' keyword.
Before this change:
- debug:
when: '["0", "1"]|min' # not skipped
- debug:
when: '{{ ["0", "1"]|min }}' # skipped
- debug:
vars:
expr: '{{ ["0", "1"]|min }}' # skipped
when: 'expr'
d501011 to
6bc650b
Compare
Completely written by sivel, thanks to him :)
6bc650b to
4a4ac77
Compare
|
Closing, as these changes are obsolete with the template engine overhaul. The examples given use the strings |
SUMMARY
Ensure bare & full Jinja var give the same result
ISSUE TYPE
COMPONENT NAME
lib/ansible/playbook/conditional.py
ANSIBLE VERSION