Reputation: 2986
Given a dictionary like:
- set_fact:
VARS: {foo: bar, baz: biz}
How can I turn this into a string of name=value
pairs, line-break-separated, preferably using filters, something like "{{ VARS | format(???) | join('\n') }}"
?
The desired result is the following string with line breaks:
foo=bar
baz=biz
I know I can use map()
to transform keys or values, but not both of them at once.
Upvotes: 1
Views: 6531
Reputation: 161
items
converts a dictionary into a list of [key, value]
lists and the nested lists can be flattened by map
ing join
over them.
This is the expression you need:
"{{ VARS | items | map('join', '=') | join('\n') }}"
[ ~]$ cd /tmp/
[ tmp]$
[ tmp]$ cat vars.yml
- hosts: all
gather_facts: false
tasks:
- set_fact:
VARS: {foo: bar, baz: biz}
- set_fact:
AS_SHELL: "{{ VARS | items | map('join', '=') | join('\n') }}"
- copy:
dest: /tmp/vars.txt
content: "{{AS_SHELL}}\n"
[ tmp]$ ansible-playbook -i localhost, -e ansible_connection=local vars.yml
PLAY [all] *************************************************************************************************************************************************
TASK [set_fact] ********************************************************************************************************************************************
ok: [localhost]
TASK [set_fact] ********************************************************************************************************************************************
ok: [localhost]
TASK [copy] ************************************************************************************************************************************************
changed: [localhost]
PLAY RECAP *************************************************************************************************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[ tmp]$ cat vars.txt
foo=bar
baz=biz
[ tmp]$ ansible-playbook --version
ansible-playbook [core 2.14.0]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.10/site-packages/ansible
ansible collection location = /home/user/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible-playbook
python version = 3.10.8 (main, Nov 1 2022, 14:18:21) [GCC 12.2.0] (/usr/bin/python)
jinja version = 3.1.2
libyaml = True
Upvotes: 2
Reputation: 1579
This problem is very similar to the following: Create a string using Jinja2 template
You could probably employ an similar solution to the one provided there. The following would give you your desired string with line breaks:
"{{ VARS | to_json | regex_replace('\\:\\ ','=') | regex_replace('[\\[\\]{}\\\"]') | regex_replace('\\,\\ ','\\n') }}"
This should give you a string like:
foo=bar
baz=biz
I'm not sure what you intend to use this output for but if you're intending to loop over this elsewhere in Ansible, for example, it may be more useful to split the string into a list of strings rather than using linebreaks. This could be done by using the following alternative:
{{ (VARS | to_json | regex_replace('\\:\\ ','=') | regex_replace('[\\[\\]{}\\\"]')).split(", ") }}
This will return a list like:
[ "foo=bar", "baz=biz" ]
Upvotes: 1