From c55fe93e16239b7b3b62c5487fa91eb33e1a3a13 Mon Sep 17 00:00:00 2001 From: Pim van Pelt Date: Sun, 20 Mar 2022 22:41:19 +0000 Subject: [PATCH] Add unit tests for bridgedomain - move is_bridge_interface*() functions to validator/bridgedomain.py --- unittest/test_bridgedomain.yaml | 56 +++++++++++++++++++++++++++++++++ validator/bridgedomain.py | 28 ++++++++++++++++- validator/interface.py | 33 +++---------------- validator/test_bridgedomain.py | 25 +++++++++++++++ 4 files changed, 112 insertions(+), 30 deletions(-) create mode 100644 unittest/test_bridgedomain.yaml create mode 100644 validator/test_bridgedomain.py diff --git a/unittest/test_bridgedomain.yaml b/unittest/test_bridgedomain.yaml new file mode 100644 index 0000000..cce8e59 --- /dev/null +++ b/unittest/test_bridgedomain.yaml @@ -0,0 +1,56 @@ +bondethernets: + BondEthernet0: + interfaces: [ GigabitEthernet3/0/0, GigabitEthernet3/0/1 ] + +interfaces: + GigabitEthernet1/0/0: + mtu: 3000 + GigabitEthernet1/0/1: + mtu: 3000 + + GigabitEthernet2/0/0: + mtu: 9000 + sub-interfaces: + 100: + mtu: 2000 + GigabitEthernet2/0/1: + mtu: 9000 + sub-interfaces: + 100: + mtu: 2000 + + GigabitEthernet3/0/0: + mtu: 9000 + sub-interfaces: + 100: + description: "Also not in a bridgedomain" + GigabitEthernet3/0/1: + mtu: 9000 + + GigabitEthernet4/0/0: + mtu: 9000 + GigabitEthernet4/0/1: + mtu: 9000 + + BondEthernet0: + mtu: 3000 + sub-interfaces: + 100: + mtu: 2000 + +bridgedomains: + bd10: + description: "Bridge Domain 10" + mtu: 3000 + interfaces: [ GigabitEthernet1/0/0, GigabitEthernet1/0/1, BondEthernet0 ] + bd11: + description: "Bridge Domain 11, both LCP and address" + mtu: 2000 + interfaces: [ GigabitEthernet2/0/0.100, GigabitEthernet2/0/1.100, BondEthernet0.100 ] + lcp: "bvi123456789012" + addresses: [ 192.0.2.1/29, 2001:db8::1/64 ] + bd12: + description: "Bridge Domain 12, invalid because it has Gi1/0/0 as well" + mtu: 9000 + interfaces: [ GigabitEthernet4/0/0, GigabitEthernet1/0/0 ] + lcp: "bvi12" diff --git a/validator/bridgedomain.py b/validator/bridgedomain.py index 4436836..4f393c0 100644 --- a/validator/bridgedomain.py +++ b/validator/bridgedomain.py @@ -31,6 +31,32 @@ def get_by_name(yaml, ifname): return None +def get_bridge_interfaces(yaml): + """ Returns a list of all interfaces that are bridgedomain members """ + + ret = [] + if not 'bridgedomains' in yaml: + return ret + + for ifname, iface in yaml['bridgedomains'].items(): + if 'interfaces' in iface: + ret.extend(iface['interfaces']) + + return ret + +def is_bridge_interface_unique(yaml, ifname): + """ Returns True if this interface is referenced in bridgedomains zero or one times """ + + ifs = get_bridge_interfaces(yaml) + return ifs.count(ifname) < 2 + + +def is_bridge_interface(yaml, ifname): + """ Returns True if this interface is a member of a BridgeDomain """ + + return ifname in get_bridge_interfaces(yaml) + + def validate_bridgedomains(yaml): result = True msgs = [] @@ -66,7 +92,7 @@ def validate_bridgedomains(yaml): result = False continue - if not interface.is_bridge_interface_unique(yaml, member): + if not is_bridge_interface_unique(yaml, member): msgs.append("bridgedomain %s member %s is not unique" % (ifname, member)) result = False diff --git a/validator/interface.py b/validator/interface.py index 1185890..8bc0f1d 100644 --- a/validator/interface.py +++ b/validator/interface.py @@ -13,6 +13,7 @@ # import logging import validator.bondethernet as bondethernet +import validator.bridgedomain as bridgedomain import validator.lcp as lcp import validator.address as address @@ -80,32 +81,6 @@ def has_address(yaml, ifname): return 'addresses' in iface -def get_bridge_interfaces(yaml): - """ Returns a list of all interfaces that are bridgedomain members """ - - ret = [] - if not 'bridgedomains' in yaml: - return ret - - for ifname, iface in yaml['bridgedomains'].items(): - if 'interfaces' in iface: - ret.extend(iface['interfaces']) - - return ret - -def is_bridge_interface_unique(yaml, ifname): - """ Returns True if this interface is referenced in bridgedomains zero or one times """ - - ifs = get_bridge_interfaces(yaml) - return ifs.count(ifname) < 2 - - -def is_bridge_interface(yaml, ifname): - """ Returns True if this interface is a member of a BridgeDomain """ - - return ifname in get_bridge_interfaces(yaml) - - def get_l2xc_interfaces(yaml): """ Returns a list of all interfaces that have an L2 CrossConnect """ ret = [] @@ -298,7 +273,7 @@ def unique_encapsulation(yaml, sub_ifname): def is_l2(yaml, ifname): """ Returns True if the interface is an L2XC target or a member of a bridgedomain """ - if is_bridge_interface(yaml, ifname): + if bridgedomain.is_bridge_interface(yaml, ifname): return True if is_l2xc_target_interface(yaml, ifname): return True @@ -424,7 +399,7 @@ def validate_interfaces(yaml): if not is_l2xc_target_interface_unique(yaml, iface['l2xc']): msgs.append("interface %s l2xc target %s is not unique" % (ifname, iface['l2xc'])) result = False - if is_bridge_interface(yaml, iface['l2xc']): + if bridgedomain.is_bridge_interface(yaml, iface['l2xc']): msgs.append("interface %s l2xc target %s is in a bridgedomain" % (ifname, iface['l2xc'])) result = False if has_lcp(yaml, iface['l2xc']): @@ -493,7 +468,7 @@ def validate_interfaces(yaml): if not is_l2xc_target_interface_unique(yaml, sub_iface['l2xc']): msgs.append("sub-interface %s l2xc target %s is not unique" % (sub_ifname, sub_iface['l2xc'])) result = False - if is_bridge_interface(yaml, sub_iface['l2xc']): + if bridgedomain.is_bridge_interface(yaml, sub_iface['l2xc']): msgs.append("sub-interface %s l2xc target %s is in a bridgedomain" % (sub_ifname, sub_iface['l2xc'])) result = False if has_lcp(yaml, sub_iface['l2xc']): diff --git a/validator/test_bridgedomain.py b/validator/test_bridgedomain.py new file mode 100644 index 0000000..2651672 --- /dev/null +++ b/validator/test_bridgedomain.py @@ -0,0 +1,25 @@ +import unittest +import yaml +import validator.bridgedomain as bridgedomain + +class TestBridgeDomainMethods(unittest.TestCase): + def setUp(self): + with open("unittest/test_bridgedomain.yaml", "r") as f: + self.cfg = yaml.load(f, Loader = yaml.FullLoader) + + def test_members(self): + self.assertTrue(bridgedomain.is_bridge_interface(self.cfg, "GigabitEthernet1/0/0")) + self.assertTrue(bridgedomain.is_bridge_interface(self.cfg, "GigabitEthernet2/0/0.100")) + self.assertFalse(bridgedomain.is_bridge_interface(self.cfg, "GigabitEthernet3/0/0")) + self.assertFalse(bridgedomain.is_bridge_interface(self.cfg, "GigabitEthernet3/0/0.100")) + + def test_unique(self): + self.assertFalse(bridgedomain.is_bridge_interface_unique(self.cfg, "GigabitEthernet1/0/0")) + self.assertTrue(bridgedomain.is_bridge_interface_unique(self.cfg, "GigabitEthernet2/0/0.100")) + + def test_enumerators(self): + ifs = bridgedomain.get_bridge_interfaces(self.cfg) + self.assertEqual(len(ifs), 8) + self.assertIn("BondEthernet0", ifs) + self.assertIn("GigabitEthernet1/0/0", ifs) + self.assertIn("GigabitEthernet2/0/0.100", ifs)