Why ansible parser can't understand that there is a variable?

Viewed 33

EDIT: Ok may be I couldn't explained it well so edit is below.


I have a list element that is filled with dict. items and looks like this:

"switch_vars": [
            {
                "leaf101": {
                    "node_id": "101", 
                    "node_name": "leaf101", 
                    "pod_id": "1"
                }, 
                "leaf102": {
                    "node_id": "102", 
                    "node_name": "leaf102", 
                    "pod_id": "1"
                }, 
                "spine103": {
                    "node_id": "103", 
                    "node_name": "spine103", 
                    "pod_id": "1"
                }
            }
        ]

When I try to access a value in a loop ansible says "'dict object' has no attribute 'why'".

- name: separate the pair leafs
  set_fact: 
    first_leaf:   "{{ item.split('-')[-2] }}"
    second_leaf:  "leaf{{ item.split('-')[-1] }}"

   #This task is ok and gives:

   #first_leaf:  "leaf101", 
   #second_leaf: "leaf102"

- name: a test 
  set_fact:
    test_var: "{{ switch_vars[0].why.node_id }}"
  loop:
    - first_leaf
    - second_leaf
  loop_control:
    loop_var: why

I expect to get 101 for the first loop and 102 for the second loop.


EDIT: I changed the list to the following

- name: get a dict.  
  set_fact:
    test_var: "{{ switch_vars | items2dict }}"

which gave me:

        "test_var": {
            "leaf101": {
                "node_id": "101", 
                "node_name": "leaf101", 
                "pod_id": "1"
            }, 
            "leaf102": {
                "node_id": "102", 
                "node_name": "leaf102", 
                "pod_id": "1"
            }, 
            "spine201": {
                "node_id": "201", 
                "node_name": "spine201", 
                "pod_id": "1"
            }
        }

when I try to access the attribute of an element I try the following:

- debug:
    msg:
      - "{{ first_leaf }} #-->this is ok and gives as expected leaf101
- debug:
    msg:
      - "{{ test_var.first_leaf.node_id }}"

This task gives the error that the dict object has no attribute "first_leaf"

So my problem here is a templating problem but I don't know how to overcome it.


1 Answers

The variable switch_vars is a list with one item. See it in YAML format below

switch_vars:
  - leaf101:
      node_id: '101'
      node_name: leaf101
      pod_id: '1'
    leaf102:
      node_id: '102'
      node_name: leaf102
      pod_id: '1'
    spine103:
      node_id: '103'
      node_name: spine103
      pod_id: '1'

If you want to get the values of the attribute node_id from the first two 'leafs' of the first item (there is only one item atm) the declarations below

    first_leaf: "{{ switch_vars.0.leaf101.node_id }}"
    second_leaf: "{{ switch_vars.0.leaf102.node_id }}"

give

    first_leaf: 101
    second_leaf: 102

If you want to iterate the first two 'leafs' declare the below variables

    first_leaf_i: "{{ item.leaf101.node_id }}"
    second_leaf_i: "{{ item.leaf102.node_id }}"

Then, the loop (there might be more items)

    - debug:
        msg: "1st: {{ first_leaf_i }} 2nd: {{ second_leaf_i }}"
      loop: "{{ switch_vars }}"

gives (abridged)

  msg: '1st: 101 2nd: 102'

A completely another category of parsing is json_query. For example,

    leafs_id: "{{ switch_vars|json_query('[].*.node_id') }}"

gives

leafs_id:
  - - '101'
    - '102'
    - '103'

Example of a complete playbook for testing

- hosts: localhost

  vars:

    switch_vars:
      - leaf101:
          node_id: '101'
          node_name: leaf101
          pod_id: '1'
        leaf102:
          node_id: '102'
          node_name: leaf102
          pod_id: '1'
        spine103:
          node_id: '103'
          node_name: spine103
          pod_id: '1'

    first_leaf: "{{ switch_vars.0.leaf101.node_id }}"
    second_leaf: "{{ switch_vars.0.leaf102.node_id }}"

    first_leaf_i: "{{ item.leaf101.node_id }}"
    second_leaf_i: "{{ item.leaf102.node_id }}"

    leafs_id: "{{ switch_vars|json_query('[].*.node_id') }}"

  tasks:

    - debug:
        var: switch_vars

    - debug:
        msg: |
          first_leaf: {{ first_leaf }}
          second_leaf: {{ second_leaf }}

    - debug:
        msg: "1st: {{ first_leaf_i }} 2nd: {{ second_leaf_i }}"
      loop: "{{ switch_vars }}"

    - debug:
        var: leafs_id

Q: "Error that the dict object has no attribute first_leaf."

first_leaf: leaf101
result: "{{ test_vars.first_leaf.node_id }}"

A: Reference to the first item is missing and indirect reference must be closed in brackets

result: "{{ test_vars.0[first_leaf].node_id }}"
Related