diff --git a/CHANGELOG.md b/CHANGELOG.md index 66f6aaa9..c2ddb988 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,19 @@ ## 4.10.0 Expected: February 2021 +### C/CLI-API changes on existing features + +Developers may need to change their code + +* Added `cvv_i` output parameter to `api_path_fmt2api_path()` to see how many cvv entries were used. + +### API changes on existing protocol/config features + +Users may have to change how they access the system + +* CLIspec dbxml API: Ability to specify deletion of _any_ vs _specific_ entry. + * In a cli_del() call, the cvv arg list either exactly matches the api-format-path in which case _any_ deletion is specified, otherwise, if there is an extra element in the cvv list, that is used for a specific delete. + ### Corrected Bugs * [Presence container configs not displayed in 'show config set' #164 ](https://github.com/clicon/clixon/issues/164) diff --git a/apps/cli/cli_auto.c b/apps/cli/cli_auto.c index 4b679afa..30470181 100644 --- a/apps/cli/cli_auto.c +++ b/apps/cli/cli_auto.c @@ -172,7 +172,7 @@ cli_auto_edit(clicon_handle h, goto done; } /* get api-path and xpath */ - if (api_path_fmt2api_path(api_path_fmt, cvv2, &api_path) < 0) + if (api_path_fmt2api_path(api_path_fmt, cvv2, &api_path, NULL) < 0) goto done; /* Store this as edit-mode */ if (clicon_data_set(h, "cli-edit-mode", api_path) < 0) @@ -250,7 +250,7 @@ cli_auto_up(clicon_handle h, cvec_append_var(cvv1, cv); } /* get api-path and xpath */ - if (api_path_fmt2api_path(api_path_fmt1, cvv1, &api_path) < 0) + if (api_path_fmt2api_path(api_path_fmt1, cvv1, &api_path, NULL) < 0) goto done; /* Store this as edit-mode */ clicon_data_set(h, "cli-edit-mode", api_path); @@ -660,7 +660,7 @@ cli_auto_sub_enter(clicon_handle h, if (cvec_append_var(cvv1, cvec_i(cvv, i)) < 0) goto done; } - if (api_path_fmt2api_path(api_path_fmt, cvv1, &api_path) < 0) + if (api_path_fmt2api_path(api_path_fmt, cvv1, &api_path, NULL) < 0) goto done; /* Assign the variables */ if ((cvv2 = cvec_append(clicon_data_cvec_get(h, "cli-edit-cvv"), cvv1)) == NULL) diff --git a/apps/cli/cli_common.c b/apps/cli/cli_common.c index 40ea7d98..9ce400be 100644 --- a/apps/cli/cli_common.c +++ b/apps/cli/cli_common.c @@ -251,6 +251,7 @@ cli_dbxml(clicon_handle h, cxobj *xerr = NULL; int ret; cg_var *cv; + int cvv_i = 0; if (cvec_len(argv) != 1){ clicon_err(OE_PLUGIN, EINVAL, "Requires one element to be xml key format string"); @@ -262,7 +263,10 @@ cli_dbxml(clicon_handle h, } arg = cvec_i(argv, 0); api_path_fmt = cv_string_get(arg); - if (api_path_fmt2api_path(api_path_fmt, cvv, &api_path) < 0) + /* 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 */ if ((xtop = xml_new("config", NULL, CX_ELMNT)) == NULL) @@ -292,9 +296,17 @@ cli_dbxml(clicon_handle h, /* Add body last in case of leaf */ if (cvec_len(cvv) > 1 && (yang_keyword_get(y) == Y_LEAF)){ - /* Add the body last */ - if (dbxml_body(xbot, cvv) < 0) - goto done; + /* Add the body last if there is remaining element that was not used in the + * earlier api-path transformation. + * This is to handle differences between: + * DELETE bar and DELETE + * i.e., (1) deletion of a specific leaf entry vs (2) deletion of any entry + * Discussion: one can claim (1) is "bad" usage but one could see cases where + * you would want to delete a value if it has a specific value but not otherwise + */ + if (cvv_i != cvec_len(cvv)) + if (dbxml_body(xbot, cvv) < 0) + goto done; /* Loop over namespace context and add them to this leaf node */ cv = NULL; while ((cv = cvec_each(nsctx, cv)) != NULL){ diff --git a/apps/cli/cli_show.c b/apps/cli/cli_show.c index 0277677e..2eb736a6 100644 --- a/apps/cli/cli_show.c +++ b/apps/cli/cli_show.c @@ -121,6 +121,7 @@ expand_dbvar(void *h, char *reason = NULL; cvec *nsc = NULL; int ret; + int cvvi = 0; if (argv == NULL || cvec_len(argv) != 2){ clicon_err(OE_PLUGIN, EINVAL, "requires arguments: "); @@ -150,7 +151,7 @@ expand_dbvar(void *h, * api_path: --> /interface/eth0/address/.* * xpath: --> /interface/[name="eth0"]/address */ - if (api_path_fmt2api_path(api_path_fmt, cvv, &api_path) < 0) + if (api_path_fmt2api_path(api_path_fmt, cvv, &api_path, &cvvi) < 0) goto done; if (api_path2xpath(api_path, yspec, &xpath, &nsc, NULL) < 0) goto done; @@ -711,6 +712,7 @@ cli_show_auto1(clicon_handle h, char *prefix = NULL; enum rfc_6020 ys_keyword; int i = 0; + int cvvi = 0; if (cvec_len(argv) < 3 || cvec_len(argv) > 4){ clicon_err(OE_PLUGIN, EINVAL, "Usage: * . (*) generated."); @@ -734,7 +736,7 @@ cli_show_auto1(clicon_handle h, clicon_err(OE_FATAL, 0, "No DB_SPEC"); goto done; } - if (api_path_fmt2api_path(api_path_fmt, cvv, &api_path) < 0) + if (api_path_fmt2api_path(api_path_fmt, cvv, &api_path, &cvvi) < 0) goto done; if (api_path2xpath(api_path, yspec, &xpath, &nsc, NULL) < 0) goto done; diff --git a/lib/clixon/clixon_path.h b/lib/clixon/clixon_path.h index 906221ec..ce033347 100644 --- a/lib/clixon/clixon_path.h +++ b/lib/clixon/clixon_path.h @@ -77,7 +77,7 @@ typedef struct { */ int xml_yang_root(cxobj *x, cxobj **xr); int yang2api_path_fmt(yang_stmt *ys, int inclkey, char **api_path_fmt); -int api_path_fmt2api_path(const char *api_path_fmt, cvec *cvv, char **api_path); +int api_path_fmt2api_path(const char *api_path_fmt, cvec *cvv, char **api_path, int *cvvi); int api_path_fmt2xpath(char *api_path_fmt, cvec *cvv, char **xpath); int api_path2xpath(char *api_path, yang_stmt *yspec, char **xpath, cvec **nsc, cxobj **xerr); int api_path2xml(char *api_path, yang_stmt *yspec, cxobj *xtop, diff --git a/lib/src/clixon_path.c b/lib/src/clixon_path.c index 0c6cdcb1..d2413c0a 100644 --- a/lib/src/clixon_path.c +++ b/lib/src/clixon_path.c @@ -424,6 +424,8 @@ yang2api_path_fmt(yang_stmt *ys, * @param[in] api_path_fmt XML key format, eg /aaa/%s/name * @param[in] cvv cligen variable vector, one for every wildchar in api_path_fmt * @param[out] api_path api_path, eg /aaa/17. Free after use + * @param[out] cvvi 1..cvv-len. Index into cvv of last cvv entry used, For example, + * if same as len of cvv, all were used, if < some entries were not * @retval 0 OK * @retval -1 Error * @note first and last elements of cvv are not used,.. @@ -446,16 +448,17 @@ yang2api_path_fmt(yang_stmt *ys, int api_path_fmt2api_path(const char *api_path_fmt, cvec *cvv, - char **api_path) + char **api_path, + int *cvv_i) { - int retval = -1; - char c; - int esc=0; - cbuf *cb = NULL; - int i; - int j; - char *str; - char *strenc=NULL; + int retval = -1; + char c; + int esc=0; + cbuf *cb = NULL; + int i; + int j; + char *str; + char *strenc=NULL; cg_var *cv; if ((cb = cbuf_new()) == NULL){ @@ -498,6 +501,8 @@ api_path_fmt2api_path(const char *api_path_fmt, clicon_err(OE_UNIX, errno, "strdup"); goto done; } + if (cvv_i) /* Last entry in cvv used */ + *cvv_i = j; retval = 0; done: if (cb) diff --git a/test/test_upgrade_simple.sh b/test/test_upgrade_simple.sh index ab0b21a1..fba067c1 100755 --- a/test/test_upgrade_simple.sh +++ b/test/test_upgrade_simple.sh @@ -59,7 +59,7 @@ if [ $BE -ne 0 ]; then new "start backend -s init -f $cfg" start_backend -s init -f $cfg - new "waiting" + new "wait backend" wait_backend fi @@ -69,6 +69,9 @@ expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" +# race condition where backend is killed before flushed to disk +sleep $DEMSLEEP + new "Kill backend" # Check if premature kill pid=$(pgrep -u root -f clixon_backend)