summaryrefslogtreecommitdiff
path: root/plugins/module_utils
diff options
context:
space:
mode:
authoromnom62 <omnom62@outlook.com>2026-07-07 20:51:27 +1000
committeromnom62 <omnom62@outlook.com>2026-07-07 20:51:27 +1000
commit121088ec0b11a8a36259e5afa3be33fc131b5ef2 (patch)
tree61d3e5481c96ece28ecce4946a397ad9b33a22c1 /plugins/module_utils
parentbe24a31fb8a4dcdd7c237eee28299cc4a20e4f9c (diff)
downloadrest.vyos-121088ec0b11a8a36259e5afa3be33fc131b5ef2.tar.gz
rest.vyos-121088ec0b11a8a36259e5afa3be33fc131b5ef2.zip
T8323: vyos_vlan module
Diffstat (limited to 'plugins/module_utils')
-rw-r--r--plugins/module_utils/vyos.py79
1 files changed, 79 insertions, 0 deletions
diff --git a/plugins/module_utils/vyos.py b/plugins/module_utils/vyos.py
index 5eda204..fedcc13 100644
--- a/plugins/module_utils/vyos.py
+++ b/plugins/module_utils/vyos.py
@@ -27,6 +27,85 @@ from ansible_collections.vyos.rest.plugins.module_utils.vyos_rest import (
)
+# ---------------------------------------------------------------------------
+# Dynamic config utilities
+# ---------------------------------------------------------------------------
+
+
+def _kebab_to_snake(s):
+ """Convert kebab-case string to snake_case."""
+ return s.replace("-", "_")
+
+
+def _snake_to_kebab(s):
+ """Convert snake_case string to kebab-case."""
+ return s.replace("_", "-")
+
+
+def normalize(raw):
+ """Recursively normalize an API response dict to snake_case keys."""
+ if isinstance(raw, dict):
+ return {_kebab_to_snake(k): normalize(v) for k, v in raw.items()}
+ if isinstance(raw, list):
+ return [normalize(v) for v in raw]
+ return raw
+
+
+def denormalize_path(path):
+ """Convert a snake_case path list to kebab-case for the API."""
+ return [_snake_to_kebab(p) for p in path]
+
+
+def _diff_value(want_val, have_val, path, cmds, delete_missing):
+ if isinstance(want_val, dict):
+ if not want_val:
+ if not have_val:
+ cmds.append(("set", denormalize_path(path)))
+ else:
+ have_dict = have_val if isinstance(have_val, dict) else {}
+ _diff_dict(want_val, have_dict, path, cmds, delete_missing)
+ elif isinstance(want_val, list):
+ have_set = set(have_val) if isinstance(have_val, list) else set()
+ for item in want_val:
+ if item not in have_set:
+ cmds.append(("set", denormalize_path(path + [str(item)])))
+ if delete_missing:
+ want_set = set(str(i) for i in want_val)
+ for item in have_val or []:
+ if str(item) not in want_set:
+ cmds.append(("delete", denormalize_path(path + [str(item)])))
+ else:
+ if want_val != have_val:
+ cmds.append(("set", denormalize_path(path + [str(want_val)])))
+
+
+def _diff_dict(want, have, path, cmds, delete_missing):
+ for key, want_val in want.items():
+ _diff_value(want_val, have.get(key), path + [key], cmds, delete_missing)
+ if delete_missing:
+ for key in have:
+ if key not in want:
+ cmds.append(("delete", denormalize_path(path + [key])))
+
+
+def diff_configs(want, have, base_path, delete_missing=False):
+ """Diff two normalized config dicts and return API command tuples.
+
+ Args:
+ want (dict): Desired configuration (snake_case keys).
+ have (dict): Current configuration (snake_case keys).
+ base_path (list): Base API path for commands.
+ delete_missing (bool): Generate delete commands for keys in
+ ``have`` absent from ``want``.
+
+ Returns:
+ list: Tuples of ``("set", path)`` or ``("delete", path)``.
+ """
+ cmds = []
+ _diff_dict(want, have, base_path, cmds, delete_missing)
+ return cmds
+
+
class VyOSModule:
"""Thin wrapper around VyOSRestClient for resource modules.