diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c53fce3..8f560b1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,7 @@ Expected: April * Changed: RPC process-control output to choice with status fields * New clixon-config@2020-03-08.yang revision * Added: `CLICON_NETCONF_HELLO_OPTIONAL` + * Added: `CLICON_CLI_AUTOCLI_EXCLUDE` ### C/CLI-API changes on existing features diff --git a/apps/cli/cli_generate.c b/apps/cli/cli_generate.c index 277dbfb7..3bb8e43b 100644 --- a/apps/cli/cli_generate.c +++ b/apps/cli/cli_generate.c @@ -1014,11 +1014,20 @@ yang2cli(clicon_handle h, yang_stmt *yc; cvec *globals; /* global variables from syntax */ genmodel_type gt; - + char *excludelist; + char **exvec = NULL; + int nexvec = 0; + int e; + if (pt == NULL){ clicon_err(OE_YANG, EINVAL, "pt is NULL"); goto done; } + /* List of modules that should not generate autocli */ + if ((excludelist = clicon_option_str(h, "CLICON_CLI_AUTOCLI_EXCLUDE")) != NULL){ + if ((exvec = clicon_strsep(excludelist, " \t", &nexvec)) == NULL) + goto done; + } gt = clicon_cli_genmodel_type(h); if ((cb = cbuf_new()) == NULL){ clicon_err(OE_XML, errno, "cbuf_new"); @@ -1026,9 +1035,17 @@ yang2cli(clicon_handle h, } /* Traverse YANG, loop through all modules and generate CLI */ yc = NULL; - while ((yc = yn_each(yn, yc)) != NULL) + while ((yc = yn_each(yn, yc)) != NULL){ + /* Check if module is in exclude list */ + for (e = 0; e < nexvec; e++){ + if (strcmp(yang_argument_get(yc), exvec[e]) == 0) + break; + } + if (e < nexvec) + continue; if (yang2cli_stmt(h, yc, gt, 0, state, show_tree, cb) < 0) goto done; + } if (printgen) clicon_log(LOG_NOTICE, "%s: Generated CLI spec:\n%s", __FUNCTION__, cbuf_get(cb)); else @@ -1050,6 +1067,8 @@ yang2cli(clicon_handle h, retval = 0; done: + if (exvec) + free(exvec); if (cb) cbuf_free(cb); return retval; diff --git a/example/main/clixon-example@2020-12-01.yang b/example/main/clixon-example@2020-12-01.yang index 6403dda2..412e571d 100644 --- a/example/main/clixon-example@2020-12-01.yang +++ b/example/main/clixon-example@2020-12-01.yang @@ -2,7 +2,8 @@ module clixon-example { yang-version 1.1; namespace "urn:example:clixon"; prefix ex; - import ietf-interfaces { + import ietf-interfaces { + /* is in yang/optional which means clixon must be installed using --opt-yang-installdir */ prefix if; } import ietf-ip { diff --git a/example/main/example.xml b/example/main/example.xml index cd6ef469..28855f19 100644 --- a/example/main/example.xml +++ b/example/main/example.xml @@ -13,6 +13,7 @@ /usr/local/var/example/example.pidfile 1 VARS + clixon-restconf /usr/local/var/example 0 init diff --git a/test/README.md b/test/README.md index 5e1f3e61..8cec5e59 100644 --- a/test/README.md +++ b/test/README.md @@ -7,6 +7,11 @@ automatically run as part of the all.sh, sum.sh tests etc. The scripts need to follow some rules to work properly, please look at one or two to get the idea. +Note that configure must ensure optional yangs be installed: +``` + ./configure --enable-optyangs +``` + See also the [site.sh](#site-sh) for example for skipping tests or setting some site-specific variables. ## Continuous Integration diff --git a/test/test_openconfig.sh b/test/test_openconfig.sh index b47e0d30..d04431b0 100755 --- a/test/test_openconfig.sh +++ b/test/test_openconfig.sh @@ -15,7 +15,6 @@ s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi APPNAME=example cfg=$dir/conf_yang.xml -fyang=$dir/test.yang new "openconfig" if [ ! -d "$OPENCONFIG" ]; then @@ -31,7 +30,6 @@ cat < $cfg $cfg ietf-netconf:startup /usr/local/share/clixon - $OCDIR $OCDIR/acl $OCDIR/aft @@ -69,7 +67,6 @@ cat < $cfg $OCDIR/wifi/mac $OCDIR/wifi/phy $OCDIR/wifi/types - /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/cli $APPNAME @@ -80,7 +77,7 @@ cat < $cfg EOF -files=$(find $OPENCONFIG -name "*.yang") +files=$(find $OCDIR -name "*.yang") # Count nr of modules (exclude submodule) Assume "module" or "submodule" # first word on first line let ms=0; # Nr of modules @@ -112,53 +109,6 @@ for f in $files; do fi done -if false; then # NYI - -# Example system -cat < $dir/startup_db - - - - eth0 - - ianaift:usb - - - - -EOF - -if [ $BE -ne 0 ]; then - new "kill old backend" - sudo clixon_backend -zf $cfg - if [ $? -ne 0 ]; then - err - fi - sudo pkill -f clixon_backend # to be sure - - new "start backend -s startup -f $cfg -y openconfig-interfaces -p /usr/local/share/openconfig/public/release/models/interfaces" - start_backend -s startup -f $cfg -y /usr/local/share/openconfig/public/release/models/interfaces/openconfig-interfaces.yang - - new "wait backend" - wait_backend -fi - -new "$clixon_cli -D $DBG -1f $cfg -y $f show version" -expectpart "$($clixon_cli -D $DBG -1f $cfg -y $f show version)" 0 "${CLIXON_VERSION}" - -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 - -fi - rm -rf $dir new "endtest" diff --git a/test/test_openconfig_interfaces.sh b/test/test_openconfig_interfaces.sh new file mode 100755 index 00000000..deb3cb5a --- /dev/null +++ b/test/test_openconfig_interfaces.sh @@ -0,0 +1,163 @@ +#!/usr/bin/env bash +# Parse "all" openconfig yangs from https://github.com/openconfig/public +# Notes: +# Notes: +# - A simple smoketest (CLI check) is made, essentially YANG parsing. +# - A full system is worked on +# - Env-var OPENCONFIG should point to checkout place. (define it in site.sh for example) +# - Env variable YANGMODELS should point to checkout place. (define it in site.sh for example) +# - Some DIFFs are necessary in yangmodels +# release/models/wifi/openconfig-ap-interfaces.yang + +# 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 + +cfg=$dir/conf_yang.xml +fyang=$dir/clixon-example.yang + +new "openconfig" +if [ ! -d "$OPENCONFIG" ]; then +# err "Hmm Openconfig dir does not seem to exist, try git clone https://github.com/openconfig/public?" + echo "...skipped: OPENCONFIG not set" + if [ "$s" = $0 ]; then exit 0; else return 0; fi +fi + +OCDIR=$OPENCONFIG/release/models + +cat < $cfg + + $cfg + ietf-netconf:startup + $OPENCONFIG/third_party/ietf/ + /usr/local/share/clixon + $OCDIR + $OCDIR + $OCDIR/acl + $OCDIR/aft + $OCDIR/bfd + $OCDIR/bgp + $OCDIR/catalog + $OCDIR/interfaces + $OCDIR/isis + $OCDIR/lacp + $OCDIR/lldp + $OCDIR/local-routing + $OCDIR/macsec + $OCDIR/mpls + $OCDIR/multicast + $OCDIR/network-instance + $OCDIR/openflow + $OCDIR/optical-transport + $OCDIR/ospf + $OCDIR/platform + $OCDIR/policy + $OCDIR/policy-forwarding + $OCDIR/probes + $OCDIR/qos + $OCDIR/relay-agent + $OCDIR/rib + $OCDIR/segment-routing + $OCDIR/stp + $OCDIR/system + $OCDIR/telemetry + $OCDIR/types + $OCDIR/vlan + $OCDIR/wifi + $OCDIR/wifi/access-points + $OCDIR/wifi/ap-manager + $OCDIR/wifi/mac + $OCDIR/wifi/phy + $OCDIR/wifi/types + $fyang + /usr/local/lib/$APPNAME/clispec + /usr/local/lib/$APPNAME/cli + $APPNAME + $APPNAME + + /usr/local/var/$APPNAME/$APPNAME.sock + /usr/local/var/$APPNAME/$APPNAME.pidfile + $dir + true + +EOF + +# Example yang +cat < $fyang +module clixon-example{ + yang-version 1.1; + namespace "urn:example:example"; + prefix ex; + + import ietf-interfaces { + prefix ietf-if; + } + import openconfig-interfaces { + prefix oc-if; + } + identity eth { /* Need to create an interface-type identity for leafrefs */ + base ietf-if:interface-type; + } +} +EOF + +# Example system +cat < $dir/startup_db + + + + e + + e + ex:eth + false + true + + + + 0 + 0 + + + + + +EOF + +if [ $BE -ne 0 ]; then + new "kill old backend" + sudo clixon_backend -zf $cfg + if [ $? -ne 0 ]; then + err + fi + sudo pkill -f clixon_backend # to be sure + + new "start backend -s startup -f $cfg" + start_backend -s startup -f $cfg + + new "wait backend" + wait_backend +fi + +new "$clixon_cli -D $DBG -1f $cfg -y $f show version" +expectpart "$($clixon_cli -D $DBG -1f $cfg show version)" 0 "${CLIXON_VERSION}" + +new "$clixon_netconf -qf $cfg" +expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^eeex:ethfalsetrue00]]>]]>" + +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_restconf_basic_auth.sh b/test/test_restconf_basic_auth.sh index eb076c16..735ef07b 100755 --- a/test/test_restconf_basic_auth.sh +++ b/test/test_restconf_basic_auth.sh @@ -81,10 +81,10 @@ cat < $fyang module myexample{ yang-version 1.1; namespace "urn:example:auth"; + prefix ex; import ietf-netconf-acm { prefix nacm; } - prefix ex; container top { leaf anonymous{ type string; diff --git a/test/test_yang_models_ieee.sh b/test/test_yang_models_ieee.sh index f8304b8c..300a50e9 100755 --- a/test/test_yang_models_ieee.sh +++ b/test/test_yang_models_ieee.sh @@ -17,7 +17,6 @@ s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi APPNAME=example cfg=$dir/conf_yang.xml -fyang=$dir/test.yang if [ ! -d "$YANGMODELS" ]; then # err "Hmm Yangmodels dir does not seem to exist, try git clone https://github.com/YangModels/yang?" diff --git a/test/test_yang_models_ietf.sh b/test/test_yang_models_ietf.sh index 1a8137ab..85ada975 100755 --- a/test/test_yang_models_ietf.sh +++ b/test/test_yang_models_ietf.sh @@ -32,7 +32,6 @@ s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi APPNAME=example cfg=$dir/conf_yang.xml -fyang=$dir/test.yang if [ ! -d "$YANGMODELS" ]; then # err "Hmm Yangmodels dir does not seem to exist, try git clone https://github.com/YangModels/yang?" @@ -49,6 +48,7 @@ cat < $cfg ietf-access-control-list:match-on-tcp /usr/local/share/clixon $YANGMODELS/standard/ieee/published/802.1 + $YANGMODELS/standard/ietf/RFC /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/cli $APPNAME @@ -59,9 +59,16 @@ cat < $cfg EOF # Standard IETF -new "yangmodel Standard IETF: $YANGMODELS/standard/ietf/RFC" -echo "$clixon_cli -D $DBG -1f $cfg -o CLICON_YANG_MAIN_DIR=$YANGMODELS/standard/ietf/RFC show version" -expectpart "$($clixon_cli -D $DBG -1f $cfg -o CLICON_YANG_MAIN_DIR=$YANGMODELS/standard/ietf/RFC show version)" 0 "${CLIXON_VERSION}" +files=$(find $YANGMODELS/standard/ietf/RFC -name "*.yang") +for f in $files; do + if [ -n "$(head -1 $f|grep '^module')" ]; then + # Mask old revision + if [ $f != $YANGMODELS/standard/ietf/RFC/ietf-yang-types@2010-09-24.yang ]; then + new "$clixon_cli -D $DBG -1f $cfg -y $f show version" + expectpart "$($clixon_cli -D $DBG -1f $cfg -y $f show version)" 0 "${CLIXON_VERSION}" + fi + fi +done rm -rf $dir diff --git a/yang/clixon/clixon-config@2021-03-08.yang b/yang/clixon/clixon-config@2021-03-08.yang index c42d1708..bbdbb844 100644 --- a/yang/clixon/clixon-config@2021-03-08.yang +++ b/yang/clixon/clixon-config@2021-03-08.yang @@ -46,7 +46,8 @@ module clixon-config { revision 2021-03-08 { description "Added option: - CLICON_NETCONF_HELLO_OPTIONAL"; + CLICON_NETCONF_HELLO_OPTIONAL; + CLICON_CLI_AUTOCLI_EXCLUDE"; } revision 2020-12-30 { description @@ -202,7 +203,7 @@ module clixon-config { } typedef cli_genmodel_type{ description - "How to generate CLI from YANG model, + "How to generate auto CLI from YANG model, eg {container c {list a{ key x; leaf x; leaf y;}}"; type enumeration{ enum NONE{ @@ -525,7 +526,7 @@ module clixon-config { type string; default "datamodel"; description - "If CLICON_CLI_GENMOEL is set, CLI specs can reference the + "If CLICON_CLI_GENMODEL is set, CLI specs can reference the model syntax using a model tree set by this option. Three trees are generated with this name as a base, (assuming base is datamodel): - @datamodel - a clispec for navigating in editing a configuration (set/merge/delete) @@ -545,7 +546,16 @@ module clixon-config { leaf CLICON_CLI_GENMODEL_TYPE { type cli_genmodel_type; default "VARS"; - description "How to generate and show CLI syntax: VARS|ALL"; + description "How to generate and show auto CLI syntax: VARS|ALL|HIDE"; + } + leaf CLICON_CLI_AUTOCLI_EXCLUDE { + type string; + description + "List of module names that should not be generated autocli from + Example: + clixon-restconf + means generate autocli for all models except clixon-restconf.yang + The value can be a list of space separated module names"; } leaf CLICON_CLI_VARONLY { type int32;