summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/build-command-templates76
-rwxr-xr-xscripts/override-default38
-rwxr-xr-xscripts/transclude-template50
3 files changed, 128 insertions, 36 deletions
diff --git a/scripts/build-command-templates b/scripts/build-command-templates
index 452c420eb..d8abb0a13 100755
--- a/scripts/build-command-templates
+++ b/scripts/build-command-templates
@@ -86,6 +86,37 @@ def make_path(l):
print(path)
return path
+def collect_validators(ve):
+ regexes = []
+ regex_elements = ve.findall("regex")
+ if regex_elements is not None:
+ regexes = list(map(lambda e: e.text.strip().replace('\\','\\\\'), regex_elements))
+ if "" in regexes:
+ print("Warning: empty regex, node will be accepting any value")
+
+ validator_elements = ve.findall("validator")
+ validators = []
+ if validator_elements is not None:
+ for v in validator_elements:
+ v_name = os.path.join(validator_dir, v.get("name"))
+
+ # XXX: lxml returns None for empty arguments
+ v_argument = None
+ try:
+ v_argument = v.get("argument")
+ except:
+ pass
+ if v_argument is None:
+ v_argument = ""
+
+ validators.append("{0} {1}".format(v_name, v_argument))
+
+
+ regex_args = " ".join(map(lambda s: "--regex \\\'{0}\\\'".format(s), regexes))
+ validator_args = " ".join(map(lambda s: "--exec \\\"{0}\\\"".format(s), validators))
+
+ return regex_args + " " + validator_args
+
def get_properties(p):
props = {}
@@ -108,7 +139,8 @@ def get_properties(p):
except:
props["val_help"] = []
- # Get the constraint statements
+ # Get the constraint and constraintGroup statements
+
error_msg = default_constraint_err_msg
# Get the error message if it's there
try:
@@ -117,40 +149,24 @@ def get_properties(p):
pass
vce = p.find("constraint")
- vc = []
+
+ distinct_validator_string = ""
if vce is not None:
# The old backend doesn't support multiple validators in OR mode
# so we emulate it
- regexes = []
- regex_elements = vce.findall("regex")
- if regex_elements is not None:
- regexes = list(map(lambda e: e.text.strip().replace('\\','\\\\'), regex_elements))
- if "" in regexes:
- print("Warning: empty regex, node will be accepting any value")
-
- validator_elements = vce.findall("validator")
- validators = []
- if validator_elements is not None:
- for v in validator_elements:
- v_name = os.path.join(validator_dir, v.get("name"))
-
- # XXX: lxml returns None for empty arguments
- v_argument = None
- try:
- v_argument = v.get("argument")
- except:
- pass
- if v_argument is None:
- v_argument = ""
-
- validators.append("{0} {1}".format(v_name, v_argument))
-
-
- regex_args = " ".join(map(lambda s: "--regex \\\'{0}\\\'".format(s), regexes))
- validator_args = " ".join(map(lambda s: "--exec \\\"{0}\\\"".format(s), validators))
+ distinct_validator_string = collect_validators(vce)
+
+ vcge = p.findall("constraintGroup")
+
+ group_validator_string = ""
+ if len(vcge):
+ for vcg in vcge:
+ group_validator_string = group_validator_string + " --grp " + collect_validators(vcg)
+
+ if vce is not None or len(vcge):
validator_script = '${vyos_libexec_dir}/validate-value'
- validator_string = "exec \"{0} {1} {2} --value \\\'$VAR(@)\\\'\"; \"{3}\"".format(validator_script, regex_args, validator_args, error_msg)
+ validator_string = "exec \"{0} {1} {2} --value \\\'$VAR(@)\\\'\"; \"{3}\"".format(validator_script, distinct_validator_string, group_validator_string, error_msg)
props["constraint"] = validator_string
diff --git a/scripts/override-default b/scripts/override-default
index c8a0ff1da..0c49087c8 100755
--- a/scripts/override-default
+++ b/scripts/override-default
@@ -27,6 +27,7 @@
import sys
import glob
import logging
+from copy import deepcopy
from lxml import etree
debug = False
@@ -60,30 +61,55 @@ def override_element(l: list):
for el in parents:
el.getparent().remove(el)
+def merge_remaining(l: list, elementtree):
+ """
+ Merge (now) single leaf node containing 'defaultValue' with leaf nodes
+ of same path and no 'defaultValue'.
+ """
+ for p in l:
+ p = p.split()
+ path_str = f'/interfaceDefinition/*'
+ path_list = []
+ for i in range(len(p)):
+ path_list.append(f'[@name="{p[i]}"]')
+ path_str += '/children/*'.join(path_list)
+ rp = elementtree.xpath(path_str)
+ if len(rp) > 1:
+ for el in rp[1:]:
+ # in practice there will only be one child of the path,
+ # either defaultValue or Properties, since
+ # override_element() has already run
+ for child in el:
+ rp[0].append(deepcopy(child))
+ el.getparent().remove(el)
+
def collect_and_override(dir_name):
"""
- Collect elements with defaultValue tag into dictionary indexed by tuple
- of (name: str, ancestor path: str).
+ Collect elements with defaultValue tag into dictionary indexed by name
+ attributes of ancestor path.
"""
for fname in glob.glob(f'{dir_name}/*.xml'):
tree = etree.parse(fname)
root = tree.getroot()
defv = {}
- xpath_str = f'//defaultValue'
+ xpath_str = '//defaultValue'
xp = tree.xpath(xpath_str)
for element in xp:
ap = element.xpath('ancestor::*[@name]')
ap_name = [el.get("name") for el in ap]
- ap_path_str = ' '.join(ap_name[:-1])
- defv.setdefault((ap_name[-1], ap_path_str), []).append(element)
+ ap_path_str = ' '.join(ap_name)
+ defv.setdefault(ap_path_str, []).append(element)
for k, v in defv.items():
if len(v) > 1:
- logger.info(f"overridding default in {k[0]}, path '{k[1]}'")
+ logger.info(f"overridding default in path '{k}'")
override_element(v)
+ to_merge = list(defv)
+ merge_remaining(to_merge, tree)
+
revised_str = etree.tostring(root, encoding='unicode', pretty_print=True)
with open(f'{fname}', 'w') as f:
diff --git a/scripts/transclude-template b/scripts/transclude-template
new file mode 100755
index 000000000..5c6668a84
--- /dev/null
+++ b/scripts/transclude-template
@@ -0,0 +1,50 @@
+#!/usr/bin/env python3
+#
+# transclude-template: preprocessor for XML interface definitions to
+# interpret #include statements to include nested XML fragments and
+# snippets in documents.
+#
+# Copyright (C) 2021 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#
+
+import os
+import re
+import sys
+
+regexp = re.compile(r'^ *#include <(.+)>$')
+
+def parse_file(filename):
+ lines = ""
+ with open(filename, 'r') as f:
+ while True:
+ line = f.readline()
+ if line:
+ result = regexp.match(line)
+ if result:
+ lines += parse_file(os.path.join(directory, result.group(1)))
+ else:
+ lines += line
+ else:
+ return lines
+
+if __name__ == '__main__':
+ if len(sys.argv) < 2:
+ print('Must specify XML file!', file=sys.stderr)
+ sys.exit(1)
+ filename = sys.argv[1]
+ directory = os.path.dirname(os.path.abspath(filename))
+ print(parse_file(filename))
+