nrser
nrser

Reputation: 1307

how can i map a list to a dict with computed values keyed by the list items in ansible?

apologies for the awkward title, but i couldn't figure out a better way to phrase what seems like a very common operation:

i have a list like

repos:
- nrser/x
- nrser/y

and want to transform it to a dict like

repos_dict:
  nrser/x: nrser_x
  nrser/y: nrser_y

this is super simple in python

repos = ['nrser/x', 'nrser/y']
repos_dict = dict((repo, repo.replace('/', '_')) for repo in repos)
# => {'nrser/x': 'nrser_x', 'nrser/y': 'nrser_y'}

but i can't figure out how to accomplish it with Ansible / Jinja2 (short of dropping into python via a module or plugin, but that seems ridiculous for such a basic use case).

it's easy to map the repos to a new list with the underscored names (i need to use them in file paths)

set_fact:
  repo_filename_segments: "{{ repos | map('replace', '/', '_') | list }}"

but then i need zip them together, and i can't find support for that either (see ziplist1-list2-in-jinja2 and how-to-combine-two-lists-together)

i've tried:

- set_fact:
      repos:
      - beiarea/www
      - beiarea/relib

  - set_fact:
      repos_dict: {}

  - with_items: "{{ repos }}"
    set_fact:
      "repos_dict[{{ item }}]: "{{ item | replace('/', '_') }}"

but that doesn't work either.

maybe it's not possible in Ansible / Jinja, but it seems like a really elementary operation to have been overlooked.

thanks for any solutions or suggestions.

Upvotes: 5

Views: 7500

Answers (1)

Peter
Peter

Reputation: 31691

Ansible 2.3 adds (amongst others) a zip filter:

- set_fact:
    repos:
    - beiarea/www
    - beiarea/relib

- set_fact:
    dirnames: "{{ repos | zip(repos|map('replace', '/', '_')) | list }}"

- debug: var=dirnames

# "dirnames": [
#     [
#         "beiarea/www", 
#         "beiarea_www"
#     ], 
#     [
#         "beiarea/relib", 
#         "beiarea_relib"
#     ]
# ]

- debug:
    msg: "{{ item[0] }} => {{ item[1] }}"
  with_items:
  - "{{ dirnames }}" # with_items flattens the first level

I'm still looking for a good way to turn that into a dictionary, for easy lookups.

Upvotes: 3

Related Questions