Home > Mobile >  ansible looping from API using with_nested
ansible looping from API using with_nested

Time:04-12

i have ansible-playbook to loop ping from leaf router to spine. The ansible task was successfully executed, it can be seen as follows:

  - name: PING FROM LEAF TO SPINE
    shell: ping {{item[0]}} -c 2 -s {{item[2]}} | grep -i received | awk '{print "{{item[3]}} :\n"," {{item[1]}} :", $4}'
    register: p
    with_nested:
    - [ ['10.0.0.1','Spine-01'], ['10.0.0.2','Spine-02'] ]
    - [ ['10.0.0.3','Leaf-01'], ['10.0.0.6','Leaf-04'], ['10.0.0.9','Leaf-07'] ]

but instead of writing it manually, I want to call the device name and ip from a variable that holds all the data. The variable I have is called "get_devices" and contains data in the form of device name, device ip, and device type (spine/leaf). I'm new to Ansible, and I'm considering creating spine and leaf variables like this:

 - name: DEFINE VARIABLE SPINE
   set_fact: spine = "{{ item }}"
   loop: "{{ get_devices.json.results }}"
   when: "item.device_role.name == 'Spine'"

 - name: DEFINE VARIABLE LEAF
   set_fact: leaf = "{{ item }}"
   loop: "{{ get_devices.json.results }}"
   when: "item.device_role.name == 'Leaf'"

 - name: PING FROM LEAF TO SPINE
   shell: ping {{item[0]}} -c 2 -s {{item[2]}} | grep -i received | awk '{print "{{item[3]}} :\n"," {{item[1]}} :", $4}'
   register: p
   with_nested:
   - [ ' {{ spine.ip_address}} ','{{ spine.name }}' ]
   - [ ' {{ leaf.ip_address}} ','{{ leaf.name }}' ]

but, it resulted in an error like this :

fatal: [localhost]: FAILED! => {"msg": "'spine' is undefined"}

any idea how i can fix this? or if there are other ways to do this, please let me know. Thank you.

Edit : this is some part of the result of get_devices.json.results :

    {
        "name": "Leaf-Ganesha-CRCS-01",
        "ip_address": "10.0.0.3"
        "device_role": {
            "display": "Leaf",
            "name": "Leaf",
        }
    },
    {
        "name": "Leaf-02",
        "ip_address": "10.0.0.6"
        "device_role": {
            "display": "Leaf",
            "name": "Leaf",
        }
    },
    {
        "name": "Spine-01",
        "ip_address": "10.0.0.1"
        "device_role": {
            "display": "Spine",
            "name": "Spine",
        }
    },
    . . . 

CodePudding user response:

another answer following your logic and using product:

  tasks:
    - name: DEFINE VARIABLE SPINE
      set_fact: 
        spine: "{{ spine | d([])   [ {'name': item.name, 'ip': item.ip_address} ] }}"
      loop: "{{ get_devices.json.results }}"
      when: "item.device_role.name == 'Spine'"

    - name: DEFINE VARIABLE LEAF
      set_fact: 
        leaf: "{{ leaf | d([])   [ {'name': item.name, 'ip': item.ip_address} ] }}"
      loop: "{{ get_devices.json.results }}"
      when: "item.device_role.name == 'Leaf'"

    - name: PING FROM LEAF TO SPINE
      debug:
        msg: ping {{item.0.ip}} -c 2 -s {{item.1.ip}} | grep -i received | awk '{print "{{item.1.name}} :\n"," {{item.0.name}} :", $4}'
      register: p
      loop: "{{ spine | product(leaf)|list }}"

result:

"msg": "ping 10.0.0.1 -c 2 -s 10.0.0.3 | grep -i received | awk '{print \"Leaf-Ganesha-CRCS-01 :\\n\",\" Spine-01 :\", $4}'"

"msg": "ping 10.0.0.1 -c 2 -s 10.0.0.6 | grep -i received | awk '{print \"Leaf-02 :\\n\",\" Spine-01 :\", $4}'"

CodePudding user response:

Given the list

get_devices.json.results:
  - device_role:
      display: Leaf
      name: Leaf
    ip_address: 10.0.0.3
    name: Leaf-Ganesha-CRCS-01
  - device_role:
      display: Leaf
      name: Leaf
    ip_address: 10.0.0.6
    name: Leaf-02
  - device_role:
      display: Spine
      name: Spine
    ip_address: 10.0.0.1
    name: Spine-01

Group the routers and create the dictionaries

routers: "{{ dict(get_devices.json.results|groupby('device_role.name')) }}"
spine: "{{ routers.Spine|items2dict(key_name='name', value_name='ip_address') }}"
leaf: "{{ routers.Leaf|items2dict(key_name='name', value_name='ip_address') }}"

gives

  routers:
    Leaf:
    - device_role:
        display: Leaf
        name: Leaf
      ip_address: 10.0.0.3
      name: Leaf-Ganesha-CRCS-01
    - device_role:
        display: Leaf
        name: Leaf
      ip_address: 10.0.0.6
      name: Leaf-02
    Spine:
    - device_role:
        display: Spine
        name: Spine
      ip_address: 10.0.0.1
      name: Spine-01

  spine:
    Spine-01: 10.0.0.1

  leaf:
    Leaf-02: 10.0.0.6
    Leaf-Ganesha-CRCS-01: 10.0.0.3

Then iterate the nested lists of spine and leaf routers, e.g.

    - debug:
        msg: >-
          ping {{ item.0.value }} -c 2 -s {{ item.1.value }} |
          grep -i received |
          awk '{print "{{ item.1.key }} :\n"," {{ item.0.key }} :", $4}'
      with_nested:
        - "{{ spine|dict2items }}"
        - "{{ leaf|dict2items }}"

will create the commands

msg: ping 10.0.0.1 -c 2 -s 10.0.0.3 | grep -i received | awk '{print "Leaf-Ganesha-CRCS-01 :\n"," Spine-01 :", $4}'
msg: ping 10.0.0.1 -c 2 -s 10.0.0.6 | grep -i received | awk '{print "Leaf-02 :\n"," Spine-01 :", $4}'
  • Related