diff options
author | Daniil Baturin <daniil@vyos.io> | 2025-06-19 16:14:10 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-06-19 16:14:10 +0100 |
commit | 1d59e897925f5298c48e57c7a34522113e7115c3 (patch) | |
tree | ab40bd8f628d5305fd3208b96b122be38ba7a9b7 | |
parent | ded75e2a7a611fb285f015cbc9d7b6cf66b84701 (diff) | |
parent | 9e7832e1fc744ef98272950c324738495c08a5a4 (diff) | |
download | vyos-1x-1d59e897925f5298c48e57c7a34522113e7115c3.tar.gz vyos-1x-1d59e897925f5298c48e57c7a34522113e7115c3.zip |
Merge pull request #4555 from dmbaturin/T7541-standalone-tag-node-support
op-mode: T7542: add support for "standalone" behavior of operational mode tag nodes
-rw-r--r-- | schema/op-mode-definition.rnc | 24 | ||||
-rw-r--r-- | schema/op-mode-definition.rng | 35 | ||||
-rwxr-xr-x | scripts/build-command-op-templates | 27 |
3 files changed, 74 insertions, 12 deletions
diff --git a/schema/op-mode-definition.rnc b/schema/op-mode-definition.rnc index ad41700b9..46430daa4 100644 --- a/schema/op-mode-definition.rnc +++ b/schema/op-mode-definition.rnc @@ -1,6 +1,6 @@ # interface_definition.rnc: VyConf reference tree XML grammar # -# Copyright (C) 2014. 2017 VyOS maintainers and contributors <maintainers@vyos.net> +# Copyright (C) 2014-2025 VyOS maintainers and contributors <maintainers@vyos.net> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -37,13 +37,27 @@ node = element node } # Tag nodes are containers for nodes without predefined names, like network interfaces -# or user names (e.g. "interfaces ethernet eth0" or "user jrandomhacker") -# Tag nodes may contain node and leafNode elements, and also nameConstraint tags -# They must not contain other tag nodes +# or user names (e.g. "show interfaces ethernet ethX"). +# Operational mode tag nodes can be parents to other tag nodes, +# like in "ping <host> count <packets>". +# +# Some commands can be called either with or without arguments, +# like "show interfaces ethernet eth0" (show info for eth0 only) +# or "show interfaces ethernet" (show info about all ethernet interfaces). +# That case is handled using the <standalone> element tagNode = element tagNode { nodeNameAttr, - (properties? & children? & command?) + (properties? & standalone? & children? & command?) +} + +# The <standalone> element is only used inside tag nodes +# to define their behavior when they are called without arguments +# It can provide a help string and a command. +# Everything else is handled in the <tagNode> itself. +standalone = element standalone +{ + help & command } # Leaf nodes are terminal configuration nodes that can't have children, diff --git a/schema/op-mode-definition.rng b/schema/op-mode-definition.rng index a255aeb73..bfd5cb50a 100644 --- a/schema/op-mode-definition.rng +++ b/schema/op-mode-definition.rng @@ -3,7 +3,7 @@ <!-- interface_definition.rnc: VyConf reference tree XML grammar - Copyright (C) 2014. 2017 VyOS maintainers and contributors <maintainers@vyos.net> + Copyright (C) 2014-2025 VyOS maintainers and contributors <maintainers@vyos.net> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -59,9 +59,14 @@ </define> <!-- Tag nodes are containers for nodes without predefined names, like network interfaces - or user names (e.g. "interfaces ethernet eth0" or "user jrandomhacker") - Tag nodes may contain node and leafNode elements, and also nameConstraint tags - They must not contain other tag nodes + or user names (e.g. "show interfaces ethernet ethX"). + Operational mode tag nodes can be parents to other tag nodes, + like in "ping <host> count <packets>". + + Some commands can be called either with or without arguments, + like "show interfaces ethernet eth0" (show info for eth0 only) + or "show interfaces ethernet" (show info about all ethernet interfaces). + That case is handled using the <standalone> element --> <define name="tagNode"> <element name="tagNode"> @@ -71,6 +76,9 @@ <ref name="properties"/> </optional> <optional> + <ref name="standalone"/> + </optional> + <optional> <ref name="children"/> </optional> <optional> @@ -80,6 +88,20 @@ </element> </define> <!-- + The <standalone> element is only used inside tag nodes + to define their behavior when they are called without arguments + It can provide a help string and a command. + Everything else is handled in the <tagNode> itself. + --> + <define name="standalone"> + <element name="standalone"> + <interleave> + <ref name="help"/> + <ref name="command"/> + </interleave> + </element> + </define> + <!-- Leaf nodes are terminal configuration nodes that can't have children, but can have values. --> @@ -139,10 +161,11 @@ <!-- completionHelp tags contain information about allowed values of a node that is used for generating tab completion in the CLI frontend and drop-down lists in GUI frontends - It is only meaninful for leaf nodes + It is only meaningful for leaf nodes Allowed values can be given as a fixed list of values (e.g. <list>foo bar baz</list>), as a configuration path (e.g. <path>interfaces ethernet</path>), - or as a path to a script file that generates the list (e.g. <script>/usr/lib/foo/list-things</script> + as a path to a script file that generates the list (e.g. <script>/usr/lib/foo/list-things</script>, + or to enable built-in image path completion (<imagePath/>). --> <define name="completionHelp"> <element name="completionHelp"> diff --git a/scripts/build-command-op-templates b/scripts/build-command-op-templates index 0bb62113e..9eef25a2f 100755 --- a/scripts/build-command-op-templates +++ b/scripts/build-command-op-templates @@ -124,6 +124,26 @@ def get_properties(p): return props +def get_standalone(s): + standalone = {} + + if s is None: + return {} + + # Get the help string + try: + standalone["help"] = s.find("help").text + except: + standalone["help"] = "No help available" + + # Get the command -- it's required by the schema + try: + standalone["command"] = s.find("command") + except: + raise AssertionError("Found a <standalone> node without <command>") + + return standalone + def make_node_def(props, command): # XXX: replace with a template processor if it grows @@ -150,6 +170,7 @@ def process_node(n, tmpl_dir): my_tmpl_dir = copy.copy(tmpl_dir) props_elem = n.find("properties") + standalone_elem = n.find("standalone") children = n.find("children") command = n.find("command") name = n.get("name") @@ -163,6 +184,7 @@ def process_node(n, tmpl_dir): os.makedirs(make_path(my_tmpl_dir), exist_ok=True) props = get_properties(props_elem) + standalone = get_standalone(standalone_elem) nodedef_path = os.path.join(make_path(my_tmpl_dir), "node.def") if node_type == "node": @@ -189,7 +211,10 @@ def process_node(n, tmpl_dir): # does not exist at all. if not os.path.exists(nodedef_path) or os.path.getsize(nodedef_path) == 0: with open(nodedef_path, "w") as f: - f.write('help: {0}\n'.format(props['help'])) + if standalone: + f.write(make_node_def(standalone, standalone["command"])) + else: + f.write('help: {0}\n'.format(props['help'])) # Create the inner node.tag part my_tmpl_dir.append("node.tag") |