Home > OS >  Loop through a list of dicts containing list in Ansible?
Loop through a list of dicts containing list in Ansible?

Time:08-03

I have an Ansible Role which creates scheduled tasks that should install specific packages.

Used like this:

scheduled_install:

  - name: install package x,y,z on the same day
    package:
    - xpackage
    - ypackage
    - zpackage
    action: install
    day: '2022-08-08'
    time: '10:00:00'

  - name: install package a on another day
    package: apackage
    action: install
    day: '2022-10-12'
    time: '12:00:00'

It works fine if I only use one package per dictionary (apackage), I would like however to be able to add a list of packages.

(The task) With only one package I'm working like this:

- name: 'Scheduled Install'
  win_scheduled_task:
    name: Scheduled Install of {{ item.package }}
    actions:
      - path: powershell.exe
        arguments: choco install {{ item.package }}
    triggers:
      - type: time
        start_boundary: '{{ item.day }}T{{ item.time }}'
    username: SYSTEM
    state: present
    enabled: yes
  loop: "{{ scheduled_install }}"

Looping over "scheduled_install". I have tried using subelements: How to loop over this dictionary in Ansible? But I couldn't make it work or figure out how to correctly tie it together to get the desired output and didn't find a case too similar to mine.

I'm essentially looking for a way to loop over the data to get this:

"msg": "Package=xpackage, day=2022-08-08, time=10:00:00"
"msg": "Package=ypackage, day=2022-08-08, time=10:00:00"
"msg": "Package=zpackage, day=2022-08-08, time=10:00:00"
"msg": "Package=apackage, day=2022-10-12, time=12:00:00"

Ansible Version: 5.7.0

CodePudding user response:

Use with_subelements. Convert all attributes package to lists first. Create the lists

package_lists: "{{ scheduled_install|json_query('[].[package]')|
                                     map('flatten')|
                                     map('community.general.dict_kv', 'package')|
                                     list }}"

gives

package_lists:
  - package:
    - xpackage
    - ypackage
    - zpackage
  - package:
    - package

Combine the list of dictionaries

scheduled_install_lists: "{{ scheduled_install|zip(package_lists)|
                                               map('combine')|
                                               list }}"

gives

scheduled_install_lists:
  - action: install
    day: '2022-08-08'
    name: install package x,y,z on the same day
    package:
    - xpackage
    - ypackage
    - zpackage
    time: '10:00:00'
  - action: install
    day: '2022-10-12'
    name: install package a on another day
    package:
    - apackage
    time: '12:00:00'

Now you can iterate the dictionary

    - debug:
        msg: >-
          Package={{ item.1 }},
          day={{ item.0.day }},
          time={{ item.0.time }}
      with_subelements:
        - "{{ scheduled_install_lists }}"
        - package

gives (abridged)

  msg: Package=xpackage, day=2022-08-08, time=10:00:00
  msg: Package=ypackage, day=2022-08-08, time=10:00:00
  msg: Package=zpackage, day=2022-08-08, time=10:00:00
  msg: Package=apackage, day=2022-10-12, time=12:00:00

  • Example of a complete playbook
- hosts: localhost
  vars:
    scheduled_install:
      - name: install package x,y,z on the same day
        package:
          - xpackage
          - ypackage
          - zpackage
        action: install
        day: '2022-08-08'
        time: '10:00:00'
      - name: install package a on another day
        package: apackage
        action: install
        day: '2022-10-12'
        time: '12:00:00'
    package_lists: "{{ scheduled_install|json_query('[].[package]')|
                                         map('flatten')|
                                         map('community.general.dict_kv', 'package')|
                                         list }}"
    scheduled_install_lists: "{{ scheduled_install|zip(package_lists)|
                                                   map('combine')|
                                                   list }}"
  tasks:
    - debug:
        msg: >-
          Package={{ item.1 }},
          day={{ item.0.day }},
          time={{ item.0.time }}
      with_subelements:
        - "{{ scheduled_install_lists }}"
        - package
  • Related