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?
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