From 694096f108c3421d4ff11ad75eec3bfb1cde562b Mon Sep 17 00:00:00 2001 From: John Estabrook Date: Fri, 10 Feb 2023 14:53:02 -0600 Subject: config_mgmt: T4991: use configtree.show_diff instead of Python difflib --- python/vyos/config_mgmt.py | 43 +++++++++++++------------------------------ python/vyos/configtree.py | 32 +++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 31 deletions(-) (limited to 'python') diff --git a/python/vyos/config_mgmt.py b/python/vyos/config_mgmt.py index 22a49ff50..fade3081c 100644 --- a/python/vyos/config_mgmt.py +++ b/python/vyos/config_mgmt.py @@ -24,7 +24,7 @@ from datetime import datetime from tabulate import tabulate from vyos.config import Config -from vyos.configtree import ConfigTree +from vyos.configtree import ConfigTree, ConfigTreeError, show_diff from vyos.defaults import directories from vyos.util import is_systemd_service_active, ask_yes_no, rc_cmd @@ -93,15 +93,7 @@ class ConfigMgmt: # a call to compare without args is edit_level aware edit_level = os.getenv('VYATTA_EDIT_LEVEL', '') - edit_path = [l for l in edit_level.split('/') if l] - if edit_path: - eff_conf = config.show_config(edit_path, effective=True) - self.edit_level_active_config = ConfigTree(eff_conf) - conf = config.show_config(edit_path) - self.edit_level_working_config = ConfigTree(conf) - else: - self.edit_level_active_config = None - self.edit_level_working_config = None + self.edit_path = [l for l in edit_level.split('/') if l] self.active_config = config._running_config self.working_config = config._session_config @@ -241,14 +233,8 @@ Proceed ?''' revision n vs. revision m; working version vs. active version; or working version vs. saved version. """ - from difflib import unified_diff - - ct1 = self.edit_level_active_config - if ct1 is None: - ct1 = self.active_config - ct2 = self.edit_level_working_config - if ct2 is None: - ct2 = self.working_config + ct1 = self.active_config + ct2 = self.working_config msg = 'No changes between working and active configurations.\n' if saved: ct1 = self._get_saved_config_tree() @@ -268,19 +254,16 @@ Proceed ?''' ct1 = self._get_config_tree_revision(rev2) msg = f'No changes between revisions {rev2} and {rev1} configurations.\n' - if commands: - lines1 = ct1.to_commands().splitlines(keepends=True) - lines2 = ct2.to_commands().splitlines(keepends=True) - else: - lines1 = ct1.to_string().splitlines(keepends=True) - lines2 = ct2.to_string().splitlines(keepends=True) - out = '' - comp = unified_diff(lines1, lines2) - for line in comp: - if re.match(r'(\-\-)|(\+\+)|(@@)', line): - continue - out += line + path = [] if commands else self.edit_path + try: + if commands: + out = show_diff(ct1, ct2, path=path, commands=True) + else: + out = show_diff(ct1, ct2, path=path) + except ConfigTreeError as e: + return e, 1 + if out: msg = out diff --git a/python/vyos/configtree.py b/python/vyos/configtree.py index f2358ee4f..c0b3ebd78 100644 --- a/python/vyos/configtree.py +++ b/python/vyos/configtree.py @@ -16,7 +16,7 @@ import os import re import json -from ctypes import cdll, c_char_p, c_void_p, c_int +from ctypes import cdll, c_char_p, c_void_p, c_int, c_bool LIBPATH = '/usr/lib/libvyosconfig.so.0' @@ -322,6 +322,36 @@ class ConfigTree(object): subt = ConfigTree(address=res) return subt +def show_diff(left, right, path=[], commands=False, libpath=LIBPATH): + if left is None: + left = ConfigTree(config_string='\n') + if right is None: + right = ConfigTree(config_string='\n') + if not (isinstance(left, ConfigTree) and isinstance(right, ConfigTree)): + raise TypeError("Arguments must be instances of ConfigTree") + if path: + if (not left.exists(path)) and (not right.exists(path)): + raise ConfigTreeError(f"Path {path} doesn't exist") + + check_path(path) + path_str = " ".join(map(str, path)).encode() + + __lib = cdll.LoadLibrary(libpath) + __show_diff = __lib.show_diff + __show_diff.argtypes = [c_bool, c_char_p, c_void_p, c_void_p] + __show_diff.restype = c_char_p + __get_error = __lib.get_error + __get_error.argtypes = [] + __get_error.restype = c_char_p + + res = __show_diff(commands, path_str, left._get_config(), right._get_config()) + res = res.decode() + if res == "#1@": + msg = __get_error().decode() + raise ConfigTreeError(msg) + + return res + class DiffTree: def __init__(self, left, right, path=[], libpath=LIBPATH): if left is None: -- cgit v1.2.3