Search code examples
variablesansiblejinja2

Nested variable in Ansible referencing a list


I'm hoping to get some guidance on the following code which involves a nested variable in Ansible. Here's the playbook:

---
- name: Testing
  hosts: localhost
  connection: local
  gather_facts: false

  vars:
    hostname: HOST1
    VLAN_DEFS: [
        {
            "TAG": "1001",
            "HOST1_DATA_IP": "10.10.0.1",
            "HOST2_DATA_IP": "10.20.0.1",
            "DATA_NETMASK": "24"
        },
        {
            "TAG": "1002",
            "HOST1_DATA_IP": "10.10.0.2",
            "HOST2_DATA_IP": "10.20.0.2",
            "DATA_NETMASK": "24"
        },
        {
            "TAG": "1003",
            "HOST1_DATA_IP": "10.10.0.3",
            "HOST2_DATA_IP": "10.20.0.3",
            "DATA_NETMASK": "24"
        }
    ]

  tasks:

    - template:
        src: ./test.j2
        dest: ./output.json

And here is the test.j2 Jinja template:

[
{% for VLAN in VLAN_DEFS %}

    {
        "VLAN": "VLAN{{ VLAN.TAG }}",
        "ADDRESS": "{{ lookup('vars', 'VLAN.' ~ hostname ~ '_DATA_IP') }}/{{ VLAN.DATA_NETMASK }}"
    }{% if not loop.last %},{% endif %}
{% endfor %}

]

The lookup line I'm using appears to give me what I want which is VLAN.HOST1_DATA_IP, but it's not being interpreted as a valid variable. The result of my playbook is the error "No variable found with this name: VLAN.HOST1_DATA_IP." However, if I replace the ADDRESS line with that exact value as illustrated below, it works fine:

"ADDRESS": "{{ VLAN.HOST1_DATA_IP }}/{{ VLAN.DATA_NETMASK }}"

Does anyone by chance have some insight into why this error is occurring?


Solution

  • You don't need to use a vars lookup. Instead of var.attribute, use var[attribute], which allows to build the attribute name with an expression, like this:

    [
    {% for VLAN in VLAN_DEFS %}
        {
            "VLAN": "VLAN{{ VLAN.TAG }}",
            "ADDRESS": "{{ VLAN[hostname ~ '_DATA_IP'] }}/{{ VLAN.DATA_NETMASK }}"
        }{% if not loop.last %},{% endif %}
    {% endfor %}
    
    ]
    

    Which produces:

    [
        {
            "VLAN": "VLAN1001",
            "ADDRESS": "10.10.0.1/24"
        },    {
            "VLAN": "VLAN1002",
            "ADDRESS": "10.10.0.2/24"
        },    {
            "VLAN": "VLAN1003",
            "ADDRESS": "10.10.0.3/24"
        }
    ]