4

I'm launching a setup playbook for a docker-compose service (apache solr) via extra vars. Those vars are set while executing since this playbook should be flexible and multiple configurations exists on one server.

My idea is, that the user can setup the variable in the ansible ui (ansible semaphore) as string:

  • Variable name project_cores
  • Variable value (string) main_en:english,main_de:german

I would like to iterate those cores as a dictionary. What I want at the end is:

{
  {
    name: main_en,
    language: english
  },
  {
    name: main_de,
    language: german
  },
}

The first step is to split them by , (this is already working):


- name: "debug: split cores"
  debug:
    msg: "{{ item }}"
  loop: "{{ project_cores.split(',') }}"

I tried then the following without success as this does not add the keys of the sub elements:


- name: "Extract solr cores configuration."
  set_fact:
    dict: "{{ dict|default({}) | combine ( { item.split(':')[0] : item.split(':')[1] } ) }}"
  with_items:
    - "{{ project_cores.split(',') }}"

I tested some combinations but does not find a working solution on how to add the keys.

Any idea how to convert that string to a real directory stated in the first example? thanks in advance!

Josef Glatz
  • 153
  • 4

1 Answers1

5

The below declaration

  project_cores_dict: "{{ dict(project_cores|
                               split(',')|
                               map('split',':')) }}"

gives what you want

  project_cores_dict:
    main_de: german
    main_en: english

  • Example of a complete playbook for testing
- hosts: localhost

  vars:

    project_cores: 'main_en:english,main_de:german'
    project_cores_dict: "{{ dict(project_cores|
                                 split(',')|
                                 map('split',':')) }}"

  tasks:

    - debug:
        var: project_cores_dict
  • Make the conversion more robust and trim the items
  project_cores_dict: "{{ dict(project_cores|
                               split(',')|map('trim')|
                               map('split',':')|map('map', 'trim')) }}"

Test it

    - debug:
        msg: |
          {{ pcd|to_yaml }}
      loop:
        - 'main_en:english,main_de:german'
        - 'main_en:english, main_de:german'
        - 'main_en: english, main_de:german'
      vars:
        pcd: "{{ dict(item|
                      split(',')|map('trim')|
                      map('split',':')|map('map', 'trim')) }}"

gives (abridged)

  msg: |-
    {main_de: german, main_en: english}
  msg: |-
    {main_de: german, main_en: english}
  msg: |-
    {main_de: german, main_en: english}

Without the trimming

    - debug:
        msg: |
          {{ pcd|to_yaml }}
      loop:
        - 'main_en:english,main_de:german'
        - 'main_en:english, main_de:german'
        - 'main_en: english,main_de:german'
      vars:
        pcd: "{{ dict(item|
                      split(',')|
                      map('split',':')) }}"

the spaces will become part of the keys and values

  msg: |-
    {main_de: german, main_en: english}
  msg: |-
    {' main_de': german, main_en: english}
  msg: |-
    {main_de: german, main_en: ' english'}
Vladimir Botka
  • 5,138
  • 8
  • 20
  • Thank you for you answer and the great examples/explanations!!! This works great for the actual need. May I ask you kindle if you can also extend your answer with an example where the dictionary has named keys like the following example? ```yaml {{ name: "main_de", language: "german" }, { name: "main_en", language: "english" }} ``` – Josef Glatz Aug 02 '23 at 07:05
  • It's not [YAML](https://www.yamllint.com/). If you want to pars anything, you must agree on a syntax first. – Vladimir Botka Aug 02 '23 at 11:09
  • OK lets rephase: is it possible to create a dict where the string before ":" is not the key but a value of a defined key? – Josef Glatz Aug 02 '23 at 13:22
  • What is preventing you from posting a [mre](https://stackoverflow.com/help/minimal-reproducible-example)? (Not in the comment, of course. Edit your question or open a new one). – Vladimir Botka Aug 02 '23 at 15:21
  • See [How do comments work?](https://meta.stackexchange.com/questions/19756/how-do-comments-work). In particular the part: `What are comments for, and when shouldn't I comment?` Comments are for 1) clarification 2) constructive criticism 3) minor or transient information. – Vladimir Botka Aug 02 '23 at 15:28