diff --git a/CHANGELOG.md b/CHANGELOG.md index 10f849c7..cb09a708 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,12 @@ ## 6.4.0 Expected: October 2023 +### API changes on existing protocol/config features +Users may have to change how they access the system + +* New `clixon-autocli@2023-09-01.yang` revision + * Added argument to alias extension + ### C/CLI-API changes on existing features Developers may need to change their code @@ -52,6 +58,8 @@ Developers may need to change their code ### Minor features * Example cli pipe grep command quotes vertical bar for OR function +* Added: [Feature request: node's alias for CLI](https://github.com/clicon/clixon/issues/434) + * Note: "Skip" is for all nodes, but "Alias" is only for leafs * New command-line option for dumping configuration options for all clixon applications after load * Syntax is `-C ` * Example: `clixon_backend -1C json` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fa39db4a..bae174ca 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -45,6 +45,9 @@ static int myfn(int par1, my_structure *par2); ### Errors +Error handling follows the "fail early and loud" principle. That is, unless a specific error-handling +is identified, exit as soon as possible and with an explicit error log. + Errors are typically declared as follows: ``` if (myfn(0) < 0){ diff --git a/README.md b/README.md index d3a117b6..eab75427 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,6 @@ Clixon has a master branch continuously tested with CI, but releases with more t Clixon interaction is best done posting issues, pull requests, or joining the Matrix clixon forum https://matrix.to/#/#clixonforum:matrix.org. -Other clixon projects include [CLIgen](https://github.com/clicon/cligen), [the Clixon controller](https://github.com/clicon/clixon-controller), [clixon applications](https://github.com/clicon/clixon-examples) and others. +Other clixon projects include [CLIgen](https://github.com/clicon/cligen), [the Clixon controller](https://github.com/clicon/clixon-controller), [Clixon applications](https://github.com/clicon/clixon-examples) and others. Clixon is sponsored by [Rubicon Communications LLC(Netgate)](https://www.netgate.com/) and [Akamai Technologies, Inc.](https://www.akamai.com). diff --git a/apps/backend/backend_plugin_restconf.c b/apps/backend/backend_plugin_restconf.c index 83ec2ed4..b43489f4 100644 --- a/apps/backend/backend_plugin_restconf.c +++ b/apps/backend/backend_plugin_restconf.c @@ -214,7 +214,7 @@ restconf_rpc_wrapper(clicon_handle h, } else{ /* Get debug flag of restconf config, set the restconf start -D daemon flag according - * to it. The restconf daemon cannoit read its debug flag from config initially, + * to it. The restconf daemon cannot read its debug flag from config initially, * but in this way it is set directly in its input args. * Its a trick. */ diff --git a/apps/cli/cli_generate.c b/apps/cli/cli_generate.c index 1518ac13..6d94ee12 100644 --- a/apps/cli/cli_generate.c +++ b/apps/cli/cli_generate.c @@ -115,8 +115,8 @@ You can see which CLISPEC it generates via clixon_cli -D 2: * @param[in] options * @param[in] fraction_digits * @param[out] cb The string where the result format string is inserted. - * @retval 1 Hide, dont show helptext etc - * @retval 0 OK + * @retval 1 OK + * @retval 0 Hide, dont show helptext etc * @retval -1 Error * @see expand_dbvar This is where the expand string is used * @note XXX only fraction_digits handled,should also have mincv, maxcv, pattern @@ -140,10 +140,8 @@ cli_expand_var_generate(clicon_handle h, cv = yang_cv_get(yspec); if (yang_extension_value(ys, "hide", CLIXON_AUTOCLI_NS, &extvalue, NULL) < 0) goto done; - if (extvalue || yang_find(ys, Y_STATUS, "deprecated") != NULL) { - retval = 1; - goto done; - } + if (extvalue || yang_find(ys, Y_STATUS, "deprecated") != NULL) + goto hide; if (yang2api_path_fmt(ys, 1, &api_path_fmt) < 0) goto done; if (pre) @@ -158,11 +156,14 @@ cli_expand_var_generate(clicon_handle h, cprintf(cb, ",\"%s%s\"", MTPOINT_PREFIX, cv_string_get(cv)); } cprintf(cb, ")>"); - retval = 0; + retval = 1; done: if (api_path_fmt) free(api_path_fmt); return retval; + hide: + retval = 0; + goto done; } /*! Create callback with api_path format string as argument @@ -211,6 +212,36 @@ yang2cli_helptext(cbuf *cb, return 0; } +/*! Print yang argument to cbuf, or aliased via extension + * + * This is only implemented for leafs. + * the reason it does not work for non-terminals is somewhat complex: + * If alias, the CLIgen command is instead given as a "keyword" variable: + * This in turn is treated as a single-value choice in cligen_parse.y + * But then in cli_dbxml, choice is treated as a variable which is correct on other cases. + * So one needs to distinguish between "keyword" as given here, and a choice with one argument. + */ +static int +yang2cli_print_alias(cbuf *cb, + yang_stmt *ys) +{ + int retval = -1; + int extvalue = 0; + char *name; + char *alias = NULL; + + if (yang_extension_value(ys, "alias", CLIXON_AUTOCLI_NS, &extvalue, &alias) < 0) + goto done; + name = yang_argument_get(ys); + if (extvalue) + cprintf(cb, "<%s:string keyword:%s>", name, alias); + else + cprintf(cb, "%s", name); + retval = 0; + done: + return retval; +} + /*! Generate identityref statements for CLI variables * @param[in] ys Yang statement * @param[in] ytype Resolved yang type. @@ -646,7 +677,7 @@ yang2cli_var_leafref(clicon_handle h, options, fraction_digits, regular_value, cb)) < 0) goto done; - if (ret == 0) + if (ret == 1) yang2cli_helptext(cb, helptext); } if (completionp && regular_value) @@ -690,9 +721,9 @@ yang2cli_var(clicon_handle h, enum cv_type cvtype; const char *cvtypestr; int options = 0; - int result; int completionp; - + int ret; + if ((patterns = cvec_new(0)) == NULL){ clicon_err(OE_UNIX, errno, "cvec_new"); goto done; @@ -716,10 +747,10 @@ yang2cli_var(clicon_handle h, if (autocli_completion(h, &completionp) < 0) goto done; if (completionp){ - if ((result = cli_expand_var_generate(h, ys, cvtypestr, - options, fraction_digits, 1, cb)) < 0) + if ((ret = cli_expand_var_generate(h, ys, cvtypestr, + options, fraction_digits, 1, cb)) < 0) goto done; - if (result == 0) + if (ret == 1) yang2cli_helptext(cb, helptext); } cprintf(cb, ")"); @@ -819,7 +850,8 @@ yang2cli_leaf(clicon_handle h, goto done; if (listkw == AUTOCLI_LISTKW_ALL || (key_leaf==0 && listkw == AUTOCLI_LISTKW_NOKEY)){ - cprintf(cb, "%s", yang_argument_get(ys)); + if (yang2cli_print_alias(cb, ys) < 0) + goto done; yang2cli_helptext(cb, helptext); cprintf(cb, " "); if (yang_extension_value(ys, "hide", CLIXON_AUTOCLI_NS, &hideext, NULL) < 0) @@ -920,18 +952,6 @@ yang2cli_container(clicon_handle h, if (extvalue || yang_find(ys, Y_STATUS, "deprecated") != NULL){ cprintf(cb, ", hide"); } -#ifdef NYI /* This is for the mode extension, not yet supported */ - { - int mode = 0; - /* First see if extension mode, if not, check if default mode */ - if (yang_extension_value(ys, "mode", CLIXON_AUTOCLI_NS, &mode, NULL) < 0) - goto done; - if (mode == 0 && autocli_edit_mode(h, Y_CONTAINER, &mode) < 0) - goto done; - if (mode) - cprintf(cb, ", mode"); - } -#endif cprintf(cb, ", act-container;{\n"); } @@ -1203,6 +1223,7 @@ yang2cli_stmt(clicon_handle h, yang_stmt *yc; int treeref_state = 0; int grouping_treeref = 0; + int extvalue = 0; if (ys == NULL){ clicon_err(OE_YANG, EINVAL, "No yang spec"); @@ -1215,6 +1236,11 @@ yang2cli_stmt(clicon_handle h, if (yang_find(ys, Y_STATUS, "deprecated") != NULL){ clicon_debug(4, "%s deprecated: %s %s", __FUNCTION__, yang_argument_get(ys), yang_argument_get(ys_module(ys))); } + /* Check if autocli skip */ + if (yang_extension_value(ys, "skip", CLIXON_AUTOCLI_NS, &extvalue, NULL) < 0) + goto done; + if (extvalue == 1) + goto ok; /* Only produce autocli for YANG non-config only if autocli-treeref-state is true */ if (autocli_treeref_state(h, &treeref_state) < 0) goto done; diff --git a/apps/cli/cli_main.c b/apps/cli/cli_main.c index b6bb00a6..6d109d1a 100644 --- a/apps/cli/cli_main.c +++ b/apps/cli/cli_main.c @@ -294,7 +294,6 @@ autocli_trees_default(clicon_handle h) if (cligen_ph_parsetree_set(ph, pt) < 0) goto done; - /* Create backward compatible tree: @datamodelshow */ if ((ph = cligen_ph_add(cli_cligen(h), "datamodelshow")) == NULL) goto done; diff --git a/apps/cli/cli_show.c b/apps/cli/cli_show.c index f5e7383c..0ce29730 100644 --- a/apps/cli/cli_show.c +++ b/apps/cli/cli_show.c @@ -1345,15 +1345,16 @@ xml2cli1(clicon_handle h, char *prepend, clicon_output_cb *fn) { - int retval = -1; - cxobj *xe = NULL; - cbuf *cbpre = NULL; - yang_stmt *ys; - int match; - char *body; - int compress = 0; + int retval = -1; + cxobj *xe = NULL; + cbuf *cbpre = NULL; + yang_stmt *ys; + int match; + char *body; + int compress = 0; autocli_listkw_t listkw; - int exist = 0; + int exist = 0; + char *name; if (autocli_list_keyword(h, &listkw) < 0) goto done; @@ -1365,13 +1366,18 @@ xml2cli1(clicon_handle h, goto done; if (exist) goto ok; + exist = 0; + if (yang_extension_value(ys, "alias", CLIXON_AUTOCLI_NS, &exist, &name) < 0) + goto done; + if (!exist) + name = xml_name(xn); /* If leaf/leaf-list or presence container, then print line */ if (yang_keyword_get(ys) == Y_LEAF || yang_keyword_get(ys) == Y_LEAF_LIST){ if (prepend) (*fn)(f, "%s", prepend); if (listkw != AUTOCLI_LISTKW_NONE) - (*fn)(f, "%s ", xml_name(xn)); + (*fn)(f, "%s ", name); if ((body = xml_body(xn)) != NULL){ if (index(body, ' ')) (*fn)(f, "\"%s\"", body); diff --git a/lib/src/clixon_yang.c b/lib/src/clixon_yang.c index 88c969b6..012ed40d 100644 --- a/lib/src/clixon_yang.c +++ b/lib/src/clixon_yang.c @@ -3780,7 +3780,7 @@ yang_anydata_add(yang_stmt *yp, * if (yang_extension_value(ys, "mymode", "urn:example:lib", &exist, &value) < 0) * err; * if (value != NULL){ - * // use extension value + * // use extension argument * } * @endcode * @see ys_populate_unknown Called when parsing YANG diff --git a/test/config.sh.in b/test/config.sh.in index e7e2fab7..7dc36c64 100755 --- a/test/config.sh.in +++ b/test/config.sh.in @@ -72,7 +72,7 @@ CLIXON_VERSION=@CLIXON_VERSION@ DATASTORE_TOP="config" # clixon yang revisions occuring in tests (see eg yang/clixon/Makefile.in) -CLIXON_AUTOCLI_REV="2023-05-01" +CLIXON_AUTOCLI_REV="2023-09-01" CLIXON_LIB_REV="2023-05-01" CLIXON_CONFIG_REV="2023-05-01" CLIXON_RESTCONF_REV="2022-08-01" diff --git a/test/test_autocli_alias_skip.sh b/test/test_autocli_alias_skip.sh new file mode 100755 index 00000000..aeca77ba --- /dev/null +++ b/test/test_autocli_alias_skip.sh @@ -0,0 +1,254 @@ +#!/usr/bin/env bash +# Tests for using autocli skip and alias extension +# Test augment mode only +# Test skip for leaf, container and list +# Test alias only for leaf, since it is not implemented for container+list +# see also test_autocli_hide.sh +set -u +# Magic line must be first in script (see README.md) +s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi + +APPNAME=example + +: ${clixon_util_datastore:=clixon_util_datastore} + +fin=$dir/in +cfg=$dir/conf_yang.xml +fyang=$dir/example.yang +fyang1=$dir/$APPNAME-augment.yang +clidir=$dir/cli +if [ -d $clidir ]; then + rm -rf $clidir/* +else + mkdir $clidir +fi + +# Use yang in example + +# Generate autocli for these modules +AUTOCLI=$(autocli_config ${APPNAME}\* kw-nokey false) + +cat < $cfg + + $cfg + ietf-netconf:startup + ${YANG_INSTALLDIR} + $dir + $dir + /usr/local/lib/$APPNAME/backend + $clidir + /usr/local/lib/$APPNAME/cli + $APPNAME + /usr/local/var/$APPNAME/$APPNAME.sock + /usr/local/var/$APPNAME/$APPNAME.pidfile + $dir + false + ${AUTOCLI} + +EOF + +cat < $clidir/ex.cli +CLICON_MODE="example"; +CLICON_PROMPT="%U@%H %W> "; +CLICON_PIPETREE="|mypipe"; + +# Autocli syntax tree operations +edit @datamodel, cli_auto_edit("datamodel"); +up, cli_auto_up("datamodel"); +top, cli_auto_top("datamodel"); +set @datamodel, cli_auto_set(); +merge @datamodel, cli_auto_merge(); +create @datamodel, cli_auto_create(); +delete("Delete a configuration item") { + @datamodel, cli_auto_del(); + all("Delete whole candidate configuration"), delete_all("candidate"); +} +show("Show a particular state of the system") configuration, + cli_show_auto_mode("candidate", "xml", false, false); +cli, cli_show_auto_mode("candidate", "cli", false, false); +EOF +# @datamodelshow, cli_show_auto("candidate", "xml", false, false, "explicit"); + +# Yang specs must be here first for backend. But then the specs are changed but just for CLI +# Augment original Yang spec example directly +# First augment /table/parameter +# Had a problem with unknown in grouping -> test uses uses/grouping +cat < $fyang +module example { + namespace "urn:example:clixon"; + prefix ex; + import clixon-autocli{ + prefix autocli; + } + container table{ + list parameter{ + key name; + leaf name{ + type string; + } + leaf same{ + type string; + } + leaf skipped{ + description "leaf skip"; + type string; + } + leaf orig{ + description "leaf alias"; + type string; + } + } + list skipped{ + description "list skip"; + key name; + leaf name{ + type string; + } + leaf value{ + type string; + } + } + } + container skipped{ + description "container skip"; + list parameter{ + key name; + leaf name{ + type string; + } + leaf value{ + type string; + } + } + } +} +EOF + +# Skip /table/parameter +cat < $fyang1 +module example-augment { + namespace "urn:example:augment"; + prefix aug; + import example{ + prefix ex; + } + import clixon-autocli{ + prefix autocli; + } + /* Leafs */ + augment "/ex:table/ex:parameter/ex:skipped" { + autocli:skip; + } + augment "/ex:table/ex:parameter/ex:orig" { + autocli:alias "alias"; + } + /* Lists */ + augment "/ex:table/ex:skipped" { + autocli:skip; + } + /* Containers */ + augment "/ex:skipped" { + autocli:skip; + } +} +EOF + +cat < $clidir/clipipe.cli +CLICON_MODE="|mypipe"; # Must start with | +as { + xml, pipe_showas_fn("xml", "false"); + cli, pipe_showas_fn("cli", "true", "set "); +} +EOF + +new "test params: -f $cfg" +if [ $BE -ne 0 ]; then + new "kill old backend" + sudo clixon_backend -z -f $cfg + if [ $? -ne 0 ]; then + err + fi + new "start backend -s init -f $cfg" + start_backend -s init -f $cfg +fi + +# Set a value, show it +# Arguments: +# 1 : contorig Container field shown in xml +# 2 : listorig List field shown in xml +# 3 : leaforig Leaf field shown in xml +# 4 : contfield Container name to set/show +# 5 : listfield List name to set/show +# 6 : leaffield Leaf field to set/show +function testok() +{ + contorig=$1 + listorig=$2 + leaforig=$3 + contfield=$4 + listfield=$5 + leaffield=$6 + + new "Set $contfield $listfield $leaffield" + expectpart "$($clixon_cli -1f $cfg set $contfield $listfield x $leaffield abc)" 0 "^$" + + new "Show config as xml" + expectpart "$($clixon_cli -1f $cfg show config as xml)" 0 "<$contorig xmlns=\"urn:example:clixon\"><$listorig>x<$leaforig>abc" + + new "Show config as cli" + expectpart "$($clixon_cli -1f $cfg show config as cli)" 0 "set $contfield $listfield x $leaffield abc" + + new "Delete $contfield $listfield $leaffield" + expectpart "$($clixon_cli -1f $cfg delete $contfield $listfield x $leaffield abc)" 0 "^$" +} + +function testfail() +{ + contfield=$1 + listfield=$2 + leaffield=$3 + + new "Set $contfield $listfield $leaffield" +# echo "$clixon_cli -1f -1f $cfg set $contfield $listfield x $leaffield abc" + expectpart "$($clixon_cli -1f $cfg set $contfield $listfield x $leaffield abc 2>&1)" 255 "Unknown command" +} + +new "wait backend" +wait_backend + +# Leaf +new "Test same" +testok table parameter same table parameter same + +new "Test leaf skipped" +testfail table parameter skipped + +new "Test leaf aliases old fail" +testfail table parameter orig + +new "Test leaf aliases new ok" +testok table parameter orig table parameter alias + +# Lists +new "Test list skipped" +testfail table skipped value + +# Container +new "Test skipped" +testfail skipped parameter value + +if [ $BE -ne 0 ]; then + new "Kill backend" + # Check if premature kill + pid=$(pgrep -u root -f clixon_backend) + if [ -z "$pid" ]; then + err "backend already dead" + fi + # kill backend + stop_backend -f $cfg +fi + +rm -rf $dir + +new "endtest" +endtest diff --git a/test/test_autocli_extension.sh b/test/test_autocli_hide.sh similarity index 97% rename from test/test_autocli_extension.sh rename to test/test_autocli_hide.sh index c92b9ded..1a2052b4 100755 --- a/test/test_autocli_extension.sh +++ b/test/test_autocli_hide.sh @@ -68,8 +68,8 @@ show("Show a particular state of the system"){ EOF # Yang specs must be here first for backend. But then the specs are changed but just for CLI -# Annotate original Yang spec example directly -# First annotate /table/parameter +# Augment original Yang spec example directly +# First augment /table/parameter # Had a problem with unknown in grouping -> test uses uses/grouping cat < $fyang module example { @@ -125,9 +125,9 @@ function testparam() set table parameter x show config xml EOF + new "set table parameter hidden" expectpart "$(cat $fin | $clixon_cli -f $cfg 2>&1)" 0 "set table parameter x" "
" - XML="x
" new "check datastore using netconf" @@ -186,7 +186,7 @@ sudo chmod a+r $dir/candidate_db new "Test hidden parameter in table/param inline" testparam -# Second annotate /table/parameter/value +# Second augment /table/parameter/value cat < $fyang module example { namespace "urn:example:clixon"; @@ -253,7 +253,7 @@ module example { } EOF -# First annotate /table/parameter +# First augment /table/parameter cat < $fyang2 module example-augment { namespace "urn:example:augment"; @@ -275,7 +275,7 @@ new "Test hidden parameter in table/param augment" testparam # Try hidden specific parameter key (note only cli yang) -# Second annotate /table/parameter/value +# Second augment /table/parameter/value cat < $fyang2 module example-augment { namespace "urn:example:augment"; @@ -319,7 +319,7 @@ module example { } EOF -# Use this as grouping (not annotate) +# Use this as grouping (not augment) cat < $fyang2 module example-augment { namespace "urn:example:augment"; diff --git a/yang/clixon/Makefile.in b/yang/clixon/Makefile.in index 049d9bd8..0927e8c5 100644 --- a/yang/clixon/Makefile.in +++ b/yang/clixon/Makefile.in @@ -47,7 +47,7 @@ YANGSPECS += clixon-lib@2023-05-01.yang # 6.3 YANGSPECS += clixon-rfc5277@2008-07-01.yang YANGSPECS += clixon-xml-changelog@2019-03-21.yang YANGSPECS += clixon-restconf@2022-08-01.yang # 5.9 -YANGSPECS += clixon-autocli@2023-05-01.yang # 6.3 +YANGSPECS += clixon-autocli@2023-09-01.yang # 6.4 all: diff --git a/yang/clixon/clixon-autocli@2022-02-11.yang b/yang/clixon/clixon-autocli@2022-02-11.yang deleted file mode 100644 index 15e2ac33..00000000 --- a/yang/clixon/clixon-autocli@2022-02-11.yang +++ /dev/null @@ -1,247 +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 2022-02-11 { - description - "Initial version - Released in Clixon 5.6"; - } - revision 2021-12-05 { - description - "Initial version - Released in Clixon 5.5"; - } - extension hide { - description - "Modify the autocli by hiding 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 - "Modify the autocli by hiding the command associated with a YANG node and its - sub-commands in CLI show commands."; - } - 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."; - } - 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; - } - /* 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; - } - } - } -}