DDStackoverflow
DDStackoverflow

Reputation: 643

How to format a dict to a string in ansible

I want to format a dict in ansible like so,

from

{'a': 1, 'b': 2, 'c': 3}

to

'a=1,b=2,c=3'

and have to set it as an environment variable in a block like so,

vars:
  test_env:
    a: 1
    b: 2
    c: 3

- block:
    # tasks
  environment:
    SOME_ENV: 'a=1,b=2,c=3'

here I want to convert test_env dict to 'a=1,b=2,c=3' I can not set the fact to modify the dict and then set it to the SOME_ENV because environment is a different clause, maybe I can modify the dict in the vars clause but is there any other solution?

Upvotes: 3

Views: 11485

Answers (1)

Vladimir Botka
Vladimir Botka

Reputation: 68394

Decompose the dictionary to the lists of keys and values. Then zip the lists and join the items. For example,

    - block:
        - command: echo $SOME_ENV
          register: result
        - debug:
            var: result.stdout
      environment:
        SOME_ENV: "{{ test_env.keys()|
                      zip(test_env.values())|
                      map('join', '=')|
                      join(',') }}"

give

  result.stdout: a=1,b=2,c=3

update

There are more options. You can also use Jinja or JMESPath. The below expressions give the same result

  SOME_ENV: |-
    {%- for k,v in test_env.items() %}
    {{ k }}={{ v }}{% if not loop.last %},{% endif %}
    {%- endfor %}
  SOME_ENV: "{{ test_env|dict2items|
                json_query('[].join(`=`, [key, to_string(value)])')|
                join(',') }}"

Example of a complete playbook for testing

- hosts: all

  vars:

    test_env:
      a: 1
      b: 2
      c: 3

  tasks:

    - block:

        - command: "echo ${{ item }}"
          register: result
          loop: [SOME_ENV, SOME_EN2, SOME_EN3]

        - debug:
            msg: "{{ result.results|
                     items2dict(key_name='item', value_name='stdout') }}"

      environment:

        SOME_ENV: "{{ test_env.keys()|
                      zip(test_env.values())|
                      map('join', '=')|
                      join(',') }}"

        SOME_EN2: |-
          {%- for k,v in test_env.items() %}
          {{ k }}={{ v }}{% if not loop.last %},{% endif %}
          {%- endfor %}

        SOME_EN3: "{{ test_env|dict2items|
                      json_query('[].join(`=`, [key, to_string(value)])')|
                      join(',') }}"

gives (abridged)

  msg:
    SOME_EN2: a=1,b=2,c=3
    SOME_EN3: a=1,b=2,c=3
    SOME_ENV: a=1,b=2,c=3

Upvotes: 8

Related Questions