diff --git a/apps/cli/cli_common.c b/apps/cli/cli_common.c index d076a304..8e5ef002 100644 --- a/apps/cli/cli_common.c +++ b/apps/cli/cli_common.c @@ -211,6 +211,53 @@ dbxml_body(cxobj *xbot, return retval; } +/*! Special handling of identityref:s whose body may be: : + * Ensure the namespace is declared if it exists in YANG +*/ +static int +identityref_add_ns(cxobj *x, + void *arg) +{ + int retval = -1; + yang_stmt *yspec = (yang_stmt *)arg; + yang_stmt *y; + yang_stmt *yrestype; /* resolved type */ + char *restype; /* resolved type */ + char *origtype = NULL; /* original type */ + char *pf = NULL; + yang_stmt *yns; + char *ns = NULL; + + if ((y = xml_spec(x)) != NULL && + yang_keyword_get(y) == Y_LEAF){ + if (yang_type_get(y, &origtype, &yrestype, NULL, NULL, NULL, NULL, NULL) < 0) + goto done; + restype = yrestype?yang_argument_get(yrestype):NULL; + if (strcmp(restype, "identityref") == 0){ + if (nodeid_split(xml_body(x), &pf, NULL) < 0) + goto done; + // search if already defined + if (pf != NULL){ + if (xml2ns(x, pf, &ns) < 0) + goto done; + if (ns == NULL && + (yns = yang_find_module_by_prefix_yspec(yspec, pf)) != NULL){ + if ((ns = yang_find_mynamespace(yns)) != NULL) + if (xmlns_set(x, pf, ns) < 0) + goto done; + } + } + } + } + retval = 0; + done: + if (origtype) + free(origtype); + if (pf) + free(pf); + return retval; +} + /*! Modify xml datastore from a callback using xml key format strings * @param[in] h Clicon handle * @param[in] cvv Vector of cli string and instantiated variables @@ -229,7 +276,7 @@ dbxml_body(cxobj *xbot, * @see cli_callback_generate where arg is generated * @note The last value may require namespace binding present in nsctx. Note that the nsctx * cannot normally be supplied by the clispec functions, such as cli_set, but need to be - * generated by afunction such as clixon_instance_id_bind() or other programmatically. + * generated by a function such as clixon_instance_id_bind() or other programmatically. */ int cli_dbxml(clicon_handle h, @@ -270,7 +317,6 @@ cli_dbxml(clicon_handle h, /* Transform template format string + cvv to actual api-path * cvv_i indicates if all cvv entries were used */ - if (api_path_fmt2api_path(api_path_fmt, cvv, &api_path, &cvv_i) < 0) goto done; /* Create config top-of-tree */ @@ -321,6 +367,11 @@ cli_dbxml(clicon_handle h, goto done; } } + /* Special handling of identityref:s whose body may be: : + * Ensure the namespace is declared if it exists in YANG + */ + if ((ret = xml_apply0(xbot, CX_ELMNT, identityref_add_ns, yspec)) < 0) + goto done; if ((cb = cbuf_new()) == NULL){ clicon_err(OE_XML, errno, "cbuf_new"); goto done; diff --git a/include/clixon_custom.h b/include/clixon_custom.h index 1be107b5..1f3e1b27 100644 --- a/include/clixon_custom.h +++ b/include/clixon_custom.h @@ -113,8 +113,8 @@ * Problem is that the tree is in an intermediate state so that a when condition may not see the * full context. * More specifically, new nodes (x0) are created without hooking them into the existing parent (x0p) - * and thus an xpath on the form ".."/PARENT may not be evaluated as they should. x0 is eventually - * added to its parent but then it is more difficult to check trhe when condition. + * and thus an xpath on the form "../PARENT" may not be evaluated as they should. x0 is eventually + * added to its parent but then it is more difficult to check the when condition. * This fix add the parent x0p as a "candidate" so that the xpath-eval function can use it as * an alernative if it exists. * Note although this solves many usecases involving parents and absolute paths, it still does not diff --git a/lib/src/clixon_datastore_write.c b/lib/src/clixon_datastore_write.c index d4b9d40b..cfeae292 100644 --- a/lib/src/clixon_datastore_write.c +++ b/lib/src/clixon_datastore_write.c @@ -163,7 +163,6 @@ check_body_namespace(cxobj *x0, cxobj *x; int isroot; cbuf *cberr = NULL; - int ret; /* XXX: need to identify root better than hiereustics and strcmp,... */ isroot = xml_parent(x0p)==NULL && @@ -221,6 +220,7 @@ bad-attribue? #endif else{ /* Namespace does not exist in x0: error */ #ifdef IDENTITYREF_KLUDGE + int ret; if (ns1 == NULL){ if ((ret = yang_find_namespace_by_prefix(y, prefix, &ns0)) < 0) goto done; diff --git a/lib/src/clixon_json.c b/lib/src/clixon_json.c index 74b519e5..d2b7c106 100644 --- a/lib/src/clixon_json.c +++ b/lib/src/clixon_json.c @@ -347,17 +347,11 @@ json2xml_decode_identityref(cxobj *x, __FUNCTION__, prefix, body, ns); if (!xml_nsctx_get_prefix(nsc, ns, &prefix2)){ /* (no) insert a xmlns: statement - * Get yang prefix from import statement of my mod */ - if (yang_find_prefix_by_namespace(y, ns, &prefix2) == 0){ -#ifndef IDENTITYREF_KLUDGE - /* Just get the prefix from the module's own namespace */ - if (xerr && netconf_unknown_namespace_xml(xerr, "application", - ns, - "No local prefix corresponding to namespace") < 0) - goto done; - goto fail; -#endif - } + * Get yang prefix from import statement of my mod + * I am not sure this is correct + */ + if (yang_find_prefix_by_namespace(y, ns, &prefix2) < 0) + goto done; /* if prefix2 is NULL here, we get the canonical prefix */ if (prefix2 == NULL) prefix2 = yang_find_myprefix(ymod); diff --git a/test/test_identity.sh b/test/test_identity.sh index bf6134ce..56b78d68 100755 --- a/test/test_identity.sh +++ b/test/test_identity.sh @@ -280,7 +280,7 @@ new "cli validate" expectpart "$($clixon_cli -1 -f $cfg -l o validate)" 0 "^$" new "Netconf set acl-type" -expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "xmc:ipv4-acl-type" "" "" +expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "xmc:ipv4-acl-type" "" "" new "netconf validate " expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" ""