mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Add support for IOS vlan parsing filter. (#40555)
* Add support for IOS vlan parsing filter. Example usage below: {% set parsed_vlans = vlans | vlan_parser %} switchport trunk allowed vlan {{ parsed_vlans[0] }} {% for i in range (1, parsed_vlans | count) %} switchport trunk allowed vlan add {{ parsed_vlans[i] }} * Update test_network.py Add import statement for filter * Fixed PEP8 issues relating to comments * Fix PEP8 issues related to blank lines * Removed magic numbers for line lengths. This should generalize support to other IOS-like NOS that use similar methods for listing vlans. The default arguments for line lengths will still be specific to Cisco IOS. The unit tests for line length are still specific to Cisco IOS.
This commit is contained in:
parent
61ae6424a3
commit
ee6ab5d5aa
2 changed files with 95 additions and 2 deletions
|
@ -399,6 +399,79 @@ def comp_type5(unencrypted_password, encrypted_password, return_original=False):
|
|||
return False
|
||||
|
||||
|
||||
def vlan_parser(vlan_list, first_line_len=48, other_line_len=44):
|
||||
|
||||
'''
|
||||
Input: Unsorted list of vlan integers
|
||||
Output: Sorted string list of integers according to IOS-like vlan list rules
|
||||
|
||||
1. Vlans are listed in ascending order
|
||||
2. Runs of 3 or more consecutive vlans are listed with a dash
|
||||
3. The first line of the list can be first_line_len characters long
|
||||
4. Subsequent list lines can be other_line_len characters
|
||||
'''
|
||||
|
||||
# Sort and remove duplicates
|
||||
sorted_list = sorted(set(vlan_list))
|
||||
|
||||
if sorted_list[0] < 1 or sorted_list[-1] > 4094:
|
||||
raise AnsibleFilterError('Valid VLAN range is 1-4094')
|
||||
|
||||
parse_list = []
|
||||
idx = 0
|
||||
while idx < len(sorted_list):
|
||||
start = idx
|
||||
end = start
|
||||
while end < len(sorted_list) - 1:
|
||||
if sorted_list[end + 1] - sorted_list[end] == 1:
|
||||
end += 1
|
||||
else:
|
||||
break
|
||||
|
||||
if start == end:
|
||||
# Single VLAN
|
||||
parse_list.append(str(sorted_list[idx]))
|
||||
elif start + 1 == end:
|
||||
# Run of 2 VLANs
|
||||
parse_list.append(str(sorted_list[start]))
|
||||
parse_list.append(str(sorted_list[end]))
|
||||
else:
|
||||
# Run of 3 or more VLANs
|
||||
parse_list.append(str(sorted_list[start]) + '-' + str(sorted_list[end]))
|
||||
idx = end + 1
|
||||
|
||||
line_count = 0
|
||||
result = ['']
|
||||
for vlans in parse_list:
|
||||
# First line (" switchport trunk allowed vlan ")
|
||||
if line_count == 0:
|
||||
if len(result[line_count] + vlans) > first_line_len:
|
||||
result.append('')
|
||||
line_count += 1
|
||||
result[line_count] += vlans + ','
|
||||
else:
|
||||
result[line_count] += vlans + ','
|
||||
|
||||
# Subsequent lines (" switchport trunk allowed vlan add ")
|
||||
else:
|
||||
if len(result[line_count] + vlans) > other_line_len:
|
||||
result.append('')
|
||||
line_count += 1
|
||||
result[line_count] += vlans + ','
|
||||
else:
|
||||
result[line_count] += vlans + ','
|
||||
|
||||
# Remove trailing orphan commas
|
||||
for idx in range(0, len(result)):
|
||||
result[idx] = result[idx].rstrip(',')
|
||||
|
||||
# Sometimes text wraps to next line, but there are no remaining VLANs
|
||||
if '' in result:
|
||||
result.remove('')
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class FilterModule(object):
|
||||
"""Filters for working with output from network devices"""
|
||||
|
||||
|
@ -408,7 +481,8 @@ class FilterModule(object):
|
|||
'parse_xml': parse_xml,
|
||||
'type5_pw': type5_pw,
|
||||
'hash_salt': hash_salt,
|
||||
'comp_type5': comp_type5
|
||||
'comp_type5': comp_type5,
|
||||
'vlan_parser': vlan_parser
|
||||
}
|
||||
|
||||
def filters(self):
|
||||
|
|
|
@ -23,7 +23,8 @@ import sys
|
|||
import pytest
|
||||
|
||||
from units.compat import unittest
|
||||
from ansible.plugins.filter.network import parse_xml, type5_pw, hash_salt, comp_type5
|
||||
from ansible.plugins.filter.network import parse_xml, type5_pw, hash_salt, comp_type5, vlan_parser
|
||||
|
||||
from ansible.errors import AnsibleFilterError
|
||||
|
||||
fixture_path = os.path.join(os.path.dirname(__file__), 'fixtures', 'network')
|
||||
|
@ -165,3 +166,21 @@ class TestCompareType5(unittest.TestCase):
|
|||
encrypted_password = '$1$nTc1$Z28sUTcWfXlvVe2x.3XAa.'
|
||||
parsed = comp_type5(unencrypted_password, encrypted_password)
|
||||
self.assertEqual(parsed, False)
|
||||
|
||||
|
||||
class TestVlanParser(unittest.TestCase):
|
||||
|
||||
def test_compression(self):
|
||||
raw_list = [1, 2, 3]
|
||||
parsed_list = ['1-3']
|
||||
self.assertEqual(vlan_parser(raw_list), parsed_list)
|
||||
|
||||
def test_single_line(self):
|
||||
raw_list = [100, 1688, 3002, 3003, 3004, 3005, 3102, 3103, 3104, 3105, 3802, 3900, 3998, 3999]
|
||||
parsed_list = ['100,1688,3002-3005,3102-3105,3802,3900,3998,3999']
|
||||
self.assertEqual(vlan_parser(raw_list), parsed_list)
|
||||
|
||||
def test_multi_line(self):
|
||||
raw_list = [100, 1688, 3002, 3004, 3005, 3050, 3102, 3104, 3105, 3151, 3802, 3900, 3998, 3999]
|
||||
parsed_list = ['100,1688,3002,3004,3005,3050,3102,3104,3105,3151', '3802,3900,3998,3999']
|
||||
self.assertEqual(vlan_parser(raw_list), parsed_list)
|
||||
|
|
Loading…
Reference in a new issue