Home > Software engineering >  Ansible - Convert a list inside a dictionary to a list of dictionaries, then put it in a play
Ansible - Convert a list inside a dictionary to a list of dictionaries, then put it in a play

Time:12-03

I will start by saying exactly what I am trying to achieve in case there is a better way of doing this altogether.

I am trying to use the 'redhat.satellite.content_view' Ansible module which is documented under 'theforeman.foreman.content_view' Ansible module to read the below variable and loop over it with idempotence.

composite_content_views:
  - name: 'ccv-number1'
    content_views:
      - 'cv-number1'
      - 'cv-number2'
  - name: 'ccv-number2'
    content_views:
      - 'cv-number3'
      - 'cv-number4'
      - 'cv-number5'

The end result I am trying to achieve is the below but using only the variables from above with a loop.

- name: create composite content views
  redhat.satellite.content_view:
    name: ccv-number1
    composite: true
    components:
      - content_view: 'cv-number1'
        latest: true
      - content_view: 'cv-number2'
        latest: true

then

- name: create composite content views
  redhat.satellite.content_view:
    name: ccv-number2
    composite: true
    components:
      - content_view: 'cv-number3'
        latest: true
      - content_view: 'cv-number4'
        latest: true
      - content_view: 'cv-number5'
        latest: true

I have been really scratching my head on this after trying various things so any help would be hugely appreciated. :)

I have tried loops with various filters to try and have something like the below but have not managed to get it to work.

- name: create composite content views
  redhat.satellite.content_view:
    name: "{{ item.name }}" 
    composite: true
    components: "{{ list of dictionaries here with only the 'cv-numberX' values changing }}"

CodePudding user response:

In each iteration declare

  components: "{{ item.content_views|
                  map('community.general.dict_kv', 'content_view')|
                  map('combine', {'latest': true})|
                  list }}"

gives

  components:
    -   content_view: cv-number1
        latest: true
    -   content_view: cv-number2
        latest: true

and

  components:
    -   content_view: cv-number3
        latest: true
    -   content_view: cv-number4
        latest: true
    -   content_view: cv-number5
        latest: true

Example of a complete playbook for testing

- hosts: localhost

  vars:

    composite_content_views:
      - name: ccv-number1
        content_views:
          - cv-number1
          - cv-number2
      - name: ccv-number2
        content_views:
          - cv-number3
          - cv-number4
          - cv-number5

  tasks:

    - debug:
        msg: |
          name: {{ item.name }}
          composite: true
          components:
          {{ components|to_nice_yaml }}
      loop: "{{ composite_content_views }}"
      vars:
        components: "{{ item.content_views|
                        map('community.general.dict_kv', 'content_view')|
                        map('combine', {'latest': true})|
                        list }}"

Example of the task

    - name: create composite content views
      redhat.satellite.content_view:
        name: "{{ item.name }}"
        composite: true
        components: "{{ components }}"
      loop: "{{ composite_content_views }}"
      vars:
        components: "{{ item.content_views|
                        map('community.general.dict_kv', 'content_view')|
                        map('combine', {'latest': true})|
                        list }}"

The Jinja template gives the same results

        components: |
          [{% for i in item.content_views %}
          {"content_view": "{{ i }}", "latest": "true"},
          {% endfor %}]
  • Related