diff --git a/CHANGELOG.md b/CHANGELOG.md index c101f0cce..090e437e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,12 @@ Expected: February 2024 * Added reference count for shared yang-specs (schema mounts) * Allowed for sharing yspec+modules between several mountpoints +### API changes on existing protocol/config features +Users may have to change how they access the system + +* Revert the creators attribute feature introduced in 6.2. It is now obsoleted. + It is replaced with a configured `creators` and user/application semantics + ### C/CLI-API changes on existing features Developers may need to change their code diff --git a/lib/clixon/clixon_xml.h b/lib/clixon/clixon_xml.h index 8538d749b..312bc2206 100644 --- a/lib/clixon/clixon_xml.h +++ b/lib/clixon/clixon_xml.h @@ -234,14 +234,6 @@ uint16_t xml_flag(cxobj *xn, uint16_t flag); int xml_flag_set(cxobj *xn, uint16_t flag); int xml_flag_reset(cxobj *xn, uint16_t flag); -int xml_creator_add(cxobj *xn, char *name); -int xml_creator_rm(cxobj *xn, char *name); -int xml_creator_find(cxobj *xn, char *name); -size_t xml_creator_len(cxobj *xn); -cvec *xml_creator_get(cxobj *xn); -int xml_creator_copy_one(cxobj *x0, cxobj *x1); -int xml_creator_copy_all(cxobj *x0, cxobj *x1); - char *xml_value(cxobj *xn); int xml_value_set(cxobj *xn, char *val); int xml_value_append(cxobj *xn, char *val); diff --git a/lib/clixon/clixon_xml_map.h b/lib/clixon/clixon_xml_map.h index e3f844894..7d8d2c132 100644 --- a/lib/clixon/clixon_xml_map.h +++ b/lib/clixon/clixon_xml_map.h @@ -77,6 +77,5 @@ int xml_rpc_isaction(cxobj *xn); int xml_find_action(cxobj *xn, int top, cxobj **xap); int purge_tagged_nodes(cxobj *xn, char *ns, char *name, char *value, int keepnode); int clixon_compare_xmls(cxobj *xc1, cxobj *xc2, enum format_enum format); -int xml_creator_tree(cxobj *xt, cxobj **xcreator); #endif /* _CLIXON_XML_MAP_H_ */ diff --git a/lib/src/clixon_datastore_read.c b/lib/src/clixon_datastore_read.c index 0b092c5ab..2c18b43b9 100644 --- a/lib/src/clixon_datastore_read.c +++ b/lib/src/clixon_datastore_read.c @@ -442,56 +442,6 @@ disable_nacm_on_empty(cxobj *xt, return retval; } -/*! Read creator data from meta-data and add to xml internal annotation - * - * Iterate creator meta-data using xpaths and create internal creator annotations - * @param[in] h Clixon handle - * @param[in] xt XML top node - * @param[in] xn XML creators node - * On the form: - * - * testA[name='foo'] - * ... - * ... - * - * @see xml_creator_metadata_write - */ -static int -xml_creator_metadata_read(clixon_handle h, - cxobj *xn) -{ - int retval = -1; - cxobj *xt; - cxobj *xc; - cxobj *xp; - cxobj *x; - char *name; - char *xpath; - - xt = xml_root(xn); - xc = NULL; - while ((xc = xml_child_each(xn, xc, CX_ELMNT)) != NULL) { - if (strcmp(xml_name(xc), "creator")) - continue; - if ((name = xml_find_body(xc, "name")) == NULL) - continue; - xp = NULL; - while ((xp = xml_child_each(xc, xp, CX_ELMNT)) != NULL) { - if (strcmp(xml_name(xp), "path")) - continue; - if ((xpath = xml_body(xp)) == NULL) - continue; - if ((x = xpath_first(xt, NULL, "%s", xpath)) == NULL) - continue; - if (xml_creator_add(x, name) < 0) - goto done; - } - } - retval = 0; - done: - return retval; -} - /*! Common read function that reads an XML tree from file * * @param[in] th Datastore text handle @@ -593,19 +543,6 @@ xmldb_readfile(clixon_handle h, xml_flag_set(x0, XML_FLAG_TOP); if (xml_child_nr(x0) == 0 && de) de->de_empty = 1; - /* Check if creator attributes are supported*/ - if (clicon_option_bool(h, "CLICON_NETCONF_CREATOR_ATTR")){ - if ((x = xpath_first(x0, NULL, "creators")) != NULL){ - ns = NULL; - if (xml2ns(x, NULL, &ns) < 0) - goto done; - if (strcmp(ns, CLIXON_LIB_NS) == 0){ - if (xml_creator_metadata_read(h, x) < 0) - goto done; - xml_purge(x); - } - } - } /* Check if we support modstate */ if (clicon_option_bool(h, "CLICON_XMLDB_MODSTATE")) if ((msdiff = modstate_diff_new()) == NULL) diff --git a/lib/src/clixon_datastore_write.c b/lib/src/clixon_datastore_write.c index deccfb34f..dd65ce09b 100644 --- a/lib/src/clixon_datastore_write.c +++ b/lib/src/clixon_datastore_write.c @@ -493,7 +493,6 @@ text_modify(clixon_handle h, char *restype; int ismount = 0; yang_stmt *mount_yspec = NULL; - char *creator = NULL; if (x1 == NULL){ clixon_err(OE_XML, EINVAL, "x1 is missing"); @@ -534,13 +533,6 @@ text_modify(clixon_handle h, clicon_data_set(h, "objectexisted", "true"); } } - if (clicon_option_bool(h, "CLICON_NETCONF_CREATOR_ATTR")){ - /* Special clixon-lib attribute for keeping track of creator of objects */ - if ((ret = attr_ns_value(x1, "creator", CLIXON_LIB_NS, cbret, &creator)) < 0) - goto done; - if (ret == 0) - goto fail; - } x1name = xml_name(x1); if (yang_keyword_get(y0) == Y_LEAF_LIST || @@ -703,10 +695,6 @@ text_modify(clixon_handle h, xml_flag_reset(x0, XML_FLAG_DEFAULT); } } /* x1bstr */ - if (creator){ - if (xml_creator_add(x0, creator) < 0) - goto done; - } if (changed){ if (xml_insert(x0p, x0, insert, valstr, NULL) < 0) goto done; @@ -807,11 +795,6 @@ text_modify(clixon_handle h, * original object is not reverted. */ if (x0){ - if (clicon_option_bool(h, "CLICON_NETCONF_CREATOR_ATTR")){ - /* Recursively copy creator attributes from existing tree */ - if (xml_creator_copy_all(x0, x1) < 0) - goto done; - } xml_purge(x0); x0 = NULL; } @@ -862,10 +845,6 @@ text_modify(clixon_handle h, #ifdef XML_PARENT_CANDIDATE xml_parent_candidate_set(x0, x0p); #endif - if (clicon_option_bool(h, "CLICON_NETCONF_CREATOR_ATTR")){ - if (xml_creator_copy_one(x1, x0) < 0) - goto done; - } changed++; /* Get namespace from x1 * Check if namespace exists in x0 parent @@ -962,10 +941,6 @@ text_modify(clixon_handle h, if (ret == 0) goto fail; } - if (creator){ - if (xml_creator_add(x0, creator) < 0) - goto done; - } if (changed){ #ifdef XML_PARENT_CANDIDATE xml_parent_candidate_set(x0, NULL); @@ -1007,8 +982,6 @@ text_modify(clixon_handle h, free(instr); if (opstr) free(opstr); - if (creator) - free(creator); if (createstr) free(createstr); if (nscx1) @@ -1239,7 +1212,6 @@ xmldb_put(clixon_handle h, int firsttime = 0; int pretty; cxobj *xerr = NULL; - cxobj *xmeta = NULL; if (cbret == NULL){ clixon_err(OE_XML, EINVAL, "cbret is NULL"); @@ -1355,18 +1327,6 @@ xmldb_put(clixon_handle h, goto done; } pretty = clicon_option_bool(h, "CLICON_XMLDB_PRETTY"); - /* Add creator attributes to datastore */ - if (clicon_option_bool(h, "CLICON_NETCONF_CREATOR_ATTR")){ - /* @see xml_creator_metadata_read */ - if (xml_creator_tree(x0, &xmeta) < 0) - goto done; - if (xml_addsub(x0, xmeta) < 0) - goto done; - if (xml_child_nr_type(xmeta, CX_ELMNT) == 0){ - xml_purge(xmeta); - xmeta = NULL; - } - } if (strcmp(format,"json")==0){ if (clixon_json2file(f, x0, pretty, fprintf, 0, 0) < 0) goto done; @@ -1377,10 +1337,6 @@ xmldb_put(clixon_handle h, */ if (xmodst && xml_purge(xmodst) < 0) goto done; - if (clicon_option_bool(h, "CLICON_NETCONF_CREATOR_ATTR") && xmeta){ - if (xml_purge(xmeta) < 0) - goto done; - } retval = 1; done: if (f != NULL) diff --git a/lib/src/clixon_xml.c b/lib/src/clixon_xml.c index d06423b6b..83f3acec6 100644 --- a/lib/src/clixon_xml.c +++ b/lib/src/clixon_xml.c @@ -186,8 +186,6 @@ struct xml{ yang_stmt *x_spec; /* Pointer to specification, eg yang, by reference, dont free */ cg_var *x_cv; /* Cached value as cligen variable (set by xml_cmp) */ - cvec *x_creators; /* Support clixon-lib creator annotation. - Only if CLICON_NETCONF_CREATOR_ATTR = true */ #ifdef XML_EXPLICIT_INDEX struct search_index *x_search_index; /* explicit search index vectors */ #endif @@ -640,186 +638,6 @@ xml_flag_reset(cxobj *xn, return 0; } -/*! Add a creator tag - * - * @param[in] xn XML tree - * @param[in] name Name of creator tag - * @retval 0 OK - * @retval -1 Error - */ -int -xml_creator_add(cxobj *xn, - char *name) -{ - int retval = -1; - cg_var *cv; - - if (!is_element(xn)) - goto ok; - if (xn->x_creators == NULL){ - if ((xn->x_creators = cvec_new(0)) == NULL){ - clixon_err(OE_XML, errno, "cvec_new"); - goto done; - } - } - if ((cv = cvec_find(xn->x_creators, name)) == NULL) - cvec_add_string(xn->x_creators, name, NULL); - ok: - retval = 0; - done: - return retval; -} - -/*! Remove a creator tag - * - * @param[in] xn XML tree - * @param[in] name Name of creator tag - * @retval 0 OK - * @retval -1 Error - */ -int -xml_creator_rm(cxobj *xn, - char *name) -{ - cg_var *cv; - - if (!is_element(xn)) - return 0; - if ((cv = cvec_find(xn->x_creators, name)) == NULL) - return 0; - return cvec_del(xn->x_creators, cv); -} - -/*! Find a creator string - * - * @param[in] xn XML tree - * @param[in] name Name of creator tag - * @retval 1 Yes, xn is tagged with creator tag "name" - * @retval 0 No, xn is not tagged with creator tag "name" - */ -int -xml_creator_find(cxobj *xn, - char *name) -{ - if (!is_element(xn)) - return 0; - if (xn->x_creators != NULL && - cvec_find(xn->x_creators, name) != NULL) - return 1; - return 0; -} - -/*! Get number of creator strings - * - * @param[in] xn XML tree - * @retval len Number of creator tags assigned to xn - * @retval 0 No creator tags or non-applicable - */ -size_t -xml_creator_len(cxobj *xn) -{ - if (!is_element(xn)) - return 0; - if (xn->x_creators) - return cvec_len(xn->x_creators); - else - return 0; -} - -/*! Get all creator attributes - */ -cvec* -xml_creator_get(cxobj *xn) -{ - if (!is_element(xn)) - return 0; - return xn->x_creators; -} - -/*! Copy creator info from x0 to x1 single object - * - * @param[in] x0 Source XML node - * @param[in] x1 Destination XML node - * @retval 0 OK - * @retval -1 Error - */ -int -xml_creator_copy_one(cxobj *x0, - cxobj *x1) -{ - int retval = -1; - - if (x0->x_creators) - if ((x1->x_creators = cvec_dup(x0->x_creators)) == NULL){ - clixon_err(OE_UNIX, errno, "cvec_dup"); - goto done; - } - retval = 0; - done: - return retval; -} - -/*! Recursively copy creator attributes from existing tree based on equivalence algorithm - * - * @param[in] x0 Source XML node - * @param[in] x1 Destination XML node - * @retval 0 OK - * @retval -1 Error - * @see xml_tree_equal equivalence algorithm - */ -int -xml_creator_copy_all(cxobj *x0, - cxobj *x1) -{ - int retval = -1; - int eq; - cxobj *x0c; /* x0 child */ - cxobj *x1c; /* x1 child */ - yang_stmt *yc0; - yang_stmt *yc1; - - /* Traverse x0 and x1 in lock-step */ - x0c = x1c = NULL; - x0c = xml_child_each(x0, x0c, CX_ELMNT); - x1c = xml_child_each(x1, x1c, CX_ELMNT); - for (;;){ - if (x0c == NULL || x1c == NULL) - goto ok; - eq = xml_cmp(x0c, x1c, 0, 0, NULL); - if (eq < 0){ - x0c = xml_child_each(x0, x0c, CX_ELMNT); - continue; - } - else if (eq > 0){ - x1c = xml_child_each(x1, x1c, CX_ELMNT); - continue; - } - else { /* equal */ - /* Both x0c and x1c exists and are equal, check if they are yang-equal. */ - yc0 = xml_spec(x0c); - yc1 = xml_spec(x1c); - if (yc0 && yc1 && yc0 != yc1){ /* choice */ - ; - } - else { - if (x0c->x_creators){ - if (xml_creator_copy_one(x0c, x1c) < 0) - goto done; - } - else if (xml_creator_copy_all(x0c, x1c) < 0) - goto done; - } - } - x0c = xml_child_each(x0, x0c, CX_ELMNT); - x1c = xml_child_each(x1, x1c, CX_ELMNT); - } - ok: - retval = 0; - done: - return retval; -} - - /*! Get value of xnode * * @param[in] xn xml node @@ -2148,8 +1966,6 @@ xml_free(cxobj *x) #ifdef XML_EXPLICIT_INDEX xml_search_index_free(x); #endif - if (x->x_creators) - cvec_free(x->x_creators); break; case CX_BODY: case CX_ATTR: @@ -2192,8 +2008,6 @@ xml_copy_one(cxobj *x0, switch (xml_type(x0)){ case CX_ELMNT: xml_spec_set(x1, xml_spec(x0)); - if (xml_creator_copy_one(x0, x1) < 0) - goto done; break; case CX_BODY: case CX_ATTR: diff --git a/lib/src/clixon_xml_map.c b/lib/src/clixon_xml_map.c index 9832d8b6a..875b6ae17 100644 --- a/lib/src/clixon_xml_map.c +++ b/lib/src/clixon_xml_map.c @@ -2034,90 +2034,3 @@ clixon_compare_xmls(cxobj *xc1, unlink(filename2); return retval; } - -/*! Add creator data to metadata xml object on the form name:xpath* - * - * Callback function type for xml_apply - * @param[in] x XML node - * @param[in] arg General-purpose argument - * @retval 2 Locally abort this subtree, continue with others - * @retval 1 Abort, dont continue with others, return 1 to end user - * @retval 0 OK, continue - * @retval -1 Error, aborted at first error encounter, return -1 to end user - * On the form: - * - * testA[name='foo'] - * ... - * ... - * - */ -static int -xml_creator_one(cxobj *x, - void *arg) -{ - int retval = -1; - cxobj *xmeta = (cxobj*)arg; - cxobj *xmc; - cvec *cvv; - cg_var *cv; - char *val; - cvec *nsc = NULL; - char *xpath = NULL; - - if ((cvv = xml_creator_get(x)) == NULL){ - retval = 0; - goto done; - } - /* Note this requires x to have YANG spec */ - if (xml2xpath(x, nsc, 0, 0, &xpath) < 0) - goto done; - cv = NULL; - while ((cv = cvec_each(cvv, cv)) != NULL){ - val = cv_name_get(cv); - /* Find existing entry where name is val */ - xmc = NULL; - while ((xmc = xml_child_each(xmeta, xmc, CX_ELMNT)) != NULL){ - if (strcmp(xml_find_body(xmc, "name"), val) == 0) - break; - } - if (xmc != NULL){ - if (clixon_xml_parse_va(YB_NONE, NULL, &xmc, NULL, "%s", xpath) < 0) - goto done; - } - else { - if (clixon_xml_parse_va(YB_NONE, NULL, &xmeta, NULL, - "%s%s", - val, xpath) < 0) - goto done; - } - } - retval = 2; - done: - if (xpath) - free(xpath); - return retval; -} - -/*! Create creator data tree on the form (name:xpath*)* - * - * @param[in] xt XML top-level node, where to look for creator attributes - * @param[out] xcreators Created XML tree on the form ... - * @retval 0 OK - * @retval -1 Error - */ -int -xml_creator_tree(cxobj *xt, - cxobj **xcreators) -{ - int retval = -1; - - if ((*xcreators = xml_new("creators", NULL, CX_ELMNT)) == NULL) - goto done; - if (xmlns_set(*xcreators, NULL, CLIXON_LIB_NS) < 0) - goto done; - if (xml_apply(xt, CX_ELMNT, xml_creator_one, *xcreators) < 0) - goto done; - retval = 0; - done: - return retval; -} diff --git a/test/test_datastore_creator.sh b/test/test_datastore_creator.sh deleted file mode 100755 index 53f1caa9e..000000000 --- a/test/test_datastore_creator.sh +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/env bash -# test for data creator attribute: add same object from sessions s1 and s2 -# Restart and ensure attributes remain - -# Magic line must be first in script (see README.md) -s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi - -cfg=$dir/conf.xml -fyang=$dir/clixon-example.yang - -: ${clixon_util_xpath:=clixon_util_xpath} - -cat < $cfg - - $cfg - ${YANG_INSTALLDIR} - $dir - $fyang - $clispec - /usr/local/lib/$APPNAME/cli - example - /usr/local/var/run/$APPNAME.sock - /usr/local/var/run/$APPNAME.pidfile - $dir - true - -EOF - -cat < $fyang -module clixon-example{ - yang-version 1.1; - namespace "urn:example:clixon"; - prefix ex; - - container table { - list parameter{ - 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_backend -s init -f $cfg -fi - -new "wait backend 1" -wait_backend - -conf="-d candidate -b $dir -y $fyang" - -new "s1 add x" -expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "nonexfoo
" "" "" - -new "datastore get" -expectpart "$(sudo $clixon_util_xpath -f $dir/candidate_db -p /config/creators)" 0 "s1/table/parameter\[name=\"x\"\]" - -new "rpc get-config" -expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "xfoo
" "" - -# duplicate -new "s1 merge x" -expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "nonexfoo
" "" "" - -new "datastore get" -expectpart "$(sudo $clixon_util_xpath -f $dir/candidate_db -p /config/creators)" 0 "s1/table/parameter\[name=\"x\"\]" - -# New service -new "s2 merge x" -expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "nonexfoo
" "" "" - -new "datastore get" -expectpart "$(sudo $clixon_util_xpath -f $dir/candidate_db -p /config/creators)" 0 "s1/table/parameter\[name=\"x\"\]s2/table/parameter\[name=\"x\"\]" - -# New entry -new "s1 create y=bar" -expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "noneybar
" "" "" - -new "datastore get" -expectpart "$(sudo $clixon_util_xpath -f $dir/candidate_db -p /config/creators)" 0 "s1/table/parameter\[name=\"x\"\]/table/parameter\[name=\"y\"\]s2/table/parameter\[name=\"x\"\]" - -# To running -new "commit to running" -expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "" - -new "datastore get running" -expectpart "$(sudo $clixon_util_xpath -f $dir/running_db -p /config/creators)" 0 "s1/table/parameter\[name=\"x\"\]/table/parameter\[name=\"y\"\]s2/table/parameter\[name=\"x\"\]" - -new "rpc get-config" -expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "xfooybar
" "" - -if [ $BE -ne 0 ]; then - new "kill old backend" - sudo clixon_backend -zf $cfg - if [ $? -ne 0 ]; then - err - fi -fi - -if [ $BE -ne 0 ]; then - new "start backend -s running -f $cfg" - start_backend -s running -f $cfg -fi - -new "wait backend 2" -wait_backend - -new "datastore get running" -expectpart "$(sudo $clixon_util_xpath -f $dir/running_db -p /config/creators)" 0 "s1/table/parameter\[name=\"x\"\]/table/parameter\[name=\"y\"\]s2/table/parameter\[name=\"x\"\]" - -new "rpc get-config" -expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "xfooybar
" "" - -if [ $BE -ne 0 ]; then - new "kill old backend" - sudo clixon_backend -zf $cfg - if [ $? -ne 0 ]; then - err - fi -fi - -rm -rf $dir - -new "endtest" -endtest diff --git a/yang/clixon/clixon-config@2024-01-01.yang b/yang/clixon/clixon-config@2024-01-01.yang index 8d473e00a..77ad139c4 100644 --- a/yang/clixon/clixon-config@2024-01-01.yang +++ b/yang/clixon/clixon-config@2024-01-01.yang @@ -51,12 +51,14 @@ module clixon-config { revision 2024-01-01 { description - "Released in Clixon 6.6"; + "Makred as obsolete: + CLICON_NETCONF_CREATOR_ATTR + Released in Clixon 6.6"; } revision 2023-11-01 { description "Added options: - CLICON_CREATOR_ATTR + CLICON_NETCONF_CREATOR_ATTR Released in Clixon 6.5"; } revision 2023-05-01 { @@ -596,7 +598,10 @@ module clixon-config { If one such client/service is deleted, the object is deleted only if all services that created the object are deleted. The clixon controller uses this feature, but could in principle be used by other - applications."; + applications. + Marked as obsolete in 6.6 since creators attribute replaced by clixon-lib creators + config"; + status obsolete; } leaf CLICON_RESTCONF_API_ROOT { type string; diff --git a/yang/clixon/clixon-lib@2024-01-01.yang b/yang/clixon/clixon-lib@2024-01-01.yang index 6b46e019d..4cb8f37d0 100644 --- a/yang/clixon/clixon-lib@2024-01-01.yang +++ b/yang/clixon/clixon-lib@2024-01-01.yang @@ -70,7 +70,7 @@ module clixon-lib { revision 2024-01-01 { description - "Moved container creators to grouping/uses + "Moved container creators to grouping/uses and removed config false Released in 6.6.0"; } revision 2023-11-01 { @@ -217,8 +217,7 @@ module clixon-lib { } grouping clixon-creators{ container creators{ - config false; - description "Meta-data for creator attribute."; + description "Meta-data for creation of data objects."; list creator { key name; leaf name {