I have this dictionary created by output from a test device:
"device_IPs": [
{
"INTERFACE": "Vlan300",
"IP_ADDRESS": "3.3.3.1",
"PROTO": "down",
"STATUS": "up"
},
{
"INTERFACE": "Vlan400",
"IP_ADDRESS": "4.4.4.1",
"PROTO": "down",
"STATUS": "up"
}
]
}
Basically i want to write a playbook that uses all of the INTERFACE values for another task - the task applies config to those vlan interfaces (derived from the INTERFACE value in the dict)
This is my playbook:
---
- name: run command and parse with textFSM
hosts: switches
gather_facts: no
tasks:
- name: show command and store in var
cisco.ios.ios_command:
commands: show ip interface brief | e una|Eth
register: sh_ip_int_br_output
- name: parse output data
ansible.builtin.set_fact:
device_IPs: "{{ sh_ip_int_br_output.stdout[0] | parse_cli_textfsm('testFSM_templates/ios_show_ip_int_br.textfsm') }}"
- name: add ip helper to vlan
cisco.ios.ios_config:
lines:
- ip helper-address 1.1.1.1
parents: "interface {{ each one of the INTERFACE values from dict }}"
How do I loop through each 'INTERFACE' key in the dictionary above, store the 'INTERFACE' value in a variable and loop through that later on in the last task ?
Hope that makes sense, Thanks
EDIT - this has been solved thanks to larsks & Vladimir's help
I added the following to my playbook
- name: extract data from dictionary list
set_fact:
dict_interface_info: "{{ device_IPs | map (attribute='INTERFACE') }}"
- name: add ip helper
cisco.ios.ios_config:
lines:
- ip helper-address 1.1.1.1
parents: "interface {{ item }}"
loop: "{{ dict_interface_info }}"
Don't think about loops; think about filters. The map
filter can be used to extract a particular attribute from a list of dictionaries, and we can use set_fact
to dynamically define new variables in a playbook:
- hosts: localhost
gather_facts: false
vars:
device_IPs: [
{
"INTERFACE": "Vlan300",
"IP_ADDRESS": "3.3.3.1",
"PROTO": "down",
"STATUS": "up"
},
{
"INTERFACE": "Vlan400",
"IP_ADDRESS": "4.4.4.1",
"PROTO": "down",
"STATUS": "up"
}
]
tasks:
- set_fact:
interfaces: "{{ device_IPs | map(attribute='INTERFACE') }}"
- debug:
var: interfaces
Running this produces as output:
TASK [debug] *********************************************************************************************************************************
ok: [localhost] => {
"interfaces": [
"Vlan300",
"Vlan400"
]
}