Added: [Feature request: node's alias for CLI](https://github.com/clicon/clixon/issues/434)

New `clixon-autocli@2023-09-01.yang` revision
Misc typos
This commit is contained in:
Olof hagsand 2023-08-31 17:57:53 +02:00
parent 4e79ac43fb
commit 3b08653eb4
13 changed files with 344 additions and 295 deletions

View file

@ -44,6 +44,12 @@
## 6.4.0 ## 6.4.0
Expected: October 2023 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 ### C/CLI-API changes on existing features
Developers may need to change their code Developers may need to change their code
@ -52,6 +58,8 @@ Developers may need to change their code
### Minor features ### Minor features
* Example cli pipe grep command quotes vertical bar for OR function * 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 * New command-line option for dumping configuration options for all clixon applications after load
* Syntax is `-C <format>` * Syntax is `-C <format>`
* Example: `clixon_backend -1C json` * Example: `clixon_backend -1C json`

View file

@ -45,6 +45,9 @@ static int myfn(int par1, my_structure *par2);
### Errors ### 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: Errors are typically declared as follows:
``` ```
if (myfn(0) < 0){ if (myfn(0) < 0){

View file

@ -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 Clixon interaction is best done posting issues, pull requests, or joining the
Matrix clixon forum https://matrix.to/#/#clixonforum:matrix.org. 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). Clixon is sponsored by [Rubicon Communications LLC(Netgate)](https://www.netgate.com/) and [Akamai Technologies, Inc.](https://www.akamai.com).

View file

@ -214,7 +214,7 @@ restconf_rpc_wrapper(clicon_handle h,
} }
else{ else{
/* Get debug flag of restconf config, set the restconf start -D daemon flag according /* 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. * but in this way it is set directly in its input args.
* Its a trick. * Its a trick.
*/ */

View file

@ -115,8 +115,8 @@ You can see which CLISPEC it generates via clixon_cli -D 2:
* @param[in] options * @param[in] options
* @param[in] fraction_digits * @param[in] fraction_digits
* @param[out] cb The string where the result format string is inserted. * @param[out] cb The string where the result format string is inserted.
* @retval 1 Hide, dont show helptext etc * @retval 1 OK
* @retval 0 OK * @retval 0 Hide, dont show helptext etc
* @retval -1 Error * @retval -1 Error
* @see expand_dbvar This is where the expand string is used * @see expand_dbvar This is where the expand string is used
* @note XXX only fraction_digits handled,should also have mincv, maxcv, pattern * @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); cv = yang_cv_get(yspec);
if (yang_extension_value(ys, "hide", CLIXON_AUTOCLI_NS, &extvalue, NULL) < 0) if (yang_extension_value(ys, "hide", CLIXON_AUTOCLI_NS, &extvalue, NULL) < 0)
goto done; goto done;
if (extvalue || yang_find(ys, Y_STATUS, "deprecated") != NULL) { if (extvalue || yang_find(ys, Y_STATUS, "deprecated") != NULL)
retval = 1; goto hide;
goto done;
}
if (yang2api_path_fmt(ys, 1, &api_path_fmt) < 0) if (yang2api_path_fmt(ys, 1, &api_path_fmt) < 0)
goto done; goto done;
if (pre) 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, ",\"%s%s\"", MTPOINT_PREFIX, cv_string_get(cv));
} }
cprintf(cb, ")>"); cprintf(cb, ")>");
retval = 0; retval = 1;
done: done:
if (api_path_fmt) if (api_path_fmt)
free(api_path_fmt); free(api_path_fmt);
return retval; return retval;
hide:
retval = 0;
goto done;
} }
/*! Create callback with api_path format string as argument /*! Create callback with api_path format string as argument
@ -211,6 +212,36 @@ yang2cli_helptext(cbuf *cb,
return 0; 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: <orig:string keyword:alias>
* 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 /*! Generate identityref statements for CLI variables
* @param[in] ys Yang statement * @param[in] ys Yang statement
* @param[in] ytype Resolved yang type. * @param[in] ytype Resolved yang type.
@ -646,7 +677,7 @@ yang2cli_var_leafref(clicon_handle h,
options, fraction_digits, regular_value, options, fraction_digits, regular_value,
cb)) < 0) cb)) < 0)
goto done; goto done;
if (ret == 0) if (ret == 1)
yang2cli_helptext(cb, helptext); yang2cli_helptext(cb, helptext);
} }
if (completionp && regular_value) if (completionp && regular_value)
@ -690,9 +721,9 @@ yang2cli_var(clicon_handle h,
enum cv_type cvtype; enum cv_type cvtype;
const char *cvtypestr; const char *cvtypestr;
int options = 0; int options = 0;
int result;
int completionp; int completionp;
int ret;
if ((patterns = cvec_new(0)) == NULL){ if ((patterns = cvec_new(0)) == NULL){
clicon_err(OE_UNIX, errno, "cvec_new"); clicon_err(OE_UNIX, errno, "cvec_new");
goto done; goto done;
@ -716,10 +747,10 @@ yang2cli_var(clicon_handle h,
if (autocli_completion(h, &completionp) < 0) if (autocli_completion(h, &completionp) < 0)
goto done; goto done;
if (completionp){ if (completionp){
if ((result = cli_expand_var_generate(h, ys, cvtypestr, if ((ret = cli_expand_var_generate(h, ys, cvtypestr,
options, fraction_digits, 1, cb)) < 0) options, fraction_digits, 1, cb)) < 0)
goto done; goto done;
if (result == 0) if (ret == 1)
yang2cli_helptext(cb, helptext); yang2cli_helptext(cb, helptext);
} }
cprintf(cb, ")"); cprintf(cb, ")");
@ -819,7 +850,8 @@ yang2cli_leaf(clicon_handle h,
goto done; goto done;
if (listkw == AUTOCLI_LISTKW_ALL || if (listkw == AUTOCLI_LISTKW_ALL ||
(key_leaf==0 && listkw == AUTOCLI_LISTKW_NOKEY)){ (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); yang2cli_helptext(cb, helptext);
cprintf(cb, " "); cprintf(cb, " ");
if (yang_extension_value(ys, "hide", CLIXON_AUTOCLI_NS, &hideext, NULL) < 0) 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){ if (extvalue || yang_find(ys, Y_STATUS, "deprecated") != NULL){
cprintf(cb, ", hide"); 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"); cprintf(cb, ", act-container;{\n");
} }
@ -1203,6 +1223,7 @@ yang2cli_stmt(clicon_handle h,
yang_stmt *yc; yang_stmt *yc;
int treeref_state = 0; int treeref_state = 0;
int grouping_treeref = 0; int grouping_treeref = 0;
int extvalue = 0;
if (ys == NULL){ if (ys == NULL){
clicon_err(OE_YANG, EINVAL, "No yang spec"); 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){ 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))); 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 */ /* Only produce autocli for YANG non-config only if autocli-treeref-state is true */
if (autocli_treeref_state(h, &treeref_state) < 0) if (autocli_treeref_state(h, &treeref_state) < 0)
goto done; goto done;

