summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Estabrook <jestabro@vyos.io>2021-06-23 21:02:07 -0500
committerGitHub <noreply@github.com>2021-06-23 21:02:07 -0500
commit1a7362622783804c72862e84b68bf065b1dabc19 (patch)
tree7a386e52ea9122966619f14c29a79d97cc82dda0
parentd48dddab0509e562209adfb115b0e691b8e47f54 (diff)
parent59a4aadfe419eca16e6288b37d6c51acd9789903 (diff)
downloadvyos-1x-1a7362622783804c72862e84b68bf065b1dabc19.tar.gz
vyos-1x-1a7362622783804c72862e84b68bf065b1dabc19.zip
Merge pull request #869 from jestabro/T3574
T3574: add constraintGroup to schema and build-command-templates
-rw-r--r--python/vyos/xml/load.py3
-rw-r--r--schema/interface_definition.rnc11
-rw-r--r--schema/interface_definition.rng21
-rwxr-xr-xscripts/build-command-templates76
4 files changed, 81 insertions, 30 deletions
diff --git a/python/vyos/xml/load.py b/python/vyos/xml/load.py
index 0965d4220..37479c6e1 100644
--- a/python/vyos/xml/load.py
+++ b/python/vyos/xml/load.py
@@ -225,6 +225,9 @@ def _format_node(inside, conf, xml):
else:
_fatal(constraint)
+ elif 'constraintGroup' in properties:
+ properties.pop('constraintGroup')
+
elif 'constraintErrorMessage' in properties:
r[kw.error] = properties.pop('constraintErrorMessage')
diff --git a/schema/interface_definition.rnc b/schema/interface_definition.rnc
index 6647f5e11..d7fc4966c 100644
--- a/schema/interface_definition.rnc
+++ b/schema/interface_definition.rnc
@@ -93,6 +93,7 @@ properties = element properties
{
help? &
constraint? &
+ constraintGroup* &
valueHelp* &
(element constraintErrorMessage { text })? &
completionHelp* &
@@ -140,6 +141,16 @@ constraint = element constraint
validator )+
}
+# Tag and leaf nodes may have constraintGroups on their names and
+# values (respectively).
+# When multiple constraints are listed within a group, they work as
+# logical AND
+constraintGroup = element constraintGroup
+{
+ ( (element regex { text }) |
+ validator )+
+}
+
# A constraint may also use an external validator rather than regex
validator = element validator
{
diff --git a/schema/interface_definition.rng b/schema/interface_definition.rng
index 22e886006..3ff60cf18 100644
--- a/schema/interface_definition.rng
+++ b/schema/interface_definition.rng
@@ -161,6 +161,9 @@
<ref name="constraint"/>
</optional>
<zeroOrMore>
+ <ref name="constraintGroup"/>
+ </zeroOrMore>
+ <zeroOrMore>
<ref name="valueHelp"/>
</zeroOrMore>
<optional>
@@ -244,6 +247,24 @@
</oneOrMore>
</element>
</define>
+ <!--
+ Tag and leaf nodes may have constraintGroups on their names and
+ values (respectively).
+ When multiple constraints are listed within a group, they work as
+ logical AND
+ -->
+ <define name="constraintGroup">
+ <element name="constraintGroup">
+ <oneOrMore>
+ <choice>
+ <element name="regex">
+ <text/>
+ </element>
+ <ref name="validator"/>
+ </choice>
+ </oneOrMore>
+ </element>
+ </define>
<!-- A constraint may also use an external validator rather than regex -->
<define name="validator">
<element name="validator">
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