From 23b466a854acb69202629de6c480c0149b4986e0 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Tue, 8 Mar 2022 09:18:10 +0100 Subject: [PATCH] * YANG unique: added single descendant node ids as special case * This means that two variants are supported: * unique "a b c", ie multiple direct chidlren * unique "a/b/c", ie single descendants * RFC 7950 Sec 7.8.3 is somewhat unclear * The combination is not supported * Netconf data-not-unique info changed to return schema nodes instead of XML for RFC7950 compliance --- CHANGELOG.md | 10 ++ lib/src/clixon_netconf_lib.c | 8 +- lib/src/clixon_validate.c | 177 ++++++++++++++++++++++++++++++--- test/test_restconf_op.sh | 2 +- test/test_rpc.sh | 2 +- test/test_unique.sh | 8 +- test/test_unique_descendant.sh | 169 +++++++++++++++++++++++++++++++ 7 files changed, 349 insertions(+), 27 deletions(-) create mode 100755 test/test_unique_descendant.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index bbbaead9..35649cc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,11 +41,21 @@ Expected: May 2022 Users may have to change how they access the system +* Netconf data-not-unique info changed to return schema nodes instead of XML for RFC7950 compliance * CLI reconnects to backend if backend restarts with a warning * Note that edits to the candidate database or locks will be lost * To force the CLI to exit if backend restarts, undef `PROTO_RESTART_RECONNECT` * This is an effect of the fix of [Broken pipe error seen in client (cli) when backend restarts and CLICON_SOCK is recreated](https://github.com/clicon/clixon/issues/312), the CLI behavior on backend restart is changed. +### Minor features + +* YANG unique: added single descendant node ids as special case + * This means that two variants are supported: + * unique "a b c", ie multiple direct chidlren + * unique "a/b/c", ie single descendants + * RFC 7950 Sec 7.8.3 is somewhat unclear + * The combination is not supported + ### Corrected Bugs * Fixed: [Broken pipe error seen in client (cli) when backend restarts and CLICON_SOCK is recreated](https://github.com/clicon/clixon/issues/312) diff --git a/lib/src/clixon_netconf_lib.c b/lib/src/clixon_netconf_lib.c index c8b14a35..4c3c89b1 100644 --- a/lib/src/clixon_netconf_lib.c +++ b/lib/src/clixon_netconf_lib.c @@ -1275,7 +1275,7 @@ netconf_malformed_message_xml(cxobj **xret, * "unique" constraint is invalidated. * @param[out] xret Error XML tree. Free with xml_free after use * @param[in] x List element containing duplicate - * @param[in] cvk List of comonents in x that are non-unique + * @param[in] cvk List of components in x that are non-unique * @see RFC7950 Sec 15.1 */ int @@ -1321,13 +1321,9 @@ netconf_data_not_unique_xml(cxobj **xret, goto done; } while ((cvi = cvec_each(cvk, cvi)) != NULL){ - if ((xi = xml_find(x, cv_string_get(cvi))) == NULL) - continue; /* ignore, shouldnt happen */ - clicon_xml2cbuf(cb, xi, 0, 0, -1); if (clixon_xml_parse_va(YB_NONE, NULL, &xinfo, NULL, - "%s", cbuf_get(cb)) < 0) + "%s", cv_string_get(cvi)) < 0) goto done; - cbuf_reset(cb); } } retval = 0; diff --git a/lib/src/clixon_validate.c b/lib/src/clixon_validate.c index aa4cb6a8..d0f942ec 100644 --- a/lib/src/clixon_validate.c +++ b/lib/src/clixon_validate.c @@ -710,6 +710,67 @@ check_mandatory(cxobj *xt, * @retval 0 OK, entry is unique * @retval -1 Duplicate detected * @note This is currently quadratic complexity. It could be improved by inserting new element sorted and binary search. + * @retval 1 Validation OK + * @retval 0 Validation failed (cbret set) + * @retval -1 Error + */ +static int +unique_search_one(cxobj *x, + char *xpath, + char ***svec, + size_t *slen) +{ + int retval = -1; + cxobj **xvec = NULL; + size_t xveclen; + int i; + int s; + cxobj *xi; + char *bi; + + /* Collect tuples */ + if (xpath_vec(x, NULL, "%s", &xvec, &xveclen, xpath) < 0) + goto done; + for (i=0; imandatory$LIST]]>]]>" "^applicationoperation-faileddata-not-uniqueerrorbar]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLOmandatory$LIST]]>]]>" "^applicationoperation-faileddata-not-uniqueerroruk]]>]]>$" new "netconf choice ok" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO42xxx]]>]]>" "^4242xxx]]>]]>$" diff --git a/test/test_unique.sh b/test/test_unique.sh index b926633e..16bed7fe 100755 --- a/test/test_unique.sh +++ b/test/test_unique.sh @@ -109,7 +109,7 @@ expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" new "netconf validate (should fail)" -expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationoperation-faileddata-not-uniqueerror192.0.2.125]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationoperation-faileddata-not-uniqueerroripport]]>]]>$" new "netconf discard-changes" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" @@ -138,7 +138,7 @@ expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" new "netconf validate (should fail)" -expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationoperation-faileddata-not-uniqueerror192.0.2.125]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationoperation-faileddata-not-uniqueerroripport]]>]]>$" new "make it valid by deleting port from smtp entry" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLOnonesmtp25 @@ -163,7 +163,7 @@ expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" new "netconf validate (should fail)" -expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationoperation-faileddata-not-uniqueerror192.0.2.1]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationoperation-faileddata-not-uniqueerrorip]]>]]>$" new "make valid by replacing IP of http entry" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLOnonehttp178.23.34.1 @@ -204,7 +204,7 @@ expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" new "netconf validate (should fail)" -expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationoperation-faileddata-not-uniqueerror192.0.2.125]]>]]>$" +expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationoperation-faileddata-not-uniqueerroripport]]>]]>$" new "netconf discard-changes" expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" diff --git a/test/test_unique_descendant.sh b/test/test_unique_descendant.sh new file mode 100755 index 00000000..4640d712 --- /dev/null +++ b/test/test_unique_descendant.sh @@ -0,0 +1,169 @@ +#!/usr/bin/env bash +# Yang list unique tests using descendant schema node identifiers +# That is, not only direct descendants as the example in RFC7890 7.8.3.1 + +# Magic line must be first in script (see README.md) +s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exi{t 0; else return 0; fi + +APPNAME=example + +cfg=$dir/conf_yang.xml +fyang=$dir/unique.yang + +cat < $cfg + + $cfg + ${YANG_INSTALLDIR} + $fyang + /usr/local/lib/$APPNAME/clispec + /usr/local/lib/$APPNAME/cli + $APPNAME + /usr/local/var/$APPNAME/$APPNAME.sock + /usr/local/var/$APPNAME/$APPNAME.pidfile + /usr/local/var/$APPNAME + +EOF + +# Example (the list server part) from RFC7950 Sec 7.8.3.1 w changed types +cat < $fyang +module unique{ + yang-version 1.1; + namespace "urn:example:clixon"; + prefix un; + list outer{ + key name; + leaf name{ + type string; + } + unique c/inner/value; + container c{ + list inner{ + key name; + leaf name{ + type string; + } + leaf value{ + type string; + } + } + } + } +} +EOF + +new "test params: -f $cfg" + +if [ $BE -ne 0 ]; then + new "kill old backend" + sudo clixon_backend -zf $cfg + if [ $? -ne 0 ]; then + err + fi + new "start backend -s init -f $cfg" + # start new backend + start_backend -s init -f $cfg +fi + +new "wait backend" +wait_backend + +RPC=$(cat<replace + + x + afoo + bbar + + + + y + afie + bfum + + +]]>]]> +EOF + ) + +# RFC test two-field caes +new "Add valid example" +expecteof "$clixon_netconf -qf $cfg" 0 "${RPC}" "^]]>]]>$" + +new "netconf validate ok" +expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" + +new "netconf discard-changes" +expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" + +RPC=$(cat<replace + + x + afoo + bfoo + + + + y + afie + bfum + + +]]>]]> +EOF + ) + +new "Add invalid example" +expecteof "$clixon_netconf -qf $cfg" 0 "${RPC}" "^]]>]]>$" + +new "netconf validate same inner (should fail)" +expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationoperation-faileddata-not-uniqueerrorc/inner/value]]>]]>$" + +new "netconf discard-changes" +expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" + +RPC=$(cat<replace + + x + afoo + bbar + + + + y + afie + bbar + + +]]>]]> +EOF + ) + +new "Add invalid example" +expecteof "$clixon_netconf -qf $cfg" 0 "${RPC}" "^]]>]]>$" + +new "netconf validate same in different outers (should fail)" +expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^applicationoperation-faileddata-not-uniqueerrorc/inner/value]]>]]>$" + +new "netconf discard-changes" +expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$" + +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 + +unset RPC + +new "endtest" +endtest