From ba2f40728b2c2796ae558a5c7e071a3eb1476546 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Sat, 7 Dec 2019 18:10:19 +0100 Subject: [PATCH] [filter in netconf - one specific entry #100](https://github.com/clicon/clixon/issues/100) --- CHANGELOG.md | 1 + apps/netconf/netconf_filter.c | 1 - apps/netconf/netconf_rpc.c | 75 +++++++++++++-------------- lib/src/clixon_xml.c | 2 +- test/test_netconf.sh | 2 +- test/test_netconf_filter.sh | 96 +++++++++++++++++++++++++++++++++++ 6 files changed, 134 insertions(+), 43 deletions(-) create mode 100755 test/test_netconf_filter.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index d174d542..57b656be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ * Main example yang changed to incorporate augmented state, new revision is 2019-11-15. ### Corrected Bugs +* [filter in netconf - one specific entry #100](https://github.com/clicon/clixon/issues/100) * [xpath_tree2cbuf() changes integers into floating point representations #99](https://github.com/clicon/clixon/issues/99) * [xml_parse_string() is slow for a long XML string #96](https://github.com/clicon/clixon/issues/96) * Mandatory variables can no longer be deleted. diff --git a/apps/netconf/netconf_filter.c b/apps/netconf/netconf_filter.c index 8451c33b..59540559 100644 --- a/apps/netconf/netconf_filter.c +++ b/apps/netconf/netconf_filter.c @@ -121,7 +121,6 @@ xml_filter_recursive(cxobj *xfilter, int remove_s; *remove_me = 0; - assert(xfilter && xparent && strcmp(xml_name(xfilter), xml_name(xparent))==0); /* 1. Check selection */ if (xml_child_nr(xfilter) == 0) goto match; diff --git a/apps/netconf/netconf_rpc.c b/apps/netconf/netconf_rpc.c index adb9329f..67e886f1 100644 --- a/apps/netconf/netconf_rpc.c +++ b/apps/netconf/netconf_rpc.c @@ -80,6 +80,31 @@ */ +static int +netconf_get_config_subtree(clicon_handle h, + cxobj *xfilter, + cxobj **xret) +{ + int retval = -1; + cxobj *xdata; + + /* a subtree filter is comprised of zero or more element subtrees*/ + if ((xdata = xpath_first(*xret, "/rpc-reply/data")) == NULL) + goto ok; + if (xml_filter(xfilter, xdata) < 0){ + xml_parse_va(xret, NULL, "" + "operation-failed" + "applicatio" + "error" + "filtering" + ""); + } +ok: + retval = 0; + // done: + return retval; +} + /*! Get configuration * @param[in] h Clicon handle * @param[in] xn Sub-tree (under xorig) at ... level. @@ -136,37 +161,22 @@ netconf_get_config(clicon_handle h, cxobj *xfilter; /* filter */ int retval = -1; char *ftype = NULL; - cxobj *xfilterconf; - cxobj *xconf; /* ie ... */ if ((xfilter = xpath_first(xn, "filter")) != NULL) ftype = xml_find_value(xfilter, "type"); - if (ftype == NULL || strcmp(ftype, "xpath")==0){ + if (xfilter == NULL || ftype == NULL || strcmp(ftype, "xpath")==0){ if (clicon_rpc_netconf_xml(h, xml_parent(xn), xret, NULL) < 0) goto done; } else if (strcmp(ftype, "subtree")==0){ - /* Default rfc filter is subtree. I prefer xpath and use it internally. - Get whole subtree and then filter aftwerwards. This is suboptimal. - Therefore please use xpath. + /* Get whole config first, then filter. This is suboptimal */ if (clicon_rpc_netconf_xml(h, xml_parent(xn), xret, NULL) < 0) goto done; - if (xfilter && - (xfilterconf = xpath_first(xfilter, "//configuration"))!= NULL && - (xconf = xpath_first(*xret, "/rpc-reply/data")) != NULL){ - /* xml_filter removes parts of xml tree not matching */ - if ((strcmp(xml_name(xfilterconf), xml_name(xconf))!=0) || - xml_filter(xfilterconf, xconf) < 0){ - xml_parse_va(xret, NULL, "" - "operation-failed" - "applicatio" - "error" - "filtering" - ""); - } - } + /* Now filter on whole tree */ + if (netconf_get_config_subtree(h, xfilter, xret) < 0) + goto done; } else{ xml_parse_va(xret, NULL, "" @@ -348,37 +358,22 @@ netconf_get(clicon_handle h, cxobj *xfilter; /* filter */ int retval = -1; char *ftype = NULL; - cxobj *xfilterconf; - cxobj *xconf; /* ie ... */ if ((xfilter = xpath_first(xn, "filter")) != NULL) ftype = xml_find_value(xfilter, "type"); - if (ftype == NULL || strcmp(ftype, "xpath")==0){ + if (xfilter == NULL || ftype == NULL || strcmp(ftype, "xpath")==0){ if (clicon_rpc_netconf_xml(h, xml_parent(xn), xret, NULL) < 0) goto done; } else if (strcmp(ftype, "subtree")==0){ - /* Default rfc filter is subtree. I prefer xpath and use it internally. - Get whole subtree and then filter aftwerwards. This is suboptimal. - Therefore please use xpath. + /* Get whole config + state first, then filter. This is suboptimal */ if (clicon_rpc_netconf_xml(h, xml_parent(xn), xret, NULL) < 0) goto done; - if (xfilter && - (xfilterconf = xpath_first(xfilter, "//configuration"))!= NULL && - (xconf = xpath_first(*xret, "/rpc-reply/data")) != NULL){ - /* xml_filter removes parts of xml tree not matching */ - if ((strcmp(xml_name(xfilterconf), xml_name(xconf))!=0) || - xml_filter(xfilterconf, xconf) < 0){ - xml_parse_va(xret, NULL, "" - "operation-failed" - "applicatio" - "error" - "filtering" - ""); - } - } + /* Now filter on whole tree */ + if (netconf_get_config_subtree(h, xfilter, xret) < 0) + goto done; } else{ xml_parse_va(xret, NULL, "" diff --git a/lib/src/clixon_xml.c b/lib/src/clixon_xml.c index f7dcf0d3..add0961b 100644 --- a/lib/src/clixon_xml.c +++ b/lib/src/clixon_xml.c @@ -400,7 +400,7 @@ xml2ns(cxobj *x, /*! Add a namespace attribute to an XML node, either default or specific prefix * @param[in] x XML tree * @param[in] prefix prefix/ns localname. If NULL then set default xmlns - * @param[out] namespace URI namespace (or NULL). Will be copied + * @param[in] ns URI namespace (or NULL). Will be copied * @retval 0 OK * @retval -1 Error * @see xml2ns diff --git a/test/test_netconf.sh b/test/test_netconf.sh index e0476c1e..c451f061 100755 --- a/test/test_netconf.sh +++ b/test/test_netconf.sh @@ -136,7 +136,7 @@ expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" -new "netconf edit config merge" +new "netconf edit config merge eth2" expecteof "$clixon_netconf -qf $cfg" 0 'eth2ex:ethmerge]]>]]>' "^]]>]]>$" # Note, the type here is non-existant identityref, fails on validation diff --git a/test/test_netconf_filter.sh b/test/test_netconf_filter.sh new file mode 100755 index 00000000..8328c2ad --- /dev/null +++ b/test/test_netconf_filter.sh @@ -0,0 +1,96 @@ +#!/usr/bin/env bash +# Test netconf filter, subtree and xpath +# Note subtree namespaces not implemented + +# 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/filter.yang + +cat < $cfg + + $cfg + /usr/local/share/clixon + $fyang + /usr/local/lib/$APPNAME/clispec + /usr/local/lib/$APPNAME/cli + $APPNAME + /usr/local/var/$APPNAME/$APPNAME.sock + /usr/local/lib/$APPNAME/backend + /usr/local/var/$APPNAME/$APPNAME.pidfile + /usr/local/var/$APPNAME + +EOF + +cat < $fyang +module filter{ + yang-version 1.1; + namespace "urn:example:filter"; + prefix fi; + container x{ + list y { + key a; + leaf a{ + type string; + } + leaf b{ + 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_backend -s init -f $cfg +fi + +new "waiting" +wait_backend + +new "Add two entries" +expecteof "$clixon_netconf -qf $cfg" 0 '1122]]>]]>' '^]]>]]>$' + +new "netconf commit" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" + +new "wrong filter type" +expecteof "$clixon_netconf -qf $cfg" 0 "1]]>]]>" '^operation-failedapplicatioerrorfilter type not supportedtype]]>]]>$' + +new "get-config subtree one" +expecteof "$clixon_netconf -qf $cfg" 0 "1]]>]]>" '^11]]>]]>$' + +new "get subtree one" +expecteof "$clixon_netconf -qf $cfg" 0 "1]]>]]>" '^11]]>]]>$' + +new "get-config xpath one" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^11]]>]]>$' + +new "get xpath one" +expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" '^11]]>]]>$' + +if [ $BE -eq 0 ]; then + exit # BE +fi + +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 + +rm -rf $dir