Reputation: 983
I want to convert this variable:
default_attr:
attr1 :
- "1"
nexatt :
- "b"
...
to "attr=1,nextattr=b,..." (i.e.comma separated string) using Jinja template. Is there a possible way to do this?
- name: Reading the attributes
set_fact:
app_attributes: |
{% set attributes = " " -%}
{% for key in default_attr.keys() -%}
{% for value in default_attr[key] -%}
{% attributes: "{{ attributes }} + [{'key=value'}]" -%}
{%- endfor %}
{%- endfor %}
{{ attributes }}
The error I get is shown below:
fatal: [dev1]: FAILED! => {"msg": "template error while templating string: Encountered unknown tag 'attributes'. Jinja was looking for the following tags: 'endfor' or 'else'. The innermost block that needs to be closed is 'for'.. String: {% set attributes = \" \" -%}\n{% for key in default_attr.keys() -%}\n {% for value in default_attr[key] -%}\n {% attributes: \"{{ attributes }} + [{'key=value'}]\" -%}\n {%- endfor %}\n{%- endfor %}\n{{ attributes }}\n"}
Is there a way to construct this string using Jinja?
Upvotes: 0
Views: 2709
Reputation: 161
It doesn't really make sense to try to have those extraneous -
s in your input. They mean the values are lists and like @Kanwar said almost any answer we could give will only work if there's only one item in each list. To see why, imagine you had
default_attr:
attr1 :
- "1"
nexatt :
- "b"
- "c"
- "d"
then what should come out? attr1=1,nextatt=b,nextatt=c,nextatt=d
? attr1=1,nextatt=d
? attr1=1,nextatt=b
? It's not clearly defined.
Judging from your goal, I'm going to assume you meant to ask about this object instead:
default_attr:
attr1 : "1"
nexatt : "b"
and in this case you can do this with one line of filters instead of a template:
"{{ default_attr | items | map('join', '=') | join(',') }}"
items
converts a dictionary into a list of [key, value]
lists and the nested lists can be flattened by map
ing join
over them, which makes a list of strings, and the final join
flattens that list to a single string.
This will produce
"attr1=1,nexatt=b"
Upvotes: 1
Reputation: 11
You can construct a list of the key/value pairs and then join them as needed:
- hosts: localhost
connection: local
gather_facts: no
vars:
the_dict:
My: Dog
Has: Fleas
tasks:
- name: Convert the dict to a list of key=value elements
ansible.builtin.set_fact:
kv_list: "{{ kv_list | default([]) | union([[item.key, item.value] | join('=')]) }}"
loop: "{{ the_dict | dict2items }}"
- name: Print out a comma-separated string
ansible.builtin.debug:
msg: "{{ kv_list | join(',') }}"
This produces "msg": "My=Dog,Has=Fleas"
Upvotes: 1
Reputation: 2327
Its a bit dirty way but for the sake of answer the snippet below should work for what you have described. One problem is that you have not specified that what will happen when there are more than one items in attr1
or any other attr
list. This snippet will work if there is only one item in each list.
- set_fact:
default_attr:
attr1 :
- "1"
nexatt :
- "b"
- set_fact: app_attributes="{{ default_attr | to_json | regex_replace('\:\ ','=') | regex_replace('[\[\]{}\"]') }}"
- debug: var=app_attributes
Upvotes: 2