From faaad2e029fd3520b62983dd78c7692434138360 Mon Sep 17 00:00:00 2001
From: Thomas Mangin <thomas.mangin@exa.net.uk>
Date: Wed, 22 Jul 2020 23:36:44 +0100
Subject: xml: T2582: use xml for is_tag and is_leaf

---
 python/vyos/validate.py       |  7 ++++---
 python/vyos/xml/__init__.py   | 15 +++++++++++++++
 python/vyos/xml/definition.py | 23 +++++++++++++++++++----
 python/vyos/xml/test_xml.py   |  2 +-
 4 files changed, 39 insertions(+), 8 deletions(-)

(limited to 'python')

diff --git a/python/vyos/validate.py b/python/vyos/validate.py
index 9072c5817..a0620e4dd 100644
--- a/python/vyos/validate.py
+++ b/python/vyos/validate.py
@@ -19,6 +19,7 @@ import netifaces
 import ipaddress
 
 from vyos.util import cmd
+from vyos import xml
 
 # Important note when you are adding new validation functions:
 #
@@ -293,12 +294,12 @@ def is_member(conf, interface, intftype=None):
     for it in intftype:
         base = 'interfaces ' + it
         for intf in conf.list_nodes(base):
-            memberintf = f'{base} {intf} member interface'
-            if conf.is_tag(memberintf):
+            memberintf = [base, intf, 'member', 'interface']
+            if xml.is_tag(memberintf):
                 if interface in conf.list_nodes(memberintf):
                     ret_val = intf
                     break
-            elif conf.is_leaf(memberintf):
+            elif xml.is_leaf(memberintf):
                 if ( conf.exists(memberintf) and
                         interface in conf.return_values(memberintf) ):
                     ret_val = intf
diff --git a/python/vyos/xml/__init__.py b/python/vyos/xml/__init__.py
index 6e0e73b1b..0f914fed2 100644
--- a/python/vyos/xml/__init__.py
+++ b/python/vyos/xml/__init__.py
@@ -35,6 +35,18 @@ def load_configuration(cache=[]):
     return xml
 
 
+# def is_multi(lpath):
+#     return load_configuration().is_multi(lpath)
+
+
+def is_tag(lpath):
+    return load_configuration().is_tag(lpath)
+
+
+def is_leaf(lpath, flat=True):
+    return load_configuration().is_leaf(lpath, flat)
+
+
 def defaults(lpath, flat=False):
     return load_configuration().defaults(lpath, flat)
 
@@ -42,3 +54,6 @@ def defaults(lpath, flat=False):
 if __name__ == '__main__':
     print(defaults(['service'], flat=True))
     print(defaults(['service'], flat=False))
+
+    print(is_tag(["system", "login", "user", "vyos", "authentication", "public-keys"]))
+    print(is_tag(['protocols', 'static', 'multicast', 'route', '0.0.0.0/0', 'next-hop']))
diff --git a/python/vyos/xml/definition.py b/python/vyos/xml/definition.py
index b0339b228..098e64f7e 100644
--- a/python/vyos/xml/definition.py
+++ b/python/vyos/xml/definition.py
@@ -126,10 +126,12 @@ class XML(dict):
         elif word:
             if data_node != kw.plainNode or len(passed) == 1:
                 self.options = [_ for _ in self.tree if _.startswith(word)]
+                self.options.sort()
             else:
                 self.options = []
         else:
             self.options = named_options
+            self.options.sort()
 
         self.plain = not is_dataNode
 
@@ -143,6 +145,7 @@ class XML(dict):
             self.word = ''
             if self.tree.get(kw.node,'') not in (kw.tagNode, kw.leafNode):
                 self.options = [_ for _ in self.tree if not kw.found(_)]
+                self.options.sort()
 
     def checks(self, cmd):
         # as we move thought the named node twice
@@ -300,16 +303,28 @@ class XML(dict):
         return tree
 
     def _get(self, lpath, tag, with_tag=True):
-        return self._tree(lpath + [tag], with_tag)
+        tree = self._tree(lpath, with_tag)
+        if tree is None:
+            return None
+        return tree.get(tag, None)
 
     def is_multi(self, lpath, with_tag=True):
-        return self._get(lpath, kw.multi, with_tag) is True
+        tree = self._get(lpath, kw.multi, with_tag)
+        if tree is None:
+            return None
+        return tree is True
 
     def is_tag(self, lpath, with_tag=True):
-        return self._get(lpath, kw.node, with_tag) == kw.tagNode
+        tree = self._get(lpath, kw.node, with_tag)
+        if tree is None:
+            return None
+        return tree == kw.tagNode
 
     def is_leaf(self, lpath, with_tag=True):
-        return self._get(lpath, kw.node, with_tag) == kw.leafNode
+        tree = self._get(lpath, kw.node, with_tag)
+        if tree is None:
+            return None
+        return tree == kw.leafNode
 
     def exists(self, lpath, with_tag=True):
         return self._get(lpath, kw.node, with_tag) is not None
diff --git a/python/vyos/xml/test_xml.py b/python/vyos/xml/test_xml.py
index ac0620d99..ff55151d2 100644
--- a/python/vyos/xml/test_xml.py
+++ b/python/vyos/xml/test_xml.py
@@ -33,7 +33,7 @@ class TestSearch(TestCase):
         last = self.xml.traverse("")
         self.assertEqual(last, '')
         self.assertEqual(self.xml.inside, [])
-        self.assertEqual(self.xml.options, ['protocols', 'service', 'system', 'firewall', 'interfaces', 'vpn', 'nat', 'vrf', 'high-availability'])
+        self.assertEqual(self.xml.options, ['firewall', 'high-availability', 'interfaces', 'nat', 'protocols', 'service', 'system', 'vpn', 'vrf'])
         self.assertEqual(self.xml.filling, False)
         self.assertEqual(self.xml.word, last)
         self.assertEqual(self.xml.check, False)
-- 
cgit v1.2.3