Search code examples
ansibleansible-facts

Concatenate value of item with replacing the dictionary in the list of dict


I have several lists of dictionaries with same key and different values. In loop, if key is identical but value is different, I would like to concatenate value with delimiter | and replace the current dictionary, selected with the right key, with the new one with the concatenate value.

Original List of dict

mylist:
  - name: openssh-server
    macros:
      - macro: SYSTEMD.NAME.SERVICE.MATCHES
        type: text
        value: sshd
  - name: apache2
    macros:
      - macro: SYSTEMD.NAME.SERVICE.MATCHES
        type: text
        value: apache2
      - macro: APACHE.STATUS.PORT
        type: text
        value: 9999

Expected concatenate list of dict

mylist updated with concatenated value (apache2|sshd) when the key of the dictionary is same but with different values.

mylist:                                                                                                                                                                                                                                          
  - macro: SYSTEMD.NAME.SERVICE.MATCHES                                                                                                                                                                                                                     
    type: text                                                                                                                                                                                                                                              
    value: apache2|sshd                                                                                                                                                                                                                                     
  - macro: APACHE.STATUS.PORT                                                                                                                                                                                                                               
    type: text                                                                                                                                                                                                                                              
    value: '9999'

Q: "Loop over mylist to check if the package is installed with when: item. name in ansible_facts.packages"

Q: "In addition, type can be other value than text and should be if possible, retrieve from mylist."


Solution

  • Q: "Concatenate value with delimiter |"

    A: For example

        - set_fact:
            my_list_con: "{{ my_list_con|d([]) + [{'macro': item.0,
                                                   'type': 'text',
                                                   'value': _value}] }}"
          loop: "{{ mylist|map(attribute='macros')|flatten|groupby('macro') }}"
          vars:
            _value: "{{ item.1|map(attribute='value')|unique|sort|join('|') }}"
    

    gives

      my_list_con:
      - macro: APACHE.STATUS.PORT
        type: text
        value: '9999'
      - macro: SYSTEMD.NAME.SERVICE.MATCHES
        type: text
        value: apache2|sshd
    

    Q: "Loop over mylist to check if the package is installed with when: item. name in ansible_facts.packages"

    A: Use selectattr. For example, given the list of the packages for testing

      ansible_facts.packages:
      - openssh-server
      - apache
    

    the task

        - set_fact:
            my_list_con: "{{ my_list_con|d([]) + [{'macro': item.0,
                                                   'type': 'text',
                                                   'value': _value}] }}"
          loop: "{{ mylist|
                    selectattr('name', 'in', ansible_facts.packages)|
                    map(attribute='macros')|flatten|groupby('macro') }}"
          vars:
            _value: "{{ item.1|map(attribute='value')|unique|sort|join('|') }}"
    

    gives

      my_list_con:
      - macro: SYSTEMD.NAME.SERVICE.MATCHES
        type: text
        value: sshd