Search code examples
pythonloopstemplatesyamljinja2

build new variables in Jinja2 Loop and use it


I have a file containing a YAML document, with informations about vlans:

#yaml_file.yaml
- vlan: 123
  name: DATEN-VLAN
- vlan: 124
  name: PRINTER-VLAN
- vlan: 125
  name: WLAN-VLAN

Then I created a Jinja2Template to loop through the vlans:

{% for vlan in vlans %}
    interface {{INTERFACE}}.{{vlan['vlan']}}
    description {{vlan['name']}}
    ip address {{'V_VLAN_IP_' ~ vlan['vlan']}}
{% endfor %}

I render the template with the following code in Python:

template = template.render(
    vlans=vlans,
    INTERFACE="Gi0/1",
    V_LAN_IP_123="192.168.100.1",
    V_LAN_IP_124="192.168.200.1",
    V_LAN_IP_125="192.168.300.1"
)

In the loop I am trying to create dynamically a new variable for each loop with the following line: ip address {{'V_VLAN_IP_' ~ vlan['vlan']}}

The Outuput looks like this:

    interface Gi0/1.123
    description DATEN-VLAN
    ip address V_VLAN_IP_123

    interface Gi0/1.124
    description PRINTER-VLAN
    ip address V_VLAN_IP_124

    interface Gi0/1.125
    description WLAN-VLAN
    ip address V_VLAN_IP_125

But that is not, I am goaling for. I want that the created variable is used and the value is replaced by the given informations in the render call in the python-script. So "V_VLAN_IP_123" should be replaced by "192.168.100.1", "V_VLAN_IP_124" by "192.168.200.1" and "V_VLAN_IP_125" by "192.168.300.1".

My output should look like this:

    interface Gi0/1.123
    description DATEN-VLAN
    ip address 192.168.100.1

    interface Gi0/1.124
    description PRINTER-VLAN
    ip address 192.168.200.1

    interface Gi0/1.125
    description WLAN-VLAN
    ip address 192.168.300.1

I tried several things to concatenate the variable.


Solution

  • Pass the IPs as a dict so you don't need to think about "variable variables":

    import jinja2
    import yaml
    
    vlans = yaml.safe_load(
        """
    - vlan: 123
      name: DATEN-VLAN
    - vlan: 124
      name: PRINTER-VLAN
    - vlan: 125
      name: WLAN-VLAN
    """
    )
    
    templ = jinja2.Template(
        """
    {% for vlan in vlans %}
        interface {{INTERFACE}}.{{vlan['vlan']}}
        description {{vlan['name']}}
        ip address {{ips[vlan['vlan']]}}
    {% endfor %}
    """.strip()
    )
    
    print(
        templ.render(
            INTERFACE="Gi0/1",
            vlans=vlans,
            ips={
                123: "192.168.100.1",
                124: "192.168.200.1",
                125: "192.168.300.1",
            },
        )
    )
    

    outputs

    
        interface Gi0/1.123
        description DATEN-VLAN
        ip address 192.168.100.1
    
        interface Gi0/1.124
        description PRINTER-VLAN
        ip address 192.168.200.1
    
        interface Gi0/1.125
        description WLAN-VLAN
        ip address 192.168.300.1