Hello, I'm trying to add a list of users from my pillar. However when I specify the dictionary to be sorted (|dictsort) it's returning the following error.
SaltRenderError: Jinja variable dict object has no element ('Username', {'fullname': 'user name', 'shell': '/bin/bash', 'email_address': '[email protected]', 'homedir': '/home/username', 'uid': 0000})
{%
for account in pillar.user_accounts|dictsort %}{%
if pillar.user_accounts[account].has_key('email_address')
%}{{ account }} {{ pillar['user_accounts'][account].email_address }}
{% endif %}{%
endfor %}
According to the following document, I should be able to use dictsort and sort by key and case insensitive.
http://jinja.pocoo.org/docs/dev/templates/
Edit: Removing "|dictsort" works however the order isn't always the same so salt thinks that there are always changes.
Here is a sample of my user_accounts pillar.
user_accounts:
user1:
fullname: user one
email_address: [email protected]
homedir: /home/user1
shell: /bin/bash
uid: 10001
user2:
fullname: user two
email_address: [email protected]
homedir: /home/user2
shell: /bin/bash
uid: 10040
@slimg00dy, thanks for the report. It seems that the problem is that |dictsort is returning an object of the form (<sort-key>, dictionary) rather than just the dictionary itself. You can work around this by either doing for account in pillar.user_accounts|dictsort[1], although I'm not sure if this will work in jinja, or change your pillar dictionary to a list.
@AkhterAli Did you get a chance to try the approach suggested by @jfindlay ?
@cachedout Apologies for the late reply. This has not worked either.
----------
ID: /etc/postfix/virtusers
Function: file.managed
Result: False
Comment: An exception occurred in this state: Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/salt/state.py", line 1563, in call
**cdata['kwargs'])
File "/usr/lib/python2.7/dist-packages/salt/states/file.py", line 1423, in managed
**kwargs
File "/usr/lib/python2.7/dist-packages/salt/modules/file.py", line 3129, in check_managed_changes
**kwargs)
File "/usr/lib/python2.7/dist-packages/salt/modules/file.py", line 2795, in get_managed
**kwargs)
File "/usr/lib/python2.7/dist-packages/salt/utils/templates.py", line 121, in render_tmpl
output = render_str(tmplstr, context, tmplpath)
File "/usr/lib/python2.7/dist-packages/salt/utils/templates.py", line 314, in render_jinja_tmpl
tmplstr)
SaltRenderError: Jinja syntax error: expected token 'end of statement block', got '['; line 3
---
root [email protected]
{%
for account in pillar.user_accounts|dictsort[1] %}{% <======================
if pillar.user_accounts.account.has_key('email_address')
%}{{ account }} {{ pillar.user_accounts.account.email_address }}
{% endif %}{%
endfor %}
{%
[...]
---
@AkhterAli
A jinja dictsort returns a tupple that you _must_ unpack. Here is how I use dictsort in jinja;
{% for accu_key, accu_value in accumulator | dictsort -%}
{% for text in accumulator[accu_key] -%}
{{ text }}
{% endfor -%}
{% endfor -%}
Could you try this?
And maybe a tip;
-%} or -}} eats all trailing whitespace (incl. newline(s)){%- or {{- eats all leading whitespace (incl. newline(s) from previous line(s))@anonymouz
I just attempted both, it seems like when I add the "-" in the mentioned places, I get the following error.
----------
ID: /etc/postfix/virtusers
Function: file.managed
Result: False
Comment: Unable to manage file: Jinja variable dict object has no element ('username', {'fullname': 'Firstname lastname', 'shell': '/bin/bash', 'email_address': '[email protected]', 'homedir': '/home/username', 'uid': 10042})
Started: 21:03:27.488589
Duration: 21.358 ms
Changes:
This is what my saltstate looked liked
{% for account in pillar['user_accounts']|dictsort -%}
{%if pillar['user_accounts'][account].has_key('email_address') -%}
{{ account }} {{ pillar['user_accounts'][account].email_address }}
{% endif -%}
{% endfor -%}
I've also tried
{% for account in pillar['user_accounts']|dictsort %}
{%if pillar['user_accounts'][account].has_key('email_address') %}
{{ account }} {{ pillar['user_accounts'][account].email_address -}}
{% endif %}
{% endfor %}
It looks up the pillar values just fine but it fails to apply them in the appropriate places for some reason.
@AkhterAli
I'm sorry for the confusion, I only mentioned the "-" for formatting the jinja template and its output. This because of your example formatting, I see it a lot, and most people don't know about the "-" modifier. This is unrelated to your question. Now back to your problem.
I'm not familiar with your pillar layout but my guess is that this should work;
{% for account, values in pillar['user_accounts'] | dictsort -%}
{% if pillar['user_accounts'][account].has_key('email_address') -%}
{{ account }} {{ pillar['user_accounts'][account].email_address }}
{% endif -%}
{% endfor -%}
Could you try this?
Maybe even !?;
{% for account, values in pillar['user_accounts'] | dictsort -%}
{% if values[account].has_key('email_address') -%}
{{ account }} {{ values[account].email_address }}
{% endif -%}
{% endfor -%}
@anonymouz This is how my pillar is structured.
user_accounts:
username:
fullname: First Name Last Name
email_address: [email protected]
homedir: /home/username
shell: /bin/bash
uid: 10001
username:
fullname: First Name Last Name
email_address: [email protected]
homedir: /home/username
shell: /bin/bash
uid: 10040
@anonymouz
{% for account, values in pillar['user_accounts'] | dictsort -%}
{% if pillar['user_accounts'][account].has_key('email_address') -%}
{{ account }} {{ pillar['user_accounts'][account].email_address }}
{% endif -%}
{% endfor -%}
That seems to be doing the trick, let me further confirm and I'll close this issue out.
@anonymouz
Thanks much!
Closing issue.
Most helpful comment
@AkhterAli
A jinja dictsort returns a tupple that you _must_ unpack. Here is how I use dictsort in jinja;
Could you try this?
And maybe a tip;
-%}or-}}eats all trailing whitespace (incl. newline(s)){%-or{{-eats all leading whitespace (incl. newline(s) from previous line(s))