Jinja2 template: output format
i am quite new to jinja2 template and i try to get output data by using jinja template.
data_list=
[
{
"v4-filter": {
"accept_1": [
{
"destination-prefix-list": "v4-future-prefix-list-1"
},
{
"source-prefix-list": "v4-future-prefix-list-2"
},
{
"source-prefix-list": "v4-future-prefix-list-3"
},
{
"destination-port": "80"
},
{
"destination-port": "443"
},
{
"action": "accept"
}
],
"accept_2": [
{
"destination-prefix-list": "v4-future-prefix-list4"
},
{
"source-prefix-list": "v4-future-prefix-list5"
},
{
"action": "accept"}]}}]
My jinja template
{%- for d in data_list -%}
{%- for k,v in d.items() -%}
{%- for term,value in v.items() -%}
term:: {{ term }}
{%- for dict_item in value -%}
{%- for key, value in dict_item.items() -%}
{% if key == "source-prefix-list" %}
source-address:: {{value}}
{% endif %}
{% if key == "destination-prefix-list" %}
destination-address:: {{value}}
{% endif %}
{% if key == "destination-port" %}
destination-port:: {{value}}
{% endif %}
{% if key == "action" %}
action:: {{value}}
{% endif %}
{%- endfor -%}
{%- endfor -%}
{%- endfor -%}
{%- endfor -%}
{%- endfor -%}
Output that i get
term:: accept_1
destination-address:: v4-future-prefix-list-1
source-address:: v4-future-prefix-list-2
source-address:: v4-future-prefix-list-3
destination-port:: 80
destination-port:: 443
action:: accept
term:: accept_2
destination-address:: v4-future-prefix-list4
source-address:: v4-future-prefix-list5
action:: accept
Output that i want
term accept_1 {
source-address:: v4-future-prefix-list-1
v4-future-prefix-list-2
v4-future-prefix-list-3
destination-port:: 80
443
action:: accept
}
term accept_2 {
source-address:: v4-future-prefix-list-5
destination-address:: v4-future-prefix-list-4
action:: accept
}
The jinja template looks not nice i know, but at the end it contains all the information that i need, is just question now to format properly as expected.
I tried by using nested if statement to properly reach the result but with no success.
Any hint is welcome. Thanks, Pablo.
Solution 1:
The following template will produce the requested output:
{%- for d in data_list -%}
{%- for k,v in d.items() -%}
{%- for term,value in v.items() -%}
{%- set label = namespace(source=false, dest=false, port=false) %}
term {{ term }} {
{%- for dict_item in value -%}
{%- for key, value in dict_item.items() -%}
{%- if key == "source-prefix-list" %}
{% if not label.source %}source-address::{% else %}{{ ' '*16 }}{% endif %} {{value}}
{%- set label.source = true %}
{%- endif %}
{%- if key == "destination-prefix-list" %}
{% if not label.dest %}destination-address::{% else %}{{ ' '*21 }}{% endif %} {{value}}
{%- set label.dest = true %}
{%- endif %}
{%- if key == "destination-port" %}
{% if not label.port %}destination-port::{% else %}{{ ' '*18 }}{% endif %} {{value}}
{%- set label.port = true %}
{%- endif %}
{%- if key == "action" %}
action:: {{value}}
{%- endif %}
{%- endfor %}
{%- endfor %}
}
{% endfor %}
{%- endfor %}
{%- endfor %}
Output:
term accept_1 {
destination-address:: v4-future-prefix-list-1
source-address:: v4-future-prefix-list-2
v4-future-prefix-list-3
destination-port:: 80
443
action:: accept
}
term accept_2 {
destination-address:: v4-future-prefix-list4
source-address:: v4-future-prefix-list5
action:: accept
}
Here we use a Jinja2 namespace object that we can use to track whether a label has been already printed or not in the current cycle. If a label is printed, we flip the boolean tracking variable in our label
namespace variable and then just print enough space to correctly align the next printed value.