View file

@ -294,7 +294,6 @@ autocli_trees_default(clicon_handle h)
if (cligen_ph_parsetree_set(ph, pt) < 0) if (cligen_ph_parsetree_set(ph, pt) < 0)
goto done; goto done;
/* Create backward compatible tree: @datamodelshow */ /* Create backward compatible tree: @datamodelshow */
if ((ph = cligen_ph_add(cli_cligen(h), "datamodelshow")) == NULL) if ((ph = cligen_ph_add(cli_cligen(h), "datamodelshow")) == NULL)
goto done; goto done;

View file

@ -1345,15 +1345,16 @@ xml2cli1(clicon_handle h,
char *prepend, char *prepend,
clicon_output_cb *fn) clicon_output_cb *fn)
{ {
int retval = -1; int retval = -1;
cxobj *xe = NULL; cxobj *xe = NULL;
cbuf *cbpre = NULL; cbuf *cbpre = NULL;
yang_stmt *ys; yang_stmt *ys;
int match; int match;
char *body; char *body;
int compress = 0; int compress = 0;
autocli_listkw_t listkw; autocli_listkw_t listkw;
int exist = 0; int exist = 0;
char *name;
if (autocli_list_keyword(h, &listkw) < 0) if (autocli_list_keyword(h, &listkw) < 0)
goto done; goto done;
@ -1365,13 +1366,18 @@ xml2cli1(clicon_handle h,
goto done; goto done;
if (exist) if (exist)
goto ok; 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 leaf/leaf-list or presence container, then print line */
if (yang_keyword_get(ys) == Y_LEAF || if (yang_keyword_get(ys) == Y_LEAF ||
yang_keyword_get(ys) == Y_LEAF_LIST){ yang_keyword_get(ys) == Y_LEAF_LIST){
if (prepend) if (prepend)
(*fn)(f, "%s", prepend); (*fn)(f, "%s", prepend);
if (listkw != AUTOCLI_LISTKW_NONE) if (listkw != AUTOCLI_LISTKW_NONE)
(*fn)(f, "%s ", xml_name(xn)); (*fn)(f, "%s ", name);
if ((body = xml_body(xn)) != NULL){ if ((body = xml_body(xn)) != NULL){
if (index(body, ' ')) if (index(body, ' '))
(*fn)(f, "\"%s\"", body); (*fn)(f, "\"%s\"", body);

View file

@ -3780,7 +3780,7 @@ yang_anydata_add(yang_stmt *yp,
* if (yang_extension_value(ys, "mymode", "urn:example:lib", &exist, &value) < 0) * if (yang_extension_value(ys, "mymode", "urn:example:lib", &exist, &value) < 0)
* err; * err;
* if (value != NULL){ * if (value != NULL){
* // use extension value * // use extension argument
* } * }
* @endcode * @endcode
* @see ys_populate_unknown Called when parsing YANG * @see ys_populate_unknown Called when parsing YANG

View file

@ -72,7 +72,7 @@ CLIXON_VERSION=@CLIXON_VERSION@
DATASTORE_TOP="config" DATASTORE_TOP="config"
# clixon yang revisions occuring in tests (see eg yang/clixon/Makefile.in) # 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_LIB_REV="2023-05-01"
CLIXON_CONFIG_REV="2023-05-01" CLIXON_CONFIG_REV="2023-05-01"
CLIXON_RESTCONF_REV="2022-08-01" CLIXON_RESTCONF_REV="2022-08-01"

254
test/test_autocli_alias_skip.sh Executable file
View file

@ -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 <<EOF > $cfg
<clixon-config xmlns="http://clicon.org/config">
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
<CLICON_FEATURE>ietf-netconf:startup</CLICON_FEATURE>
<CLICON_YANG_DIR>${YANG_INSTALLDIR}</CLICON_YANG_DIR>
<CLICON_YANG_DIR>$dir</CLICON_YANG_DIR>
<CLICON_YANG_MAIN_DIR>$dir</CLICON_YANG_MAIN_DIR>
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
<CLICON_CLISPEC_DIR>$clidir</CLICON_CLISPEC_DIR>
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
<CLICON_XMLDB_DIR>$dir</CLICON_XMLDB_DIR>
<CLICON_YANG_LIBRARY>false</CLICON_YANG_LIBRARY>
${AUTOCLI}
</clixon-config>
EOF
cat <<EOF > $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 <<EOF > $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 <<EOF > $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 <<EOF > $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><name>x</name><$leaforig>abc</$leaforig></$listorig></$contorig>"
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

View file

@ -68,8 +68,8 @@ show("Show a particular state of the system"){
EOF EOF
# Yang specs must be here first for backend. But then the specs are changed but just for CLI # Yang specs must be here first for backend. But then the specs are changed but just for CLI
# Annotate original Yang spec example directly # Augment original Yang spec example directly
# First annotate /table/parameter # First augment /table/parameter
# Had a problem with unknown in grouping -> test uses uses/grouping # Had a problem with unknown in grouping -> test uses uses/grouping
cat <<EOF > $fyang cat <<EOF > $fyang
module example { module example {
@ -125,9 +125,9 @@ function testparam()
set table parameter x set table parameter x
show config xml show config xml
EOF EOF
new "set table parameter hidden" new "set table parameter hidden"
expectpart "$(cat $fin | $clixon_cli -f $cfg 2>&1)" 0 "set table parameter x" "<table xmlns=\"urn:example:clixon\"></table>" expectpart "$(cat $fin | $clixon_cli -f $cfg 2>&1)" 0 "set table parameter x" "<table xmlns=\"urn:example:clixon\"></table>"
XML="<table xmlns=\"urn:example:clixon\"><parameter><name>x</name></parameter></table>" XML="<table xmlns=\"urn:example:clixon\"><parameter><name>x</name></parameter></table>"
new "check datastore using netconf" new "check datastore using netconf"
@ -186,7 +186,7 @@ sudo chmod a+r $dir/candidate_db
new "Test hidden parameter in table/param inline" new "Test hidden parameter in table/param inline"
testparam testparam
# Second annotate /table/parameter/value # Second augment /table/parameter/value
cat <<EOF > $fyang cat <<EOF > $fyang
module example { module example {
namespace "urn:example:clixon"; namespace "urn:example:clixon";
@ -253,7 +253,7 @@ module example {
} }
EOF EOF
# First annotate /table/parameter # First augment /table/parameter
cat <<EOF > $fyang2 cat <<EOF > $fyang2
module example-augment { module example-augment {
namespace "urn:example:augment"; namespace "urn:example:augment";
@ -275,7 +275,7 @@ new "Test hidden parameter in table/param augment"
testparam testparam
# Try hidden specific parameter key (note only cli yang) # Try hidden specific parameter key (note only cli yang)
# Second annotate /table/parameter/value # Second augment /table/parameter/value
cat <<EOF > $fyang2 cat <<EOF > $fyang2
module example-augment { module example-augment {
namespace "urn:example:augment"; namespace "urn:example:augment";
@ -319,7 +319,7 @@ module example {
} }
EOF EOF
# Use this as grouping (not annotate) # Use this as grouping (not augment)
cat <<EOF > $fyang2 cat <<EOF > $fyang2
module example-augment { module example-augment {
namespace "urn:example:augment"; namespace "urn:example:augment";

View file

@ -47,7 +47,7 @@ YANGSPECS += clixon-lib@2023-05-01.yang # 6.3
YANGSPECS += clixon-rfc5277@2008-07-01.yang YANGSPECS += clixon-rfc5277@2008-07-01.yang
YANGSPECS += clixon-xml-changelog@2019-03-21.yang YANGSPECS += clixon-xml-changelog@2019-03-21.yang
YANGSPECS += clixon-restconf@2022-08-01.yang # 5.9 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: all:

View file

@ -1,247 +0,0 @@
module clixon-autocli{
yang-version 1.1;
namespace "http://clicon.org/autocli";
prefix autocli;
organization
"Clicon / Clixon";
contact
"Olof Hagsand <olof@hagsand.se>";
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:
<module-default>false</module-default>
<rule>
<name>wifi</name>
<operation>enable</operation>
<module-name>openconfig-wifi</module-name>
</rule>
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
<rule>
<name>container compress</name>
<operation>compress</operation>
<yang-keyword>container</yang-keyword>
<yang-keyword-child>list</yang-keyword-child>
</rule>
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<CR>
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 <x> <y>";
}
enum kw-nokey{
description "Keywords on non-key variables: a <x> y <y>";
}
enum kw-all{
description "Keywords on all variables: a x <x> y <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<cr>
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 /<id>/<id> or just a single <id> 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;
}
}
}
}