diff --git a/acl_loader/main.py b/acl_loader/main.py index ee5cfb17e6..bf4af9a77b 100644 --- a/acl_loader/main.py +++ b/acl_loader/main.py @@ -4,6 +4,7 @@ import ipaddress import json import syslog +import operator import openconfig_acl import tabulate @@ -754,7 +755,7 @@ def incremental_update(self): namespace_configdb.mod_entry(self.ACL_RULE, key, None) for key in existing_controlplane_rules: - if cmp(self.rules_info[key], self.rules_db_info[key]) != 0: + if not operator.eq(self.rules_info[key], self.rules_db_info[key]): self.configdb.set_entry(self.ACL_RULE, key, self.rules_info[key]) # Program for per-asic namespace corresponding to front asic also if present. # For control plane ACL it's not needed but to keep all db in sync program everywhere diff --git a/tests/acl_input/incremental_1.json b/tests/acl_input/incremental_1.json new file mode 100644 index 0000000000..57ede08bf7 --- /dev/null +++ b/tests/acl_input/incremental_1.json @@ -0,0 +1,32 @@ +{ + "acl": { + "acl-sets": { + "acl-set": { + "ntp-acl": { + "acl-entries": { + "acl-entry": { + "1": { + "ip": { + "config": { + "source-ip-address": "20.0.0.12/32" + } + }, + "config": { + "sequence-id": 1 + }, + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + } + } + } + }, + "config": { + "name": "ntp-acl" + } + } + } + } + } +} \ No newline at end of file diff --git a/tests/acl_input/incremental_2.json b/tests/acl_input/incremental_2.json new file mode 100644 index 0000000000..b7de6edbac --- /dev/null +++ b/tests/acl_input/incremental_2.json @@ -0,0 +1,32 @@ +{ + "acl": { + "acl-sets": { + "acl-set": { + "ntp-acl": { + "acl-entries": { + "acl-entry": { + "1": { + "ip": { + "config": { + "source-ip-address": "20.0.0.12/32" + } + }, + "config": { + "sequence-id": 1 + }, + "actions": { + "config": { + "forwarding-action": "DROP" + } + } + } + } + }, + "config": { + "name": "ntp-acl" + } + } + } + } + } +} \ No newline at end of file diff --git a/tests/acl_loader_test.py b/tests/acl_loader_test.py index e1b7e949ea..59bbe21577 100644 --- a/tests/acl_loader_test.py +++ b/tests/acl_loader_test.py @@ -1,6 +1,7 @@ import sys import os import pytest +from unittest import mock test_path = os.path.dirname(os.path.abspath(__file__)) modules_path = os.path.dirname(test_path) @@ -200,3 +201,19 @@ def test_icmp_fields_with_non_tcp_protocol(self, acl_loader): acl_loader.rules_info = {} acl_loader.load_rules_from_file(os.path.join(test_path, 'acl_input/tcp_bad_protocol_number.json')) assert not acl_loader.rules_info.get("RULE_1") + + def test_incremental_update(self, acl_loader): + acl_loader.rules_info = {} + acl_loader.tables_db_info['NTP_ACL'] = { + "stage": "INGRESS", + "type": "CTRLPLANE" + } + acl_loader.load_rules_from_file(os.path.join(test_path, 'acl_input/incremental_1.json')) + acl_loader.rules_db_info = acl_loader.rules_info + assert acl_loader.rules_info[(('NTP_ACL', 'RULE_1'))]["PACKET_ACTION"] == "ACCEPT" + acl_loader.per_npu_configdb = None + acl_loader.configdb.mod_entry = mock.MagicMock(return_value=True) + acl_loader.configdb.set_entry = mock.MagicMock(return_value=True) + acl_loader.load_rules_from_file(os.path.join(test_path, 'acl_input/incremental_2.json')) + acl_loader.incremental_update() + assert acl_loader.rules_info[(('NTP_ACL', 'RULE_1'))]["PACKET_ACTION"] == "DROP"