'Ansible: Is there a way to check for an IP address and return a subnet from a list, if present?
I am tasked in setting up a check to verify if an IP address is contained within a subnet, with Ansible.
I have set up a test playbook, where I have done the following:
tasks:
- name: "Include_vars"
include_vars:
file: /vlans.yml
- name: "Set_fact"
set_fact:
test_item "{{ item | string | split (':') | last }}"
loop: "{{ vlans }}"
Within the vlans.yml, the file contains a list of VLAN subnets, formatted like this:
vlans:
- "vlan-1-external:10.0.1.0/24"
- "vlan-2-internal:10.0.2.0/24"
[...]
The playbook manages - with a debug instruction - to split the given string and only return the subnet like 10.0.1.0/24.
My objective is to make the playbook evaluate every VLAN within the list, passing an IP as an argument, and returning the specific VLAN which contains that IP address.
I have looked into the ipaddr filter, but I cannot see any way to perform this kind of check.
Does anybody know a way to perform the check that I'm looking for?
Thanks in advance for any hints.
Solution 1:[1]
Q: "Verify if an IP address is contained within a subnet."
A: Test a list of the IP addresses in the loop, e.g.
- debug:
msg: "{{ item.0 }}: {{ test_list|ansible.netcommon.ipaddr(item.1) }}"
loop: "{{ vlans|map('split', ':')|list }}"
vars:
test_list:
- 10.0.1.99
- 10.0.2.99
- 10.0.3.99
gives (abridged)
msg: 'vlan-1-external: [''10.0.1.99'']'
msg: 'vlan-2-internal: [''10.0.2.99'']'
Optionally, convert the list to a dictionary first
vlans_subnet: "{{ dict(vlans|map('split', ':')) }}"
gives
vlans_subnet:
vlan-1-external: 10.0.1.0/24
vlan-2-internal: 10.0.2.0/24
Then, test a list of IP addresses in the loop
- debug:
msg: "{{ item.key }}: {{ test_list|ansible.netcommon.ipaddr(item.value) }}"
loop: "{{ vlans_subnet|dict2items }}"
vars:
test_list:
- 10.0.1.99
- 10.0.2.99
- 10.0.3.99
gives (abridged)
msg: 'vlan-1-external: [''10.0.1.99'']'
msg: 'vlan-2-internal: [''10.0.2.99'']'
Solution 2:[2]
Other than Vladimir's answer, there is another way to accomplish this:
First, set up a mapped list such as
vlans:
- name: "vlan-1-internal"
network: "192.168.1.0/24"
[...]
Then cycle through this list and use network_in_usable, in order to verify if the IP address is within such list. Then, convert it to a JSON object:
vlan:
{% set map = [] %}
{% for object in vlans %}
{%if (object.network | ansible.netcommon.network_in_usable(ip_to_check) ) %}
{% set x=map.append({
"name": object.name
"network": object.network
[...]
}) %}
{% endif %}
{% endfor %}
{{ map | to_json }}
Hope this helps.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Alessandro |
