Todd Lewis
Todd Lewis

Reputation: 91

ansible flattened map filter results

I'm using Ansible's map filter to extract data, but the output is a list of lists; what I need is a flattened list. The closest I've come is illustrated by the "energy.yml" playbook below. Invoke as

ansible-playbook ./energy.yml --extra-vars='src=solar'

---
- hosts: localhost
  vars:
    region: [ 'east', 'west' ]
    sources:   
      wind:
        east:
          filenames:
            - noreaster.txt
            - gusts.txt
            - drafty.txt
        west:
          filenames:
            - zephyr.txt
            - jetstream.txt
      solar:
        east:
          filenames:
            - sunny.txt
            - cloudy.txt
        west:
          filenames:
            - blazing.txt
            - frybaby.txt
            - skynuke.txt
    src: wind
  tasks:
  - name: Do the {{ src }} data
    debug:
      msg: "tweak file '/energy/{{src}}/{{ item[0] }}/{{ item[1] }}'."
    with_nested:
      - "{{ region }}"
      - "{{ 
            (region|map('extract',sources[src],'filenames')|list)[0] +
            (region|map('extract',sources[src],'filenames')|list)[1]
         }}"
    when: "item[1] in sources[src][item[0]].filenames"

The output of the map() filter is a number of lists the same length as "region". Jinja's "+" operator is the only mechanism I've found to join lists, but since it's a binary operator rather than a filter, I can't apply it to an arbitrary number of lists. The code above depends on "region" having length 2, and having to map() multiple times is ugly in the extreme.

Restructuring the data (or the problem) is not an option. The aspect I'd like to focus on is flattening the map() output, or some other way of generating the correct "msg:" lines the code above does

Upvotes: 2

Views: 4089

Answers (1)

Konstantin Suvorov
Konstantin Suvorov

Reputation: 68239

sum filter with start=[] is your friend:

region | map('extract',sources[src],'filenames') | sum(start=[])

From this:

[
    [
        "noreaster.txt",
        "gusts.txt",
        "drafty.txt"
    ],
    [
        "zephyr.txt",
        "jetstream.txt"
    ]
]

It will do this:

[
    "noreaster.txt",
    "gusts.txt",
    "drafty.txt",
    "zephyr.txt",
    "jetstream.txt"
]

Upvotes: 6

Related Questions