Skip to content

Commit

Permalink
[GCU] Prohibit removal of PFC_WD POLL_INTERVAL field (#2545)
Browse files Browse the repository at this point in the history
  • Loading branch information
isabelmsft committed Jan 19, 2023
1 parent 163e766 commit 3d8e9c6
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 0 deletions.
4 changes: 4 additions & 0 deletions generic_config_updater/generic_updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ def apply(self, patch):
# Generate target config
self.logger.log_notice("Simulating the target full config after applying the patch.")
target_config = self.patch_wrapper.simulate_patch(patch, old_config)

# Validate all JsonPatch operations on specified fields
self.logger.log_notice("Validating all JsonPatch operations are permitted on the specified fields")
self.config_wrapper.validate_field_operation(old_config, target_config)

# Validate target config does not have empty tables since they do not show up in ConfigDb
self.logger.log_notice("Validating target config does not have empty tables, " \
Expand Down
19 changes: 19 additions & 0 deletions generic_config_updater/gu_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
class GenericConfigUpdaterError(Exception):
pass

class IllegalPatchOperationError(ValueError):
pass

class EmptyTableError(ValueError):
pass

Expand Down Expand Up @@ -136,6 +139,22 @@ def validate_config_db_config(self, config_db_as_json):

return True, None

def validate_field_operation(self, old_config, target_config):
"""
Some fields in ConfigDB are restricted and may not allow third-party addition, replacement, or removal.
Because YANG only validates state and not transitions, this method helps to JsonPatch operations/transitions for the specified fields.
"""
patch = jsonpatch.JsonPatch.from_diff(old_config, target_config)

# illegal_operations_to_fields_map['remove'] yields a list of fields for which `remove` is an illegal operation
illegal_operations_to_fields_map = {'add':[],
'replace': [],
'remove': ['/PFC_WD/GLOBAL/POLL_INTERVAL', '/PFC_WD/GLOBAL']}
for operation, field_list in illegal_operations_to_fields_map.items():
for field in field_list:
if any(op['op'] == operation and field == op['path'] for op in patch):
raise IllegalPatchOperationError("Given patch operation is invalid. Operation: {} is illegal on field: {}".format(operation, field))

def validate_lanes(self, config_db):
if "PORT" not in config_db:
return True, None
Expand Down
12 changes: 12 additions & 0 deletions tests/generic_config_updater/gu_common_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,18 @@ def setUp(self):
self.config_wrapper_mock = gu_common.ConfigWrapper()
self.config_wrapper_mock.get_config_db_as_json=MagicMock(return_value=Files.CONFIG_DB_AS_JSON)

def test_validate_field_operation_legal(self):
old_config = {"PFC_WD": {"GLOBAL": {"POLL_INTERVAL": "60"}}}
target_config = {"PFC_WD": {"GLOBAL": {"POLL_INTERVAL": "40"}}}
config_wrapper = gu_common.ConfigWrapper()
config_wrapper.validate_field_operation(old_config, target_config)

def test_validate_field_operation_illegal(self):
old_config = {"PFC_WD": {"GLOBAL": {"POLL_INTERVAL": 60}}}
target_config = {"PFC_WD": {"GLOBAL": {}}}
config_wrapper = gu_common.ConfigWrapper()
self.assertRaises(gu_common.IllegalPatchOperationError, config_wrapper.validate_field_operation, old_config, target_config)

def test_ctor__default_values_set(self):
config_wrapper = gu_common.ConfigWrapper()

Expand Down

0 comments on commit 3d8e9c6

Please sign in to comment.