I am trying to create set of templates with names and its content created dynamically based on certain list and dictionary.
Part of the code that is causing the issue is below.
{% for tenant in object_list %}
{%- set name = 'object_t' + tenant + 'rules' %}
{{name}}:
- permit ip any {{ tenant_public_ip['object_t' + tenant | string +'_pub'['Subnets'][0] }}
{% endfor %}
# combine acls
complete_acls:
- name: DEFAULT_ACL
rules: {{'"{{ default_rules }}"'}}
{% for tenant in object_list %}
{% set item= 'object_t' + tenant + 'rules' %}
- name: Tenant_{{tenant}}_ACCESS-VLANS
rules: {{"{{item}}"}}
{% endfor %}
Got error: template error while templating string: expected token ',', got '{'.
Parameters being parsed:
object_list: [1, 2, 3, 4, 5]
tenant_public_ip: {u''object_t5_pub'': {u''Subnets'': [u''8.51.14.124/28''], u''Vlan_id'': u''5010''}, u''object_t2_pub'': {u''Subnets'': [u''8.51.14.128/28''], u''Vlan_id'': u''2010''}, u''object_t4_pub'': {u''Subnets'': [u''8.51.14.176/28''], u''Vlan_id'': u''4100''}, u''object_t1_pub'': {u''Subnets'': [u''8.51.14.160/28''], u''Vlan_id'': u''1100''}, u''object_t3_pub'': {u''Subnets'': [u''8.51.14.144/28''], u''Vlan_id'': u''3100''}} '
I am new to Jinja2 templating, what am i doing wrong?
One other issue that i ran into after initial one was when combining all the rules at the bottom after adding several modules like above.
I get the rules as the 'item' variable name split into letters - "o, b, j, e, c, t" instead of gathering the rules that were created earlier that were stored under "object_t_1rules" for example. I can access them individually by directly using a specific name that they were created with but not using a for loop. I know Jinja2 does not allow nested variable access. How else can i achieve what i want here ?
You have more than one error in your template/code, on the following lines to be precise:
{%- set name = 'object_t' + tenant + 'rules' %}
- permit ip any {{ tenant_public_ip[ip_{{tenant}}_pub][Subnets][0] }}
Firstly, tenant
is an integer, and you're trying to put it betwixt two strings. Jinja is less forgiving than vanilla Python, so you need a filter:
{%- set name = 'object_t' + tenant | string + 'rules' %}
Secondly, Subnets
should be a string; however, you're trying to access an object called Subnets
(because of the lack of apostrophes):
- permit ip any {{ tenant_public_ip[ip_{{tenant}}_pub]['Subnets'][0] }}
Thirdly, you don't need the {{
and }}
that are wrapped around tenant
:
- permit ip any {{ tenant_public_ip[ip_tenant_pub]['Subnets'][0] }}
And finally, your tenant_public_ip
example dictionary does not contain any keys called ip_<integer>_pub
, only object_t<integer>_pub
. In order for your code to work as intended, either modify your dictionary to this:
tenant_public_ip: {'ip_1_pub': {'Subnets': ...}, ...}
Or modify your template to this:
- permit ip any {{ tenant_public_ip['object_t' + tenant | string + '_pub']['Subnets'][0] }}
Personally, I'd choose the former (modifying the template).