diff options
| author | Henning Surmeier <me@hensur.de> | 2022-01-28 17:28:32 +0100 | 
|---|---|---|
| committer | Henning Surmeier <me@hensur.de> | 2022-01-28 17:28:32 +0100 | 
| commit | c501ae0fdc5de3c24c998891f78c8bb05ffb35c7 (patch) | |
| tree | e98947cd1435ef42d7498a1109f10941813db7c1 | |
| parent | a414fa198a96ac5557bc1bd827e8dc18c3150825 (diff) | |
| download | vyos-1x-c501ae0fdc5de3c24c998891f78c8bb05ffb35c7.tar.gz vyos-1x-c501ae0fdc5de3c24c998891f78c8bb05ffb35c7.zip  | |
policy: T4151: remove all previous rules on edit
| -rwxr-xr-x | smoketest/scripts/cli/test_policy.py | 37 | ||||
| -rwxr-xr-x | src/conf_mode/policy-local-route.py | 47 | 
2 files changed, 75 insertions, 9 deletions
diff --git a/smoketest/scripts/cli/test_policy.py b/smoketest/scripts/cli/test_policy.py index d055762f4..6dac28a0f 100755 --- a/smoketest/scripts/cli/test_policy.py +++ b/smoketest/scripts/cli/test_policy.py @@ -1438,6 +1438,43 @@ class TestPolicy(VyOSUnitTestSHIM.TestCase):          self.assertEqual(sort_ip(tmp), original)          self.assertEqual(sort_ip(tmp_v6), original_v6) +    # Test multiple commits ipv4 +    def test_multiple_commit_ipv4_table_id(self): +        path = base_path + ['local-route'] + +        sources = ['192.0.2.1', '192.0.2.2'] +        destination = '203.0.113.25' +        rule = '105' +        table = '151' +        self.cli_set(path + ['rule', rule, 'set', 'table', table]) +        for src in sources: +            self.cli_set(path + ['rule', rule, 'source', src]) + +        self.cli_commit() + +        # Check generated configuration +        # Expected values +        original_first = """ +        105:	from 192.0.2.1 lookup 151 +        105:	from 192.0.2.2 lookup 151 +        """ +        tmp = cmd('ip rule show prio 105') + +        self.assertEqual(sort_ip(tmp), sort_ip(original_first)) + +        # Create second commit with added destination +        self.cli_set(path + ['rule', rule, 'destination', destination]) +        self.cli_commit() + +        original_second = """ +        105:	from 192.0.2.1 to 203.0.113.25 lookup 151 +        105:	from 192.0.2.2 to 203.0.113.25 lookup 151 +        """ +        tmp = cmd('ip rule show prio 105') + +        self.assertEqual(sort_ip(tmp), sort_ip(original_second)) + +  def sort_ip(output):      return output.splitlines().sort() diff --git a/src/conf_mode/policy-local-route.py b/src/conf_mode/policy-local-route.py index 6dabb37ae..71183c6ba 100755 --- a/src/conf_mode/policy-local-route.py +++ b/src/conf_mode/policy-local-route.py @@ -69,20 +69,47 @@ def get_config(config=None):          # delete policy local-route rule x fwmark x          # delete policy local-route rule x destination x.x.x.x          if 'rule' in pbr[route]: -            for rule in pbr[route]['rule']: +            for rule, rule_config in pbr[route]['rule'].items():                  src = leaf_node_changed(conf, base_rule + [rule, 'source'])                  fwmk = leaf_node_changed(conf, base_rule + [rule, 'fwmark'])                  dst = leaf_node_changed(conf, base_rule + [rule, 'destination']) +                # keep track of changes in configuration +                # otherwise we might remove an existing node although nothing else has changed +                changed = False                  rule_def = {} -                if src: -                    rule_def = dict_merge({'source' : src}, rule_def) -                if fwmk: -                    rule_def = dict_merge({'fwmark' : fwmk}, rule_def) -                if dst: -                    rule_def = dict_merge({'destination' : dst}, rule_def) -                dict = dict_merge({dict_id : {rule : rule_def}}, dict) -                pbr.update(dict) +                # src is None if there are no changes to src +                if src is None: +                    # if src hasn't changed, include it in the removal selector +                    # if a new selector is added, we have to remove all previous rules without this selector +                    # to make sure we remove all previous rules with this source(s), it will be included +                    if 'source' in rule_config: +                        rule_def = dict_merge({'source': rule_config['source']}, rule_def) +                else: +                    # if src is not None, it's previous content will be returned +                    # this can be an empty array if it's just being set, or the previous value +                    # either way, something has to be changed and we only want to remove previous values +                    changed = True +                    # set the old value for removal if it's not empty +                    if len(src) > 0: +                        rule_def = dict_merge({'source' : src}, rule_def) +                if fwmk is None: +                    if 'fwmark' in rule_config: +                        rule_def = dict_merge({'fwmark': rule_config['fwmark']}, rule_def) +                else: +                    changed = True +                    if len(fwmk) > 0: +                        rule_def = dict_merge({'fwmark' : fwmk}, rule_def) +                if dst is None: +                    if 'destination' in rule_config: +                        rule_def = dict_merge({'destination': rule_config['destination']}, rule_def) +                else: +                    changed = True +                    if len(dst) > 0: +                        rule_def = dict_merge({'destination' : dst}, rule_def) +                if changed: +                    dict = dict_merge({dict_id : {rule : rule_def}}, dict) +                    pbr.update(dict)      return pbr @@ -116,6 +143,8 @@ def apply(pbr):      if not pbr:          return None +    print(pbr) +      # Delete old rule if needed      for rule_rm in ['rule_remove', 'rule6_remove']:          if rule_rm in pbr:  | 
