Reference: jinja
Applies a filter on a sequence of objects or looks up an attribute. This is useful when dealing with lists of objects but you are really only interested in a certain value of it.
The basic usage is mapping on an attribute. Imagine you have a list of users but you are only interested in a list of usernames:
Users on this page:
{{ users|map(attribute='username')|join(', ') }}
Alternatively you can let it invoke a filter by passing the name of the filter and the arguments afterwards. A good example would be applying a text conversion filter on a sequence:
Users on this page: {{ titles|map('lower')|join(', ') }}
Examples
Reference: OzNetNerd.com
The code below passes the names
dictionary to the map
filter on four separate occasions to demonstrate the ways in which it can be used:
- hosts: localhost connection: local gather_facts: no vars: names: - first: Paul last: Thompson - first: Rod last: Johnson tasks: - debug: msg={{ names | map(attribute='first') | list }} - debug: msg={{ names | map(attribute='last') | list }} - debug: msg={{ names | map('upper') | list }} - debug: msg={{ names | map(attribute='last') | map('upper') | list }}
Output #1
In this run we see that the map(attribute='first')
filter prints the “first” values of the Key Value pairs:
TASK [debug] *******************************************************************
ok: [localhost] => {
"msg": [
"Paul",
"Rod"
]
}
Output #2
Similar to the previous run, we see that the map(attribute='last')
filter prints the “last” values of the Key Value pairs:
TASK [debug] *******************************************************************
ok: [localhost] => {
"msg": [
"Thompson",
"Johnson"
]
}
Output #3
This example differs from the previous two in that we’re passing the upper
Jinja filter to map
as opposed to an attribute:
TASK [debug] *******************************************************************
ok: [localhost] => {
"msg": [
"{U'LAST': U'THOMPSON', U'FIRST': U'PAUL'}",
"{U'LAST': U'JOHNSON', U'FIRST': U'ROD'}"
]
}
Output #4
This example demonstrates how we can chain two map
filters. Note that one is being passed an attribute while the other is being passed the upper
filter:
TASK [debug] *******************************************************************
ok: [localhost] => {
"msg": [
"THOMPSON",
"JOHNSON"
]
}
Cisco Example
The following Playbook uses map()
to extract interface information from Cisco devices:
- hosts: ""
connection: local
gather_facts: no
vars:
provider:
host: "{{ ansible_host }}"
username: ""
password: ""
platform: ""
tasks:
- name: ntc_show
ntc_show_command:
provider: ""
connection: ""
command: ""
secret: ""
register: results
- name: DEBUG - print original results
debug: msg=
- name: DEBUG - print extracted results
debug: msg={{ results.response | map(attribute='intf') | list }}
Running this Playbook results in the following output: ```
$ ansible-playbook interface_map.yml -i hosts.ini --extra-vars "hosts=gns3 username=cisco password=cisco connection=ssh platform=cisco_ios secret=cisco command='show ip interface brief'"
PLAY [gns3] ********************************************************************
TASK [ntc_show] ****************************************************************
ok: [R2]
ok: [R1]
TASK [DEBUG - print original results] ******************************************
ok: [R1] => {
"msg": {
"changed": false,
"response": [
{
"intf": "FastEthernet0/0",
"ipaddr": "192.168.0.210",
"proto": "up",
"status": "up"
},
{
"intf": "FastEthernet0/1",
"ipaddr": "unassigned",
"proto": "down",
"status": "administratively down"
}
],
"response_list": []
}
}
ok: [R2] => {
"msg": {
"changed": false,
"response": [
{
"intf": "FastEthernet0/0",
"ipaddr": "192.168.0.197",
"proto": "up",
"status": "up"
},
{
"intf": "FastEthernet0/1",
"ipaddr": "unassigned",
"proto": "down",
"status": "administratively down"
}
],
"response_list": []
}
}
TASK [DEBUG - print extracted results] *****************************************
ok: [R1] => {
"msg": [
"FastEthernet0/0",
"FastEthernet0/1"
]
}
ok: [R2] => {
"msg": [
"FastEthernet0/0",
"FastEthernet0/1"
]
}
PLAY RECAP *********************************************************************
R1 : ok=3 changed=0 unreachable=0 failed=0
R2 : ok=3 changed=0 unreachable=0 failed=0
Source
These Playbooks are available in the map() section of my Github repo.
As always, if you have any questions or have a topic that you would like me to discuss, please feel free to post a comment at the bottom of this blog entry, e-mail at will@oznetnerd.com, or drop me a message on Reddit (OzNetNerd).
Note: The opinions expressed in this blog are my own and not those of my employer.
Leave a comment