def test___restart_peers_found_deployment_id(): test___restart_peers_found_deployment_id.run_command_counter = 0 def run_command(cmd): output = [ [ 'vtysh', '-c', 'clear bgp peer-group BGP_TEST_PEER_GROUP_1 soft in' ], [ 'vtysh', '-c', 'clear bgp peer-group BGP_TEST_PEER_GROUP_2 soft in' ], ] desired_value = output[ test___restart_peers_found_deployment_id.run_command_counter] assert cmd == desired_value test___restart_peers_found_deployment_id.run_command_counter += 1 return 0, "", "" cfg_mgr = MagicMock() common_objs = { 'directory': Directory(), 'cfg_mgr': cfg_mgr, 'tf': TemplateFabric(), 'constants': global_constants, } mgr = BGPAllowListMgr(common_objs, "CONFIG_DB", "BGP_ALLOWED_PREFIXES") mocked = MagicMock( name='_BGPAllowListMgr__find_peer_group_by_deployment_id') mocked.return_value = ["BGP_TEST_PEER_GROUP_1", "BGP_TEST_PEER_GROUP_2"] mgr._BGPAllowListMgr__find_peer_group_by_deployment_id = mocked app.allow_list.run_command = run_command rc = mgr._BGPAllowListMgr__restart_peers(5) assert rc
def set_del_test(op, args, currect_config, expected_config): from app.allow_list import BGPAllowListMgr set_del_test.push_list_called = False def push_list(args): set_del_test.push_list_called = True assert args == expected_config return True # app.allow_list.run_command = lambda cmd: (0, "", "") # cfg_mgr = MagicMock() cfg_mgr.update.return_value = None cfg_mgr.push_list = push_list cfg_mgr.get_text.return_value = currect_config common_objs = { 'directory': Directory(), 'cfg_mgr': cfg_mgr, 'tf': TemplateFabric(), 'constants': global_constants, } mgr = BGPAllowListMgr(common_objs, "CONFIG_DB", "BGP_ALLOWED_PREFIXES") if op == "SET": mgr.set_handler(*args) elif op == "DEL": mgr.del_handler(*args) else: assert False, "Wrong operation" if expected_config: assert set_del_test.push_list_called, "cfg_mgr.push_list wasn't called" else: assert not set_del_test.push_list_called, "cfg_mgr.push_list was called"
def run_tests(test_name, template_fname, tests): tf = TemplateFabric(TEMPLATE_PATH) template = tf.from_file(template_fname) for case_name, param_fname, result_fname in tests: params = load_json(param_fname) raw_generated_result = str(template.render(params)) assert "None" not in raw_generated_result, "Test %s.%s" % (test_name, case_name) # this is used only for initial generation write_result(result_fname, raw_generated_result) canonical_generated_result = ConfigMgr.to_canonical( raw_generated_result) with open(result_fname) as result_fp: raw_saved_result = result_fp.read() canonical_saved_result = ConfigMgr.to_canonical(raw_saved_result) assert canonical_saved_result == canonical_generated_result, "Test %s.%s" % ( test_name, case_name)
def test_set_handler_no_community_data_is_already_presented(): from app.allow_list import BGPAllowListMgr cfg_mgr = MagicMock() cfg_mgr.update.return_value = None cfg_mgr.get_text.return_value = [ 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 10 deny 0.0.0.0/0 le 17', 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 20 permit 20.20.30.0/24 ge 25', 'ip prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4 seq 30 permit 40.50.0.0/16 ge 17', 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 10 deny 0::/0 le 59', 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 20 deny 0::/0 ge 65', 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 30 permit fc01:20::/64 ge 65', 'ipv6 prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6 seq 40 permit fc01:30::/64 ge 65', 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V4 permit 30000', ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V4', 'route-map ALLOW_LIST_DEPLOYMENT_ID_5_V6 permit 30000', ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_5_COMMUNITY_empty_V6', "" ] common_objs = { 'directory': Directory(), 'cfg_mgr': cfg_mgr, 'tf': TemplateFabric(), 'constants': global_constants, } mgr = BGPAllowListMgr(common_objs, "CONFIG_DB", "BGP_ALLOWED_PREFIXES") mgr.set_handler( "DEPLOYMENT_ID|5", { "prefixes_v4": "20.20.30.0/24,40.50.0.0/16", "prefixes_v6": "fc01:20::/64,fc01:30::/64", }) assert not cfg_mgr.push_list.called, "cfg_mgr.push_list was called, but it shouldn't have been"
def test___set_handler_validate(): from app.allow_list import BGPAllowListMgr cfg_mgr = MagicMock() common_objs = { 'directory': Directory(), 'cfg_mgr': cfg_mgr, 'tf': TemplateFabric(), 'constants': global_constants, } mgr = BGPAllowListMgr(common_objs, "CONFIG_DB", "BGP_ALLOWED_PREFIXES") data = { "prefixes_v4": "20.20.30.0/24,40.50.0.0/16", "prefixes_v6": "fc01:20::/64,fc01:30::/64", } assert not mgr._BGPAllowListMgr__set_handler_validate( "DEPLOYMENT_ID|5|1010:2020", None) assert not mgr._BGPAllowListMgr__set_handler_validate( "DEPLOYMENT_ID1|5|1010:2020", data) assert not mgr._BGPAllowListMgr__set_handler_validate( "DEPLOYMENT_ID|z|1010:2020", data) assert not mgr._BGPAllowListMgr__set_handler_validate( "DEPLOYMENT_ID|5|1010:2020", { "prefixes_v4": "20.20.30.0/24,40.50.0.0/16", "prefixes_v6": "20.20.30.0/24,40.50.0.0/16", }) assert not mgr._BGPAllowListMgr__set_handler_validate( "DEPLOYMENT_ID|5|1010:2020", { "prefixes_v4": "fc01:20::/64,fc01:30::/64", "prefixes_v6": "fc01:20::/64,fc01:30::/64", })
def test_pfx_filter_wrong_ip(caplog): src = { ('Loopback0', 'wrong_ip'): {}, } res = TemplateFabric.pfx_filter(src) assert "'wrong_ip' is invalid ip address" in caplog.text assert isinstance(res, OrderedDict) and len(res) == 0
def parse_instance_conf(filename): activate_re = re.compile(r'^neighbor\s+(\S+)\s+activate$') with open(filename) as fp: lines = [ line.strip() for line in fp if not line.strip().startswith('!') and line.strip() != '' ] # Search all v6 neighbors neighbors = {} for line in lines: if activate_re.match(line): neighbor = activate_re.match(line).group(1) if TemplateFabric.is_ipv6(neighbor): neighbors[neighbor] = {} # Extract peer-groups and route-maps for neighbor, neighbor_data in neighbors.iteritems(): route_map_in_re = re.compile( r'^neighbor\s+%s\s+route-map\s+(\S+) in$' % neighbor) peer_group_re = re.compile(r'^neighbor\s+%s\s+peer-group\s+(\S+)$' % neighbor) for line in lines: if route_map_in_re.match(line): assert "route-map" not in neighbor_data neighbor_data["route-map"] = route_map_in_re.match(line).group( 1) if peer_group_re.match(line): assert "peer-group" not in neighbor_data neighbor_data["peer-group"] = peer_group_re.match(line).group( 1) # Ensure that every ivp6 neighbor has either route-map or peer-group for neighbor, neighbor_data in neighbors.iteritems(): assert "route-map" in neighbor_data or "peer-group" in neighbor_data,\ "IPv6 neighbor '%s' must have either route-map in or peer-group %s" % (neighbor, neighbor_data) return neighbors
def test_pfx_filter_strings(): src = { 'Loopback0': {}, 'Loopback1': {}, } expected = OrderedDict([]) res = TemplateFabric.pfx_filter(src) assert res == expected
def __set_handler_validate(self, key, data): """ Validate parameters of a "Set" message :param key: ket of the 'SET' message :param data: data of the 'SET' message :return: True if parameters are valid, False if parameters are invalid """ if data is None: log_err( "BGPAllowListMgr::Received BGP ALLOWED 'SET' message without data" ) return False if not self.key_re.match(key): log_err( "BGPAllowListMgr::Received BGP ALLOWED 'SET' message with invalid key: '%s'" % key) return False prefixes_v4 = [] prefixes_v6 = [] if "prefixes_v4" in data: prefixes_v4 = str(data["prefixes_v4"]).split(",") if not all( TemplateFabric.is_ipv4(prefix) for prefix in prefixes_v4): arguments = "prefixes_v4", str(data["prefixes_v4"]) log_err( "BGPAllowListMgr::Received BGP ALLOWED 'SET' message with invalid input[%s]:'%s'" % arguments) return False if "prefixes_v6" in data: prefixes_v6 = str(data["prefixes_v6"]).split(",") if not all( TemplateFabric.is_ipv6(prefix) for prefix in prefixes_v6): arguments = "prefixes_v6", str(data["prefixes_v6"]) log_err( "BGPAllowListMgr::Received BGP ALLOWED 'SET' message with invalid input[%s]:'%s'" % arguments) return False if not prefixes_v4 and not prefixes_v6: log_err( "BGPAllowListMgr::Received BGP ALLOWED 'SET' message with no prefixes specified: %s" % str(data)) return False return True
def test_pfx_filter_pfx_v4_no_mask(): src = { ('Loopback0', '11.11.11.11'): {}, ('Loopback1', '55.55.55.55'): {}, } expected = OrderedDict([ (('Loopback1', '55.55.55.55/32'), {}), (('Loopback0', '11.11.11.11/32'), {}), ]) res = TemplateFabric.pfx_filter(src) assert res == expected
def test_pfx_filter_pfx_v6_no_mask(): src = { ('Loopback0', 'fc00::'): {}, ('Loopback1', 'fc00::1'): {}, } expected = OrderedDict([ (('Loopback0', 'fc00::/128'), {}), (('Loopback1', 'fc00::1/128'), {}), ]) res = TemplateFabric.pfx_filter(src) assert res == expected
def test_pfx_filter_mixed_keys(): src = { 'Loopback0': {}, ('Loopback0', '11.11.11.11/32'): {}, 'Loopback1': {}, ('Loopback1', '55.55.55.55/32'): {}, } expected = OrderedDict([ (('Loopback1', '55.55.55.55/32'), {}), (('Loopback0', '11.11.11.11/32'), {}), ]) res = TemplateFabric.pfx_filter(src) assert res == expected
def test___restart_peers_not_found_deployment_id(): def run_command(cmd): assert cmd == ['vtysh', '-c', 'clear bgp * soft in'] return 0, "", "" cfg_mgr = MagicMock() common_objs = { 'directory': Directory(), 'cfg_mgr': cfg_mgr, 'tf': TemplateFabric(), 'constants': global_constants, } mgr = BGPAllowListMgr(common_objs, "CONFIG_DB", "BGP_ALLOWED_PREFIXES") mocked = MagicMock( name='_BGPAllowListMgr__find_peer_group_by_deployment_id') mocked.return_value = [] mgr._BGPAllowListMgr__find_peer_group_by_deployment_id = mocked app.allow_list.run_command = run_command rc = mgr._BGPAllowListMgr__restart_peers(5) assert rc
def test_pfx_filter_pfx_comprehensive(): src = { 'Loopback0': {}, ('Loopback0', 'fc00::'): {}, 'Loopback1': {}, ('Loopback1', 'fc00::1/128'): {}, ('Loopback2', '11.11.11.11/32'): {}, ('Loopback3', '55.55.55.55'): {}, 'Loopback2': {}, 'Loopback3': {}, ('Loopback5', '22.22.22.1/24'): {}, ('Loopback6', 'fc00::55/64'): {}, } expected = OrderedDict([ (('Loopback1', 'fc00::1/128'), {}), (('Loopback3', '55.55.55.55/32'), {}), (('Loopback6', 'fc00::55/64'), {}), (('Loopback2', '11.11.11.11/32'), {}), (('Loopback0', 'fc00::/128'), {}), (('Loopback5', '22.22.22.1/24'), {}), ]) res = TemplateFabric.pfx_filter(src) assert res == expected
def test___find_peer_group_by_deployment_id(): from app.allow_list import BGPAllowListMgr cfg_mgr = MagicMock() cfg_mgr.update.return_value = None cfg_mgr.get_text.return_value = [ 'router bgp 64601', ' neighbor BGPSLBPassive peer-group', ' neighbor BGPSLBPassive remote-as 65432', ' neighbor BGPSLBPassive passive', ' neighbor BGPSLBPassive ebgp-multihop 255', ' neighbor BGPSLBPassive update-source 10.1.0.32', ' neighbor PEER_V4 peer-group', ' neighbor PEER_V4_INT peer-group', ' neighbor PEER_V6 peer-group', ' neighbor PEER_V6_INT peer-group', ' neighbor 10.0.0.1 remote-as 64802', ' neighbor 10.0.0.1 peer-group PEER_V4', ' neighbor 10.0.0.1 description ARISTA01T1', ' neighbor 10.0.0.1 timers 3 10', ' neighbor fc00::2 remote-as 64802', ' neighbor fc00::2 peer-group PEER_V6', ' neighbor fc00::2 description ARISTA01T1', ' neighbor fc00::2 timers 3 10', ' address-family ipv4 unicast', ' neighbor BGPSLBPassive activate', ' neighbor BGPSLBPassive soft-reconfiguration inbound', ' neighbor BGPSLBPassive route-map FROM_BGP_SPEAKER in', ' neighbor BGPSLBPassive route-map TO_BGP_SPEAKER out', ' neighbor PEER_V4 soft-reconfiguration inbound', ' neighbor PEER_V4 allowas-in 1', ' neighbor PEER_V4 route-map FROM_BGP_PEER_V4 in', ' neighbor PEER_V4 route-map TO_BGP_PEER_V4 out', ' neighbor PEER_V4_INT soft-reconfiguration inbound', ' neighbor PEER_V4_INT allowas-in 1', ' neighbor PEER_V4_INT route-map FROM_BGP_PEER_V4 in', ' neighbor PEER_V4_INT route-map TO_BGP_PEER_V4 out', ' neighbor 10.0.0.1 activate', ' exit-address-family', ' address-family ipv6 unicast', ' neighbor BGPSLBPassive activate', ' neighbor PEER_V6 soft-reconfiguration inbound', ' neighbor PEER_V6 allowas-in 1', ' neighbor PEER_V6 route-map FROM_BGP_PEER_V6 in', ' neighbor PEER_V6 route-map TO_BGP_PEER_V6 out', ' neighbor PEER_V6_INT soft-reconfiguration inbound', ' neighbor PEER_V6_INT allowas-in 1', ' neighbor PEER_V6_INT route-map FROM_BGP_PEER_V6 in', ' neighbor PEER_V6_INT route-map TO_BGP_PEER_V6 out', ' neighbor fc00::2 activate', ' exit-address-family', 'route-map ALLOW_LIST_DEPLOYMENT_ID_0_V4 permit 10', ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_0_COMMUNITY_1010:1010', ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_0_COMMUNITY_1010:1010_V4', 'route-map ALLOW_LIST_DEPLOYMENT_ID_0_V4 permit 30000', ' match ip address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_0_COMMUNITY_empty_V4', 'route-map ALLOW_LIST_DEPLOYMENT_ID_0_V4 permit 65535', ' set community 5060:12345 additive', 'route-map ALLOW_LIST_DEPLOYMENT_ID_0_V6 permit 10', ' match community COMMUNITY_ALLOW_LIST_DEPLOYMENT_ID_0_COMMUNITY_1010:1010', ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_0_COMMUNITY_1010:1010_V6', 'route-map ALLOW_LIST_DEPLOYMENT_ID_0_V6 permit 30000', ' match ipv6 address prefix-list PL_ALLOW_LIST_DEPLOYMENT_ID_0_COMMUNITY_empty_V6', 'route-map ALLOW_LIST_DEPLOYMENT_ID_0_V6 permit 65535', ' set community 5060:12345 additive', 'route-map FROM_BGP_PEER_V4 permit 100', 'route-map FROM_BGP_PEER_V4 permit 2', ' call ALLOW_LIST_DEPLOYMENT_ID_0_V4', ' on-match next', 'route-map FROM_BGP_PEER_V6 permit 1', ' set ipv6 next-hop prefer-global ', 'route-map FROM_BGP_PEER_V6 permit 100', 'route-map FROM_BGP_PEER_V6 permit 2', ' call ALLOW_LIST_DEPLOYMENT_ID_0_V6', ' on-match next', 'route-map FROM_BGP_SPEAKER permit 10', 'route-map RM_SET_SRC permit 10', ' set src 10.1.0.32', 'route-map RM_SET_SRC6 permit 10', ' set src FC00:1::32', 'route-map TO_BGP_PEER_V4 permit 100', 'route-map TO_BGP_PEER_V6 permit 100', 'route-map TO_BGP_SPEAKER deny 1', ] common_objs = { 'directory': Directory(), 'cfg_mgr': cfg_mgr, 'tf': TemplateFabric(), 'constants': global_constants, } mgr = BGPAllowListMgr(common_objs, "CONFIG_DB", "BGP_ALLOWED_PREFIXES") values = mgr._BGPAllowListMgr__find_peer_group_by_deployment_id(0) assert values == ['PEER_V4_INT', 'PEER_V6_INT', 'PEER_V6', 'PEER_V4']
def test_pfx_filter_empty_dict(): res = TemplateFabric.pfx_filter({}) assert isinstance(res, OrderedDict) and len(res) == 0
def test_pfx_filter_none(): res = TemplateFabric.pfx_filter(None) assert isinstance(res, OrderedDict) and len(res) == 0