Skip to content

PR190 revive, vyos_conf match "enforced"#415

Open
omnom62 wants to merge 28 commits intovyos:mainfrom
omnom62:pr190-revive
Open

PR190 revive, vyos_conf match "enforced"#415
omnom62 wants to merge 28 commits intovyos:mainfrom
omnom62:pr190-revive

Conversation

@omnom62
Copy link
Copy Markdown
Contributor

@omnom62 omnom62 commented Apr 23, 2025

Change Summary

The change modifies vyso_config module to add additional match feature, 'smart', that allows to overwrite the existing configuration by the supplied in the Ansible playboo, i..e this is to enforce the configuration.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes)
  • Migration from an old Vyatta component to vyos-1x, please link to related PR inside obsoleted component
  • Other (please describe):

Related Task(s)

Related PR(s)

Component(s) name

Proposed changes

How to test

Test results

  • Sanity tests passed
  • Unit tests passed

Tested against VyOS versions:

  • 1.3.8
  • 1.4.3
  • 1.5q2

Checklist:

  • I have read the CONTRIBUTING document
  • I have linked this PR to one or more Phabricator Task(s)
  • I have run the ansible sanity and unit tests
  • My commit headlines contain a valid Task id
  • My change requires a change to the documentation
  • I have updated the documentation accordingly
  • I have added unit tests to cover my changes
  • I have added a file to changelogs/fragments to describe the changes

@github-actions
Copy link
Copy Markdown

github-actions bot commented Jul 22, 2025

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@omnom62
Copy link
Copy Markdown
Contributor Author

omnom62 commented Aug 4, 2025

I have read the CLA Document and I hereby sign the CLA

@omnom62 omnom62 marked this pull request as ready for review November 27, 2025 03:52
@omnom62 omnom62 requested a review from a team as a code owner November 27, 2025 03:52
Copilot AI review requested due to automatic review settings April 17, 2026 12:05
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a new match: smart mode to vyos_config, intended to compute an “enforcing” diff (including delete commands) by comparing structured representations of the candidate and running configuration.

Changes:

  • Add smart to the match parameter choices for vyos_config, and update examples/docs accordingly.
  • Implement diff_match == "smart" in the VyOS cliconf plugin using a new VyosConf helper to generate set/delete command diffs.
  • Add unit tests for the new VyosConf diff logic and a new vyos_config test case for match=smart, plus a changelog fragment and a .gitignore update.

Reviewed changes

Copilot reviewed 7 out of 10 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
plugins/cliconf/vyos.py Adds diff_match="smart" branch to generate delete/set diffs via VyosConf, and exposes smart in supported diff_match values.
plugins/cliconf_utils/vyosconf.py Introduces VyosConf for parsing set/delete commands into a tree and computing structured diffs.
plugins/modules/vyos_config.py Adds smart to the module argument choices and examples; module passes match through as diff_match.
tests/unit/modules/network/vyos/test_vyos_config.py Adds a unit test case for match=smart in the vyos_config module tests.
tests/unit/cliconf/test_utils_vyosconf.py Adds unit tests covering VyosConf parse/build/diff behavior.
docs/vyos.vyos.vyos_config_module.rst Documents smart as a match choice and adds it to an example.
changelogs/fragments/vyos_config_smart.yml Adds a release-note fragment for the new smart match feature.
.gitignore Ignores *.bak files.
Comments suppressed due to low confidence (1)

docs/vyos.vyos.vyos_config_module.rst:204

  • The docs list smart as a valid match choice, but the parameter description doesn’t explain what smart does or warn about its potential to remove existing configuration. Please expand the description to define smart behavior and any prerequisites/risks (e.g., whether it enforces full config vs. only specified subtrees).
                <td>
                        <ul style="margin: 0; padding: 0"><b>Choices:</b>
                                    <li><div style="color: blue"><b>line</b>&nbsp;&larr;</div></li>
                                    <li>smart</li>
                                    <li>none</li>
                        </ul>
                </td>
                <td>
                        <div>The <code>match</code> argument controls the method used to match against the current active configuration.  By default, the desired config is matched against the active config and the deltas are loaded.  If the <code>match</code> argument is set to <code>none</code> the active configuration is ignored and the configuration is always loaded.</div>
                </td>

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread plugins/cliconf/vyos.py
diff["config_diff"] = list(candidate_commands)
return diff
if diff_match == "smart":
running_conf = VyosConf(running.splitlines())
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

