Sort with two attributes

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

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.

1 Like

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.

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 

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.