Hello experts,
How to sort a dict with two attributes for output in a report, similar to the code:
---
- hosts: localhost
gather_facts: false
vars:
databases: [
{
"dbname": "A_dg",
"is_standby": false
},
{
"dbname": "C_dg",
"is_standby": true
},
{
"dbname": "B_dg",
"is_standby": true
}
]
tasks:
- name: "Output"
debug:
msg: |
{% for db in databases | sort(attribute='is_standby', reverse=true) | sort(attribute='dbname') %}
{{ db.dbname }}
{% endfor %}
expected output:
TASK [Exibe bancos_standby] **********************************************************************************************************************
ok: [localhost] => {
"msg": "B_dg\nC_dg\nA_dg\n"
}
But I can only sort by the second field:
TASK [Exibe bancos] ******************************************************************************************************************************
ok: [localhost] => {
"msg": "A_dg\nB_dg\nC_dg\n"
}
I’ve tried using some of the methods below but it gave an error:
FAILED! => {“msg”: "The task includes an option with an undefined variable. The error was: ‘dict object’ has no attribute ‘[is_standby,dbname]’
...
{% for db in databases | sort(attribute='is_standby,dbname', reverse=true) %}
...
ansible --version: ansible 2.9.27
hugonz
(Hugo F. Gonzalez)
February 21, 2025, 6:42pm
2
Hi,
Sorting on a list of attributes was added to Jinja in (Jinja)version 2.11.0 per Template Designer Documentation — Jinja Documentation (3.1.x)
What version of Jinja is Ansible using? ansible --version gives you that. As I read the docs, what you’re doing should work, but your ansible-core is very old.
Hi Hugo, thanks for the reply. My ansible is ansible 2.9.27.
I think it’s unlikely that the people responsible where I work will update the version.
hugonz
(Hugo F. Gonzalez)
February 21, 2025, 7:44pm
4
BTW, in newer ansible (ansible [core 2.16.14]) I tried your sorting keys and I’m getting this, which is not what you said you needed anyway
- hosts: localhost
gather_facts: false
vars:
databases: [
{
"dbname": "A_dg",
"is_standby": false
},
{
"dbname": "C_dg",
"is_standby": true
},
{
"dbname": "B_dg",
"is_standby": true
}
]
tasks:
- name: "Output"
ansible.builtin.debug:
msg: |
{% for db in databases | sort(attribute='is_standby,dbname', reverse=true) %}
{{ db.dbname }}
{% endfor %}
result:
$ ansible-playbook doublesortdic.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does
not match 'all'
PLAY [localhost] ********************************************************************************************
TASK [Output] ***********************************************************************************************
ok: [localhost] => {
"msg": "C_dg\nB_dg\nA_dg\n"
}
PLAY RECAP **************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
hugonz
(Hugo F. Gonzalez)
February 21, 2025, 7:54pm
5
What you need it is to split into two lists based on true/false and then sort them in forward order:
- name: "Output"
ansible.builtin.debug:
msg: |
{% for db in databases | selectattr('is_standby','true') | sort(attribute='dbname') %}
{{ db.dbname }}
{% endfor %}
{% for db in databases | selectattr('is_standby','false') | sort(attribute='dbname') %}
{{ db.dbname }}
{% endfor %}
Results
TASK [Output] ***********************************************************************************************
ok: [localhost] => {
"msg": "B_dg\nC_dg\n\nA_dg\n"
}
PLAY RECAP **************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
I wouldn’t off the top of my head know how sorting true/false works. I wouln’ t use sort when there’s only two options.
Great idea! Thank you very much.