3

I have a list I'm looping over, the issue is it gives a weird order.

param.yml file:

my_list:
  a: val1
  b: val2
  c: val3
  d: val3

Here my simple debug loop:

- name: debug
  debug:
    msg: "{{ item }}"
  loop: "{{ my_list | list }}"

Here the output:

ok: [host] => (item=a) => {
    "msg": "a"
}
ok: [host] => (item=c) => {
    "msg": "c"
}
ok: [host] => (item=b) => {
    "msg": "b"
}
ok: [host] => (item=d) => {
    "msg": "d"
}

I'm using ansible 2.10 with python 2.7.5:

ansible --version
ansible 2.10.2
  config file = /home/ansible.cfg
  configured module search path = [u'/home/ansible/library']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /bin/ansible
  python version = 2.7.5 (default, Apr  2 2020, 13:16:51) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]

The problem when I switch to python3, it is working as expected:

ok: [host] => (item=a) => {
    "msg": "a"
}
ok: [host] => (item=b) => {
    "msg": "b"
}
ok: [host] => (item=c) => {
    "msg": "c"
}
ok: [host] => (item=d) => {
    "msg": "d"
}

Unfortunately, I cannot upgrade the environment to python3 and I need the list to be in the same order as in the param.yml file.

Thank you!

sadok-f
  • 1,387
  • 15
  • 28

1 Answers1

3

Variable my_list is not a list. It's a dictionary. There is no guarantee in which order the keys of a dictionary will be iterated. Use sort filter. For example

    loop: "{{ my_list | list | sort }}"

Q: "I need to iterate over it in the same order as it is in the param.yml"

A: It's the wrong data structure for a use-case.YAML mapping s an unordered set. You can't "iterate over it in the same order" because there is no order. Use a list of keys. For example

    - debug:
        msg: "{{ item }}: {{ my_list[item] }}"
      loop: "{{ my_keys }}"
      vars:
        my_keys: [a,b,c,d]

gives (abridged)

  msg: 'a: val1'

  msg: 'b: val2'

  msg: 'c: val3'

  msg: 'd: val3'

Below is an example of a list's iteration. The task

    - debug:
        msg: "{{ item }}"
      loop: "{{ my_list }}"
      vars:
        my_list:
          - a: val1
          - b: val2
          - c: val3
          - d: val3

gives (abridged)

  msg:
    a: val1

  msg:
    b: val2

  msg:
    c: val3

  msg:
    d: val3
Vladimir Botka
  • 58,131
  • 4
  • 32
  • 63
  • Thank you for your reply, the problem `my_list` I cannot sort it, I need to iterate over it in the same order as it is in the `param.yml` file (I just simplified it here) – sadok-f Oct 07 '20 at 16:20
  • 1
    There is no solution to this problem. [YAML mapping s an **unordered set**](https://yaml.org/spec/1.2/spec.html#mapping//). i.e. You can't *"iterate over it in the same order"* because there is no order. – Vladimir Botka Oct 07 '20 at 16:30
  • thanks, this file contains dict of objects, and there's another automation that inserts into this file at the end, I need to get the last 10 objects inserted via ansible, converting it to list and get the last 10 wasn't usefully (due to this random order), any idea how I can accomplish that? – sadok-f Oct 07 '20 at 16:38
  • 1
    You'll have to parse the file on your own. – Vladimir Botka Oct 07 '20 at 16:49
  • @sadok-f building on this answer, what you can do is to have a dict containing both the value and a field you'd sort on (sorry that's the JSON notation, than fits better in the comment that the YAML one) e.g. `{'a': { 'value': 'val1', 'added_at': '2020-10-07 08:00:00' } }` and then sort on this `added_at` fields – β.εηοιτ.βε Oct 07 '20 at 16:53
  • thanks for your suggestion, I'd do that if the project is new or have few objects, but currently the yml file is quite huge and used by many components. I think I'll go to parse the file on my own and get the last objects. – sadok-f Oct 07 '20 at 19:11