diff_match == "smart" currently computes a full-tree diff between the entire running config and the (often partial) candidate. With a partial candidate (common for vyos_config), this will generate delete commands for any top-level config not present in the candidate, potentially wiping unrelated configuration. Consider scoping deletions to only the subtrees explicitly managed by the candidate (e.g., by adding a root-level “keep existing” sentinel or otherwise restricting the diff), and document the exact destructive semantics if full replacement is intended.

Suggested change
running_conf = VyosConf(running.splitlines())
managed_roots = set()
for line in candidate_commands:
item = str(line).replace("'", "").strip()
if item.startswith("set") or item.startswith("delete"):
parts = item.split()
if len(parts) > 1:
managed_roots.add(parts[1])
scoped_running = list()
for line in running.splitlines():
item = str(line).replace("'", "").strip()
if item.startswith("set") or item.startswith("delete"):
parts = item.split()
if len(parts) > 1 and parts[1] in managed_roots:
scoped_running.append(item)
running_conf = VyosConf(scoped_running)

Copilot uses AI. Check for mistakes.
Comment thread changelogs/fragments/vyos_config_smart.yml Outdated
Comment thread plugins/cliconf_utils/vyosconf.py
Comment thread plugins/cliconf_utils/vyosconf.py
Comment thread tests/unit/modules/network/vyos/test_vyos_config.py Outdated
Comment thread plugins/modules/vyos_config.py
Comment thread plugins/cliconf_utils/vyosconf.py
Comment thread plugins/cliconf_utils/vyosconf.py Outdated
Copilot AI review requested due to automatic review settings April 17, 2026 18:54
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 10 changed files in this pull request and generated 6 comments.

Comment thread plugins/cliconf_utils/vyosconf.py
Comment thread tests/unit/cliconf/test_utils_vyosconf.py
Comment on lines +151 to +155
self.conn.get_diff = MagicMock(
return_value=self.cliconf_obj.get_diff(candidate, None, diff_match="none"),
)
self.execute_module(changed=True, commands=lines, sort=False)

Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

test_vyos_config_match_smart sets match="smart" but stubs conn.get_diff to call get_diff(..., diff_match="none"), so the new smart diff logic is never exercised. Update the stub to use diff_match="smart" and pass a realistic running config (e.g. self.running_config) so the test actually validates the behavior (including expected deletes/sets).

Suggested change
self.conn.get_diff = MagicMock(
return_value=self.cliconf_obj.get_diff(candidate, None, diff_match="none"),
)
self.execute_module(changed=True, commands=lines, sort=False)
diff = self.cliconf_obj.get_diff(candidate, self.running_config, diff_match="smart")
config_diff = diff.get("config_diff", diff) if isinstance(diff, dict) else diff
commands = [command for command in config_diff.splitlines() if command]
self.assertTrue(any(command.startswith("delete ") for command in commands))
self.assertTrue(any(command.startswith("set ") for command in commands))
self.conn.get_diff = MagicMock(return_value=diff)
self.execute_module(changed=True, commands=commands, sort=False)

Copilot uses AI. Check for mistakes.
Comment on lines +100 to +107
line = re.match(r"^('(.*)'|\"(.*)\"|([^#\"']*))*", line).group(0).strip()
path = re.findall(r"('.*?'|\".*?\"|\S+)", line)
leaf = path[-1]
if leaf.startswith('"') and leaf.endswith('"'):
leaf = leaf[1:-1]
if leaf.startswith("'") and leaf.endswith("'"):
leaf = leaf[1:-1]
return [path[0], path[1:-1], leaf]
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

parse_line() strips quotes from the leaf token but leaves quotes intact on intermediate path tokens. If a quoted token appears in the path (e.g., a named object containing spaces), it will be stored with its surrounding quotes and later quote_key() can double-quote it, producing incorrect commands and diffs. Consider unquoting every parsed token (not just leaf) before storing it in the config tree.

Copilot uses AI. Check for mistakes.
Comment thread plugins/cliconf_utils/vyosconf.py
Comment thread plugins/cliconf_utils/vyosconf.py
@omnom62
Copy link
Copy Markdown
Contributor Author

omnom62 commented Apr 18, 2026

@claude

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants