Skip to content

[generic_config_updater]: Rewrite key-level removes that empty a ConfigDB table - #4856

Open
Verma-Anukul wants to merge 2 commits into
sonic-net:masterfrom
Verma-Anukul:gcu-all-key-del
Open

Verma-Anukul wants to merge 2 commits into
sonic-net:masterfrom
Verma-Anukul:gcu-all-key-del

Conversation

@Verma-Anukul

Copy link
Copy Markdown
Contributor

What I did

Fixes #4852

config apply-patch now accepts per-key removes that empty a ConfigDB table (for example /VLAN/Vlan3911) and rewrites them to a table-level remove. Automation can delete keys one by one without inspecting running config or special-casing the empty-table restriction.

How I did it

After field-operation validation on the original simulated target, PatchApplier.apply calls rewrite_patch_emptying_tables(). Only op=remove with path /TABLE/KEY is rewritten, and only when every operation on that emptied table is of that form. Other patch shapes are unchanged. Protected paths such as /LOOPBACK_INTERFACE/Loopback0 are still validated on the original transition.

How to verify it

Unit tests:

  • tests/generic_config_updater/gu_common_test.py::TestRewritePatchEmptyingTables
  • tests/generic_config_updater/generic_updater_test.py rewrite and Loopback0 tests

Device verification (VS):

admin@sonic:~$ show vlan config
Name        VID  Member    Mode
--------  -----  --------  ------
Vlan3911   3911
Vlan3912   3912
admin@sonic:~$ redis-cli -n 4 keys "VLAN*"
1) "VLAN|Vlan3911"
2) "VLAN|Vlan3912"
admin@sonic:~$ sudo config apply-patch vlan.json
Patch Applier: localhost: Patch: [{"op": "remove", "path": "/VLAN/Vlan3911"}, {"op": "remove", "path": "/VLAN/Vlan3912"}]
Patch Applier: localhost: key-level removes would empty table VLAN; rewriting to table-level remove. Rewritten patch: [{"op": "remove", "path": "/VLAN"}]
Patch applied successfully.
admin@sonic:~$ redis-cli -n 4 keys "VLAN*"
(empty array)
admin@sonic:~$ show vlan config
Name    VID    Member    Mode
------  -----  --------  ------

vlan.json:

[
  {"op": "remove", "path": "/VLAN/Vlan3911"},
  {"op": "remove", "path": "/VLAN/Vlan3912"}
]

Previous command output (if the output of a command-line utility has changed)

given patch is not valid because it will result in empty tables which is not allowed in ConfigDb. Table: VLAN

New command output (if the output of a command-line utility has changed)

Patch Applier: localhost: key-level removes would empty table VLAN; rewriting to table-level remove. Rewritten patch: [{"op": "remove", "path": "/VLAN"}]
Patch applied successfully.

…igDB table

Signed-off-by: Verma-Anukul <anukulverma2013@gmail.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@mssonicbld

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Signed-off-by: Verma-Anukul <anukulverma2013@gmail.com>
@mssonicbld

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@Verma-Anukul

Copy link
Copy Markdown
Contributor Author

@rimunagala rimunagala left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intended pure key-removal behavior and protected-field validation look correct, and all CI checks pass. Requesting changes for the config replace regression noted inline; the RFC 6902 from-path case is non-blocking.

# removes (for example /VLAN/Vlan10) without knowing they delete the last
# remaining entries. Only those key-level removes are rewritten to a
# table-level remove; other operations are left unchanged.
empty_tables = self.config_wrapper.get_empty_tables(target_config)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PatchApplier is also used by ConfigReplacer (config replace). If a replacement target contains "VLAN": {}, generate_patch() produces per-key removes; this branch rewrites and applies them as /VLAN, but ConfigReplacer then compares the absent table with the original empty-table target and raises after ConfigDB has already been modified. Before this change, EmptyTableError occurred before any writes. Please restrict this rewrite to the explicit apply-patch flow, or reject/canonicalize empty replacement targets before applying, and add a config replace regression test.

parsed_ops = []
ops_by_table = {table: [] for table in empty_tables}

for operation in patch:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking edge: eligibility considers only path, but RFC 6902 move/copy can reference this table through from. For example, remove /VLAN/B, copy /VLAN/A -> /OTHER/Y, then remove /VLAN/A is rewritten to remove /VLAN before the copy, causing re-simulation to fail. Since GCU accepts move/copy and the PR states other patch shapes remain unchanged, please skip rewriting tables referenced through from, or otherwise preserve those dependencies.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[GCU] Need enhancement to support deleting keys one by one without empty-table restriction

3 participants