I am trying to write data to a yaml file using a jinja2 template and python. Below is the jinja2 template
Jinja2 template:
name: eos-lab
topology:
nodes:
{{ switch_name }}:
kind: ceos
image: ceos:4.30.3M
binds:
- {{ switch_name }}.txt.json:/mnt/flash/EosIntfMapping.json:ro
Tried the below python code
import yaml
import jinja2
i = [{"switch_name": "a"}, {"switch_name": "b"}]
template_file = "eos-test-sb.clab.j2"
env = jinja2.Environment(loader=jinja2.FileSystemLoader(searchpath="."))
template = env.get_template(template_file)
for device in i:
result = template.render(device)
print(result)
This gives me output as
name: eos-lab
topology:
nodes:
a:
kind: ceos
image: ceos:4.30.3M
binds:
- a.txt.json:/mnt/flash/EosIntfMapping.json:ro
name: eos-lab
topology:
nodes:
b:
kind: ceos
image: ceos:4.30.3M
binds:
- b.txt.json:/mnt/flash/EosIntfMapping.json:ro
Desired Output:
name: eos-lab
topology:
nodes:
a:
kind: ceos
image: ceos:4.30.3M
binds:
- a.txt.json:/mnt/flash/EosIntfMapping.json:ro
b:
kind: ceos
image: ceos:4.30.3M
binds:
- b.txt.json:/mnt/flash/EosIntfMapping.json:ro
Any suggestions greatly appreciated
The "right" (IMHO) way of handling a for loop in the Jinja template is... in the Jinja template itself, which is very capable of using for
loops (see the docs) and of accessing dictionaries (see this other tutorial)
With that in mind, modify the template to iterate over your list of devices:
Option 1)
name: eos-lab
topology:
nodes:
{% for device in devices %}
{{ device.switch_name }}:
kind: ceos
image: ceos:4.30.3M
binds:
- {{ device.switch_name }}.txt.json:/mnt/flash/EosIntfMapping.json:ro
{% endfor %}
Option 2)
name: eos-lab
topology:
nodes:
{% for device in devices %}
{{ device['switch_name'] }}:
kind: ceos
image: ceos:4.30.3M
binds:
- {{ device['switch_name'] }}.txt.json:/mnt/flash/EosIntfMapping.json:ro
{% endfor %}
Notice the only difference in those two snippets of code is just how the device
dictionary is read: either device.switch_name
or device['switch_name']
. As per the docs:
You can use a dot (.) to access attributes of a variable in addition to the standard Python getitem “subscript” syntax ([]).
The following lines do the same thing:
{{ foo.bar }}
{{ foo['bar'] }}
Now your code just has to tell the renderer what devices
is:
import jinja2
devices = [{"switch_name": "a"}, {"switch_name": "b"}]
template_file = "eos-test-sb.clab.j2"
env = jinja2.Environment(loader=jinja2.FileSystemLoader(searchpath="."))
template = env.get_template(template_file)
result = template.render(devices=devices)
print(result)
And you'll see:
name: eos-lab
topology:
nodes:
a:
kind: ceos
image: ceos:4.30.3M
binds:
- a.txt.json:/mnt/flash/EosIntfMapping.json:ro
b:
kind: ceos
image: ceos:4.30.3M
binds:
- b.txt.json:/mnt/flash/EosIntfMapping.json:ro