How to parse a map?

I'm trying to create a list in ansible which consists of some docker container information. First, I'm running a command module which returns this in stdout:

"map[key1:value1 key2:value2 key3:value3]"

How can I parse this further to get the values based on the key that I provide? When I use a map filter, I get this:

"msg": "<generator object do_map at 0x7f3845b8a740>"

If I run the list filter, I just get output as every single character in the map, so ["m", "a", "p", "[", "k", ...]

What filter should I use?


Solution 1:

For example

    - set_fact:
        x: "{{ _dict|from_yaml }}"
      vars:
        _regex: '^(.*)\[(.*)\](.*)$'
        _key: "{{ stdout|regex_replace(_regex, '\\1') }}"
        _val: "{{ stdout|regex_replace(_regex, '\\2') }}"
        _dict: |
          {{ _key }}:
          {% for i in _val.split() %}
            {{ i|regex_replace(':', ': ') }}
          {% endfor %}

gives

  x:
    map:
      key1: value1
      key2: value2
      key3: value3

If there were more lines, e.g.

    stdout_lines:
      - "map1[key1:value1 key2:value2 key3:value3]"
      - "map2[key1:value1 key2:value2 key3:value3]"
      - "map3[key1:value1 key2:value2 key3:value3]"

it would be possible to combine the dictionary, e.g.

    - set_fact:
        x: "{{ x|d({})|combine(_dict|from_yaml) }}"
      loop: "{{ stdout_lines }}"
      vars:
        _regex: '^(.*)\[(.*)\](.*)$'
        _key: "{{ item|regex_replace(_regex, '\\1') }}"
        _val: "{{ item|regex_replace(_regex, '\\2') }}"
        _dict: |
          {{ _key }}:
          {% for i in _val.split() %}
            {{ i|regex_replace(':', ': ') }}
          {% endfor %}

gives

  x:
    map1:
      key1: value1
      key2: value2
      key3: value3
    map2:
      key1: value1
      key2: value2
      key3: value3
    map3:
      key1: value1
      key2: value2
      key3: value3

If the keys were repeating, e.g.

    stdout_lines:
      - "map[key1:value1 key2:value2 key3:value3]"
      - "map[key1:value1 key2:value2 key3:value3]"
      - "map[key1:value1 key2:value2 key3:value3]"

it would be possible to concatenate a list, e.g.

    - set_fact:
        x: "{{ x|d([]) + [_dict|from_yaml] }}"
      loop: "{{ stdout_lines }}"
      vars:
        _regex: '^(.*)\[(.*)\](.*)$'
        _key: "{{ item|regex_replace(_regex, '\\1') }}"
        _val: "{{ item|regex_replace(_regex, '\\2') }}"
        _dict: |
          {{ _key }}:
          {% for i in _val.split() %}
            {{ i|regex_replace(':', ': ') }}
          {% endfor %}

gives

  x:
  - map:
      key1: value1
      key2: value2
      key3: value3
  - map:
      key1: value1
      key2: value2
      key3: value3
  - map:
      key1: value1
      key2: value2
      key3: value3