-
Notifications
You must be signed in to change notification settings - Fork 23.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
"KeyError: 'undefined variable: 0'" when using {% import %} and {% include %} #20494
Comments
I believe this may be a duplicate of #20063 I would recommend trying out the ansible devel release to see if that resolves your problem. You may also try downgrading to jinja2<2.9 as 2.9 is known to be incompatible. |
Doesn't sound like the same thing to me ("nested templates inside of loops defined in a parent template do not receive the local scope"). I'm not doing any loops here.
In a fresh 16.04 environment:
Set up the same test, it fails in the same way
OK, that works. So, perhaps should ansible declare this python version dependency explicitly, until the issue is sorted? |
We had actually pinned jinja2, and found that on a number of systems, that jinja2<2.9 is not available via package managers, so it has been unpinned for now. cc @jimi-c |
Hello Thanks for suggestion, its works also for me, with only changing Jinja2 version 2.9.4 -> 2.8.1. My case was like following:
Regards, |
Just noting that with Jinja2 > 2.8.1, this breaks all the way back to the 1.x versions, so it's not necessarily because of anything new we've done. |
The statsd.j2 include approach is great, but it is hitting an ansible bug with Jinja2==2.9.5 which hasn't been fixed with Ansible and doens't seem to be fixed anytime soon. Here is an example bug: ansible/ansible#20494 This patch also refactors the statsd.j2 import parts, a lot of if/else statements were not required. Change-Id: Ib78ac0a8891874b1c2e777fac8f3fb89304e6872
The statsd.j2 include approach is great, but it is hitting an ansible bug with Jinja2==2.9.5 which hasn't been fixed with Ansible and doens't seem to be fixed anytime soon. Here is an example bug: ansible/ansible#20494 This patch also refactors the statsd.j2 import parts, a lot of if/else statements were not required. Change-Id: Ib78ac0a8891874b1c2e777fac8f3fb89304e6872 (cherry picked from commit 352969e)
same issue when importing 2x, jinja 2.8 downgrade can work around it my templates just suddenly stopped working after I updated my system regularly 757a05a doesn't help |
In order to unblock the Swift gate for stable/newton we need to backport 2 fixes at the same time: Move away from include statsd.j2 The statsd.j2 include approach is great, but it is hitting an ansible bug with Jinja2==2.9.5 which hasn't been fixed with Ansible and doens't seem to be fixed anytime soon. Here is an example bug: ansible/ansible#20494 This patch also refactors the statsd.j2 import parts, a lot of if/else statements were not required. (cherry picked from commit 3591f80) Use upper constraints when installing test requirements (cherry picked from commit 5de40eb) Change-Id: Iaf883eeaed3bd935aefef0debfb0723785a170f1
kill me now |
Hello, my distro ansible package maintainer cites this bug as a reason he is forcing us to downgrade jinja when we install ansible-2.3.1.0 [1]., so I want to ask here, is there any idea of an ETA to get this fixed? Downgrading everyone's jinja when they install ansible doesn't seem to be an optimal solution to me. |
this should also be tagged affects_2.3 as that's the version we have |
Don't upgrade to fedora 26 or you'll hit this issue. Comes with: python2-jinja2-2.9.6-1 Probably not the best place, but workaround if you're on Fedora 26 to install the fc25 version of jinja2:
[edit] dnf updates may want to include |
Can you please give us an update on this bug? Do you have any ideas regarding what is going on? Have you been able to reproduce this, or do you know when it could possibly be fixed? |
looks like this wasn't fixed in 2.3.2.0 either... |
Can someone from upstream please take a look at this and give us an idea of what is going on and when it will be fixed? Thanks much for your time. |
Note: the affects_2.3 is to mark that this affects 2.3; it's not a guarantee that it will be fixed in 2.3. We'll have to find out what the fix is before we can decide whether it can be backported or not. |
pallets/jinja@d67f0fd changed the behavior of get_all so that it returns a "private" dictionary: diff --git a/jinja2/runtime.py b/jinja2/runtime.py
index 43f25063..95268e5a 100644
--- a/jinja2/runtime.py
+++ b/jinja2/runtime.py
@@ -170,9 +170,14 @@ def get_exported(self):
return dict((k, self.vars[k]) for k in self.exported_vars)
def get_all(self):
- """Return a copy of the complete context as dict including the
- exported variables.
+ """Return the complete context as dict including the exported
+ variables. For optimizations reasons this might not return an
+ actual copy so be careful with using it.
"""
+ if not self.vars:
+ return self.parent
+ if not self.parent:
+ return self.vars
return dict(self.parent, **self.vars)
@internalcode That could cause problems with any code that isn't careful with that "private" dictionary. For example, the jinja2.debug.get_jinja_locals function modifies the dictionary returned from https://github.com/pallets/jinja/blob/d67f0fd4cc2a4af08f51f4466150d49da7798729/jinja2/debug.py#L198 |
The get_all calls inside jinja2.compiler look suspicious: https://github.com/pallets/jinja/blob/d67f0fd4cc2a4af08f51f4466150d49da7798729/jinja2/compiler.py It appears to be creating new contexts that hold references to the "private" dictionary returned from get_all! |
Since commit d67f0fd, callers of Context.get_all() need to make a copy it they're going to modify the result. Fixes: d67f0fd ("Generalize scoping. This fixes pallets#603") See: ansible/ansible#20494
Since commit d67f0fd, callers of Context.get_all() need to make a copy it they're going to modify the result. Fixes: d67f0fd ("Generalize scoping. This fixes pallets#603") See: ansible/ansible#20494
I think the problem on ansible sides is related to ansible.template.vars.AnsibleJ2Vars. It isn't 'dict-like' enough for the way jinja creates the context. At one point it uses an instance Adding an iter to AnsibleJ2Vars seems to get this working at first glance |
manually applying the patch zmedico@db69669 fixes the issues I had since updating to jinja 2.9 Thank you @zmedico ! |
@zmedico Once again you made things work again. Thanks. |
for reference, stack traces for the 'fails1.sh' and 'fails2.sh' repros, after letting the 'template' action re raise templating exceptions diff diff --git lib/ansible/plugins/action/template.py lib/ansible/plugins/action/template.py
index 33aa580..54034e9 100644
--- lib/ansible/plugins/action/template.py
+++ lib/ansible/plugins/action/template.py
@@ -154,6 +154,7 @@ class ActionModule(ActionBase):
resultant = self._templar.do_template(template_data, preserve_trailing_newlines=True, escape_backslashes=False)
self._templar.set_available_variables(old_vars)
except Exception as e:
+ raise
result['failed'] = True
result['msg'] = "%s: %s" % (type(e).__name__, to_text(e))
return result jinja-2.9
fails2.sh
|
some intg tests the reproduce this at devel...alikins:jinja_29_intg_tests_20494 |
and some unit tests at devel...alikins:jinja_29_20494_unit_tests (separate branches so they can more easily be merged/picked into @zmedico branch) |
test cases here are based on ansible#20494 (comment)
For compatibility with the Context.get_all() implementation in jinja 2.9, make AnsibleJ2Vars implement collections.Mapping. Also, make AnsibleJ2Template.newcontext() handle dict type for the 'vars' parameter. See: pallets/jinja@d67f0fd Fixes: ansible#20494
test cases here are based on ansible#20494 (comment)
Fix a long standing incompatibility between recent versions of ansible and jinja. ansible/ansible#20494 Based on a patch by Zac Medico at: zmedico/ansible@32e5613 Masked for testing.
* template: fix KeyError: 'undefined variable: 0 For compatibility with the Context.get_all() implementation in jinja 2.9, make AnsibleJ2Vars implement collections.Mapping. Also, make AnsibleJ2Template.newcontext() handle dict type for the 'vars' parameter. See: pallets/jinja@d67f0fd Fixes: #20494 * add units/template/test_vars * intg tests for jinja-2.9 issues like 20494 test cases here are based on #20494 (comment)
* template: fix KeyError: 'undefined variable: 0 For compatibility with the Context.get_all() implementation in jinja 2.9, make AnsibleJ2Vars implement collections.Mapping. Also, make AnsibleJ2Template.newcontext() handle dict type for the 'vars' parameter. See: pallets/jinja@d67f0fd Fixes: ansible#20494 * add units/template/test_vars * intg tests for jinja-2.9 issues like 20494 test cases here are based on ansible#20494 (comment) (cherry picked from commit 501fc7a)
ISSUE TYPE
COMPONENT NAME
ANSIBLE VERSION
CONFIGURATION
N/A
OS / ENVIRONMENT
Ubuntu 16.04. ansible installed via pip.
SUMMARY
When one template imports another one, and then includes another template, it barfs with "KeyError: 'undefined variable: 0'"
STEPS TO REPRODUCE
EXPECTED RESULTS
/tmp/foo to be created with:
ACTUAL RESULTS
ADDITIONAL INFO
If you change
templates/foo
to this, it works fine:And so does this:
So it appears to be something to do with the combination of import and include which is causing it to barf.
However if you remove the "with context", like this:
then it barfs in a different way:
So there is a potentially separate issue, that 'import ... with context' works, but 'import' by itself does not, in Ansible.
The difference is that in the latter case, jinja2 will cache the import with the template (since it doesn't depend on any of the dynamic context in that particular expansion of the template)
Finally: this appears not to be a bug with jinja2 itself. Using jinja2 API directly runs the test case with no problem:
gives:
The text was updated successfully, but these errors were encountered: