diff --git a/apps/backend/backend_plugin.c b/apps/backend/backend_plugin.c index f9675a35..1f55099c 100644 --- a/apps/backend/backend_plugin.c +++ b/apps/backend/backend_plugin.c @@ -388,7 +388,7 @@ clixon_plugin_statedata_all(clicon_handle h, if (xml_sort_recurse(x) < 0) goto done; /* Remove global defaults and empty non-presence containers */ - if (xml_defaults_nopresence(x, 1) < 0) + if (xml_defaults_nopresence(x, 2) < 0) goto done; if (xml_default_recurse(x, 1) < 0) goto done; diff --git a/lib/src/clixon_datastore_read.c b/lib/src/clixon_datastore_read.c index 2c663c91..2b65e51c 100644 --- a/lib/src/clixon_datastore_read.c +++ b/lib/src/clixon_datastore_read.c @@ -890,7 +890,7 @@ xmldb_get_cache(clicon_handle h, goto done; } /* Remove global defaults and empty non-presence containers */ - if (xml_defaults_nopresence(x0t, 1) < 0) + if (xml_defaults_nopresence(x0t, 2) < 0) goto done; if (yb != YB_NONE){ /* Add default global values */ @@ -1163,7 +1163,7 @@ xmldb_get0_clear(clicon_handle h, if (x == NULL) goto ok; /* Remove global defaults and empty non-presence containers */ - if (xml_defaults_nopresence(x, 1) < 0) + if (xml_defaults_nopresence(x, 2) < 0) goto done; /* Clear XML tree of defaults */ if (xml_tree_prune_flagged(x, XML_FLAG_TRANSIENT, 1) < 0) diff --git a/lib/src/clixon_datastore_write.c b/lib/src/clixon_datastore_write.c index e05ea2fc..15c5bcb8 100644 --- a/lib/src/clixon_datastore_write.c +++ b/lib/src/clixon_datastore_write.c @@ -1258,7 +1258,7 @@ xmldb_put(clicon_handle h, (void*)(XML_FLAG_NONE|XML_FLAG_MARK)) < 0) goto done; /* Remove global defaults and empty non-presence containers */ - if (xml_defaults_nopresence(x0, 1) < 0) + if (xml_defaults_nopresence(x0, 2) < 0) goto done; #if 0 /* debug */ if (xml_apply0(x0, -1, xml_sort_verify, NULL) < 0) diff --git a/lib/src/clixon_xml_map.c b/lib/src/clixon_xml_map.c index d5f6f00f..81b35129 100644 --- a/lib/src/clixon_xml_map.c +++ b/lib/src/clixon_xml_map.c @@ -1103,11 +1103,14 @@ xml_global_defaults(clicon_handle h, /*! Recursively find empty nopresence containers and default leaves, optionally purge * * @param[in] xn XML tree - * @param[in] purge Remove sub-nodes that is empty non-presence container or default leaf + * @param[in] purge 0: Dont remove any nodes + * 1: Remove config sub-nodes that are empty non-presence container or default leaf + * 2: Remove all sub-nodes that are empty non-presence container or default leaf * @retval 1 Node is an (recursive) empty non-presence container or default leaf * @retval 0 Other node * @retval -1 Error * @note xn is not itself removed if purge + * @note for purge=1 are removed only if config or no yang spec(!) */ int xml_defaults_nopresence(cxobj *xn, @@ -1117,9 +1120,11 @@ xml_defaults_nopresence(cxobj *xn, cxobj *x; cxobj *xprev; yang_stmt *yn; + yang_stmt *y; int rmx = 0; /* If set, remove this xn */ int ret; enum rfc_6020 keyw; + int config = 0; if ((yn = xml_spec(xn)) != NULL){ keyw = yang_keyword_get(yn); @@ -1129,6 +1134,7 @@ xml_defaults_nopresence(cxobj *xn, else if (keyw == Y_LEAF && xml_flag(xn, XML_FLAG_DEFAULT)) rmx = 1; + config = yang_config_ancestor(yn); } /* Loop thru children */ x = NULL; @@ -1137,14 +1143,26 @@ xml_defaults_nopresence(cxobj *xn, if ((ret = xml_defaults_nopresence(x, purge)) < 0) goto done; if (ret == 1){ - if (purge){ + switch (purge){ + case 1: /* config nodes only */ + if (!config) + break; + if ((y = xml_spec(x)) != NULL && + !yang_config(y)) + break; + /* fall thru */ + case 2: /* purge all nodes */ if (xml_purge(x) < 0) goto done; x = xprev; + break; + default: + break; } } else if (rmx) - rmx = 0; + /* May switch an empty non-presence container (rmx=1) to non-empty non-presence container (rmx=0) */ + rmx = 0; } retval = rmx; done: diff --git a/test/test_yang_with_defaults.sh b/test/test_yang_with_defaults.sh index 455fa9db..988c7326 100755 --- a/test/test_yang_with_defaults.sh +++ b/test/test_yang_with_defaults.sh @@ -249,8 +249,12 @@ expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ Data already exists; cannot create new resource\ " # nothing to commit here, but just to verify + +new "2.3.3 (part 1) commit" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "" + # verify no change +new "2.3.3 (part 1) verify" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ "" "" \ "\ @@ -272,9 +276,13 @@ expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ none " \ "" \ "" + # commit change +new "2.3.3 (part 2) commit" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "" + # verify that the mtu value has changed +new "2.3.3 (part 2) verify" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ "" "" \ "\ @@ -296,9 +304,13 @@ expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ none" \ "" \ "" + # commit delete +new "2.3.3 (part 3) commit" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "" -# check thet the default mtu vale has been restored + +# check that the default mtu vale has been restored +new "2.3.3 (part 3) verify" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ "" "" \ "\ @@ -325,9 +337,13 @@ expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ error\ Data does not exist; cannot delete resource\ " + # nothing to commit +new "2.3.3 (part 4) commit" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "" + # verify that the configuration has not changed +new "2.3.3 (part 4) verify" expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ "" "" \ "\ @@ -411,13 +427,15 @@ expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \ " -new "rfc8040 4.3. RESTCONF GET" +new "rfc8040 4.3. RESTCONF GET json" expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example:interfaces)" \ 0 \ "HTTP/$HVER 200" \ "Content-Type: application/yang-data+json" \ "Cache-Control: no-cache" \ '{"example:interfaces":{"interface":\[{"name":"eth0","mtu":8192,"status":"ok"},{"name":"eth1","mtu":1500,"status":"ok"},{"name":"eth2","mtu":9000,"status":"not feeling so good"},{"name":"eth3","mtu":1500,"status":"waking up"}\]}}' + +new "rfc8040 4.3. RESTCONF GET xml" expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example:interfaces)" \ 0 \ "HTTP/$HVER 200" \ @@ -425,13 +443,15 @@ expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPR "Cache-Control: no-cache" \ 'eth08192oketh11500oketh29000not feeling so goodeth31500waking up' -new "rfc8040 B.3.9. RESTCONF with-defaults parameter = report-all" +new "rfc8040 B.3.9. RESTCONF with-defaults parameter = report-all json" expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example:interfaces/interface=eth1?with-defaults=report-all)" \ 0 \ "HTTP/$HVER 200" \ "Content-Type: application/yang-data+json" \ "Cache-Control: no-cache" \ '{"example:interface":\[{"name":"eth1","mtu":1500,"status":"ok"}\]}' + +new "rfc8040 B.3.9. RESTCONF with-defaults parameter = report-all xml" expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPROTO://localhost/restconf/data/example:interfaces/interface=eth1?with-defaults=report-all)" \ 0 \ "HTTP/$HVER 200" \ @@ -439,7 +459,7 @@ expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+xml' $RCPR "Cache-Control: no-cache" \ 'eth11500ok' -new "rfc8040 B.3.9. RESTONF with-defaults parameter = explicit" +new "rfc8040 B.3.9. RESTONF with-defaults parameter = explicit " expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/example:interfaces/interface=eth1?with-defaults=explicit)" \ 0 \ "HTTP/$HVER 200" \