diff --git a/CHANGELOG.md b/CHANGELOG.md
index d11dc535..057e7e9d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,8 @@ Expected: October 2024
### Features
+* New `clixon-autocli@2024-08-01.yang` revision
+ - Added: disable operation for module rules
* Optimize YANG memory
* Added union and extended struct for uncommon fields
* Removed per-object YANG linenr info
@@ -23,7 +25,7 @@ Expected: October 2024
* New: [CLI simple alias](https://github.com/clicon/cligen/issues/112)
* See: https://clixon-docs.readthedocs.io/en/latest/cli.html#cli-aliases
* List pagination: Added where, sort-by and direction parameter for configured data
-* New `clixon-lib@2024-04-01.yang` revision
+* New `clixon-lib@2024-08-01.yang` revision
- Added: list-pagination-partial-state extension
### API changes on existing protocol/config features
diff --git a/apps/cli/cli_autocli.c b/apps/cli/cli_autocli.c
index 8252c514..7a7e479f 100644
--- a/apps/cli/cli_autocli.c
+++ b/apps/cli/cli_autocli.c
@@ -59,8 +59,9 @@
/* Mapping from YANG autocli-op to C enum */
static const map_str2int autocli_op_map[] = {
{"enable", AUTOCLI_OP_ENABLE},
+ {"disable", AUTOCLI_OP_DISABLE},
{"compress", AUTOCLI_OP_COMPRESS},
- {NULL, -1}
+ {NULL, -1}
};
/* Mapping from YANG list-keyword-type to C enum */
@@ -68,7 +69,7 @@ static const map_str2int list_kw_map[] = {
{"kw-none", AUTOCLI_LISTKW_NONE},
{"kw-nokey", AUTOCLI_LISTKW_NOKEY},
{"kw-all", AUTOCLI_LISTKW_ALL},
- {NULL, -1}
+ {NULL, -1}
};
@@ -108,6 +109,7 @@ autocli_listkw_int2str(int listkw)
* @param[out] enablep Include this module in autocli
* @retval 0 OK, and enablep set
* @retval -1 Error
+ * Special rule: module-default=false and no operation=enable rules is disable
*/
int
autocli_module(clixon_handle h,
@@ -120,6 +122,7 @@ autocli_module(clixon_handle h,
char *str;
char *element;
int enable = 0;
+ int op;
cxobj *xautocli;
char *body;
@@ -136,18 +139,18 @@ autocli_module(clixon_handle h,
goto done;
}
enable = strcmp(str, "true") == 0;
- if (!enable){
- xrule = NULL;
- while ((xrule = xml_child_each(xautocli, xrule, CX_ELMNT)) != NULL) {
- if (strcmp(xml_name(xrule), "rule") != 0)
- continue;
- if ((str = xml_find_body(xrule, "operation")) == NULL)
- continue;
- /* Peek in element of rule to skip non-compress operations */
- if (autocli_str2op(str) != AUTOCLI_OP_ENABLE)
- continue;
- /* At this point this rule is a compress rule
- * enable rules logic is:
+ if (enable && modname == NULL)
+ goto ok;
+ xrule = NULL;
+ while ((xrule = xml_child_each(xautocli, xrule, CX_ELMNT)) != NULL) {
+ if (strcmp(xml_name(xrule), "rule") != 0)
+ continue;
+ if ((str = xml_find_body(xrule, "operation")) == NULL)
+ continue;
+ /* Skip other than enable/disable */
+ op = autocli_str2op(str);
+ if (!enable && op == AUTOCLI_OP_ENABLE) {
+ /* Enable rules logic is:
* - If match, break, done
*/
xmod = NULL;
@@ -168,6 +171,23 @@ autocli_module(clixon_handle h,
break;
}
}
+ else if (enable && op == AUTOCLI_OP_DISABLE) {
+ xmod = NULL;
+ while ((xmod = xml_child_each(xrule, xmod, CX_ELMNT)) != NULL) {
+ if ((element = xml_name(xmod)) == NULL)
+ continue;
+ if (strcmp(element, "module-name") == 0){
+ if ((body = xml_body(xmod)) == NULL)
+ continue; /* invalid rule? */
+ if (fnmatch(body, modname, 0) == 0)
+ break; /* match */
+ }
+ }
+ if (xmod != NULL){ /* break: found match */
+ enable = 0;
+ break;
+ }
+ }
}
ok:
*enablep = enable;
diff --git a/apps/cli/cli_autocli.h b/apps/cli/cli_autocli.h
index ac687f97..64949daf 100644
--- a/apps/cli/cli_autocli.h
+++ b/apps/cli/cli_autocli.h
@@ -44,6 +44,7 @@
*/
enum autocli_op{
AUTOCLI_OP_ENABLE,
+ AUTOCLI_OP_DISABLE,
AUTOCLI_OP_COMPRESS,
};
diff --git a/example/main/Makefile.in b/example/main/Makefile.in
index 844e4da0..8510382d 100644
--- a/example/main/Makefile.in
+++ b/example/main/Makefile.in
@@ -179,6 +179,7 @@ install: $(YANGSPECS) $(CLISPECS) $(PLUGINS) $(APPNAME).xml restconf.xml autocli
[ -n "$$(getent group "$(CLICON_GROUP)")" ] || groupadd "$(CLICON_GROUP)"
[ -n "$$(getent passwd "$(CLICON_USER)")" ] || useradd -M -s /usr/sbin/nologin -g "$(CLICON_GROUP)" "$(CLICON_USER)"
install -d -m 0755 $(DESTDIR)$(sysconfdir)/clixon
+ install -d -m 0755 $(DESTDIR)$(sysconfdir)/clixon/$(APPNAME)
install -m 0644 $(APPNAME).xml $(DESTDIR)$(sysconfdir)/clixon
install -m 0644 autocli.xml $(DESTDIR)$(sysconfdir)/clixon/$(APPNAME)
install -m 0644 restconf.xml $(DESTDIR)$(sysconfdir)/clixon/$(APPNAME)
diff --git a/example/main/autocli.xml b/example/main/autocli.xml
index 6d92bd0a..78ebc5fe 100644
--- a/example/main/autocli.xml
+++ b/example/main/autocli.xml
@@ -1,14 +1,14 @@
- false
+ true
kw-nokey
false
list container
true
- include clixon-example
- clixon-example
- enable
+ exclude nacm
+ ietf-netconf-acm
+ disable
diff --git a/lib/src/clixon_xpath.c b/lib/src/clixon_xpath.c
index b47f8eb3..841fc73a 100644
--- a/lib/src/clixon_xpath.c
+++ b/lib/src/clixon_xpath.c
@@ -1096,7 +1096,7 @@ xpath_traverse_canonical(xpath_tree *xs,
* Then incoming:
* xpath0: /x/c:y
* nsc0: NULL:"urn:example:a"; c:"urn:example:b"
- * will be translated to:
+ * is translated to:
* xpath1: /a:x/b:y
* nsc1: a:"urn:example:a"; b:"urn:example:b"
* @code
diff --git a/yang/clixon/clixon-autocli@2023-05-01.yang b/yang/clixon/clixon-autocli@2023-05-01.yang
deleted file mode 100644
index 9c05806c..00000000
--- a/yang/clixon/clixon-autocli@2023-05-01.yang
+++ /dev/null
@@ -1,278 +0,0 @@
-module clixon-autocli{
- yang-version 1.1;
- namespace "http://clicon.org/autocli";
- prefix autocli;
-
- organization
- "Clicon / Clixon";
-
- contact
- "Olof Hagsand ";
-
- description
- "Clixon CLIgen specification declarations, including autocli.
- Design inspired by ietf-netconf-acm.yang
-
- ***** BEGIN LICENSE BLOCK *****
- Copyright (C) 2020-2021 Olof Hagsand and Rubicon Communications, LLC(Netgate)
-
- This file is part of CLIXON
-
- Licensed under the Apache License, Version 2.0 (the \"License\");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an \"AS IS\" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- Alternatively, the contents of this file may be used under the terms of
- the GNU General Public License Version 3 or later (the \"GPL\"),
- in which case the provisions of the GPL are applicable instead
- of those above. If you wish to allow use of your version of this file only
- under the terms of the GPL, and not to allow others to
- use your version of this file under the terms of Apache License version 2,
- indicate your decision by deleting the provisions above and replace them with
- the notice and other provisions required by the GPL. If you do not delete
- the provisions above, a recipient may use your version of this file under
- the terms of any one of the Apache License version 2 or the GPL.
-
- ***** END LICENSE BLOCK *****";
-
- revision 2023-05-01 {
- description
- "Added extensions skip and alias
- Added grouping-treeref
- Released in Clixon 6.3";
- }
- revision 2022-02-11 {
- description
- "Released in Clixon 5.6";
- }
- revision 2021-12-05 {
- description
- "Initial version
- Released in Clixon 5.5";
- }
- extension hide {
- description
- "Hide the command associated with a YANG node and its
- sub-commands.
- The command is active but not shown by ? or TAB. In other words, it hides the
- auto-completion of commands";
- }
- extension hide-show {
- description
- "Hide the command associated with a YANG node and its
- sub-commands in CLI show commands.";
- }
- extension skip {
- description
- "Skip the command associated with a YANG node and its sub-commands altogether.
- The command is completely removed from the CLI, but still exists in NETCONF/
- RESTCONF.";
- }
- extension strict-expand {
- description
- "Modify the autocli by only showing exactly the expanded values of a variable.
- It should not be possible to add a new value that is not in the expanded list.";
- }
- extension alias {
- description
- "Replace the command name with a new value.
- Instead of using the YANG argument name, use this instead";
- }
- typedef autocli-op {
- description
- "Autocli rule-type operation, each rule use different fields as
- described in the individual enums below.";
- type enumeration {
- enum enable {
- description
- "Include a complete subtree to rendering of autocli.
- Example:
- false
-
- wifi
- enable
- openconfig-wifi
-
- Only on module-level and if module-default is false,
- Rule fields used: module-name";
- }
- enum compress {
- description
- "Skip a keyword from a command.
- Keep the command, only make it shorter by omitting a part.
- Example: compress containers if single list child
-
- container compress
- compress
- container
- list
-
- Rule fields used:
- module-name, yang-keyword, schema-nodeid, yang-keyword-child, extension";
- }
- enum edit-mode {
- description
- "Autocli CLI edit modes for YANG symbols.
- For example,
- edit interface eth0
- enters a new mode with local context.";
- }
- }
- }
- typedef list-keyword-type {
- description
- "Autocli CLI keyword behaviour in YANG lists.
- With 'keyword' is meant CLIgen 'constants' rather than 'variables'.
- Assume a YANG LIST: list a{ key x; leaf x; leaf y;} and how to generate
- the autocli";
- type enumeration {
- enum kw-none{
- description "No extra keywords, only variables: a ";
- }
- enum kw-nokey{
- description "Keywords on non-key variables: a y ";
- }
- enum kw-all{
- description "Keywords on all variables: a x y ";
- }
- }
- }
- typedef yang-keywords {
- type bits {
- bit list;
- bit listall{ /* NYI */
- description
- "Variant of list encompassing all list entries, not just an instance";
- }
- bit container;
- bit leaf; /* Also leaf-list (NYI) */
- }
- }
- grouping clixon-autocli{
- /* options */
- leaf module-default {
- description
- "Include YANG modules for generation of autocli.
- If true, all modules with a top-level datanode are generated, ie
- they get a top-level entry in the @basemodel tree.
- If false, you need to explicitly enable modules for autocli generation
- using 'enable' rules";
- type boolean;
- default true;
- }
- leaf list-keyword-default {
- description
- "Autocli CLI keyword behaviour in YANG lists.";
- type list-keyword-type;
- default kw-nokey;
- }
- leaf treeref-state-default {
- description
- "If 'true', generate CLI from YANG state/non-config statements as well, not only config data.
- Many specs have very large state parts, for example openconfig has ca 10 times
- larger state than config parts, see for example openconfig-isis.yang.";
- type boolean;
- default false;
- }
- leaf edit-mode-default {
- description
- "Open automatic edit-modes for some YANG keywords and do not allow others.
- A CLI edit mode opens a carriage-return option and changes the context to be
- in that local context.
- For example:
- cli> interfaces interface e0
- eth0>
- Default is to generate edit-modes for all containers and lists.";
- type yang-keywords;
- default "list container";
- }
- leaf completion-default {
- description
- "Generate code for CLI completion of existing db symbols.
- That is, check existing configure database for completion options.
- This is normally always enabled.";
- type boolean;
- default true;
- }
- leaf grouping-treeref {
- description
- "Controls the behaviour when generating CLISPEC of YANG 'uses' statements into the
- corresponding 'grouping' definition: macro expansion.
- For optimization of memory footprint.
- If 'false', replace the uses definition with the grouping definition.
- If 'true' use indirect tree reference '@treeref' to reference the grouping definition. This
- saves memory for large YANGs.
-
- See also AUTOCLI_GROUPING_TOPLEVEL_SKIP and AUTOCLI_GROUPING_AUGMENT_SKIP for
- temporary disabled cornercases.
- This option was introduced in Clixon 6.3";
- type boolean;
- default false;
- }
- /* rules */
- list rule {
- description
- "Represents a modification rule of a clixon clispec.";
- key name;
- leaf name {
- description
- "Arbitrary name assigned for the rule, must be unique";
- type string;
- }
- leaf description {
- description
- "Rule description";
- type string;
- }
- leaf operation {
- description "Rule operation";
- type autocli-op;
- }
- leaf module-name {
- description
- "Name of the module associated with this rule.
- Wildchars '*' and '?' can be used (glob pattern).
- Revision and yang suffix are omitted
- Example: 'openconfig-*'";
- type string;
- }
- leaf yang-keyword {
- description
- "If present identifes a YANG keyword which the rule applies to
- Example: 'container'
- ";
- type string;
- }
- leaf schema-nodeid {
- description
- "path in the form of // or just a single identifying a YANG
- schema-node identifier as defined in RFC 7950 Sec 6.5
- Example: 'config', '/interfaces/interface'";
- type string;
- }
- leaf yang-keyword-child {
- description
- "The YANG statement has a single child, and the yang type of the child is the
- value of this option
- A (maybe too) specific property to cover openconfig compressions
- as defined here:
- https://github.com/openconfig/ygot/blob/master/docs/design.md#openconfig-path-compression";
- type string;
- }
- leaf extension {
- /* Consider making this a container with name/module/value instead */
- description
- "The extension is set either in the node itself, or in this module
- Extension prefix must be set
- Example: oc-ext:openconfig-version";
- type string;
- }
- }
- }
-}