* Added cvv_i output parameter to api_path_fmt2api_path() to see how many cvv entries were used
* CLIspec dbxml API: Ability to specify deletion of _any_ vs _specific_ entry.
This commit is contained in:
parent
906d8bc63c
commit
96ab7292b9
7 changed files with 55 additions and 20 deletions
13
CHANGELOG.md
13
CHANGELOG.md
|
|
@ -29,6 +29,19 @@
|
||||||
## 4.10.0
|
## 4.10.0
|
||||||
Expected: February 2021
|
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
|
### Corrected Bugs
|
||||||
|
|
||||||
* [Presence container configs not displayed in 'show config set' #164 ](https://github.com/clicon/clixon/issues/164)
|
* [Presence container configs not displayed in 'show config set' #164 ](https://github.com/clicon/clixon/issues/164)
|
||||||
|
|
|
||||||
|
|
@ -172,7 +172,7 @@ cli_auto_edit(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* get api-path and xpath */
|
/* 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;
|
goto done;
|
||||||
/* Store this as edit-mode */
|
/* Store this as edit-mode */
|
||||||
if (clicon_data_set(h, "cli-edit-mode", api_path) < 0)
|
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);
|
cvec_append_var(cvv1, cv);
|
||||||
}
|
}
|
||||||
/* get api-path and xpath */
|
/* 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;
|
goto done;
|
||||||
/* Store this as edit-mode */
|
/* Store this as edit-mode */
|
||||||
clicon_data_set(h, "cli-edit-mode", api_path);
|
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)
|
if (cvec_append_var(cvv1, cvec_i(cvv, i)) < 0)
|
||||||
goto done;
|
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;
|
goto done;
|
||||||
/* Assign the variables */
|
/* Assign the variables */
|
||||||
if ((cvv2 = cvec_append(clicon_data_cvec_get(h, "cli-edit-cvv"), cvv1)) == NULL)
|
if ((cvv2 = cvec_append(clicon_data_cvec_get(h, "cli-edit-cvv"), cvv1)) == NULL)
|
||||||
|
|
|
||||||
|
|
@ -251,6 +251,7 @@ cli_dbxml(clicon_handle h,
|
||||||
cxobj *xerr = NULL;
|
cxobj *xerr = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
cg_var *cv;
|
cg_var *cv;
|
||||||
|
int cvv_i = 0;
|
||||||
|
|
||||||
if (cvec_len(argv) != 1){
|
if (cvec_len(argv) != 1){
|
||||||
clicon_err(OE_PLUGIN, EINVAL, "Requires one element to be xml key format string");
|
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);
|
arg = cvec_i(argv, 0);
|
||||||
api_path_fmt = cv_string_get(arg);
|
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;
|
goto done;
|
||||||
/* Create config top-of-tree */
|
/* Create config top-of-tree */
|
||||||
if ((xtop = xml_new("config", NULL, CX_ELMNT)) == NULL)
|
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 */
|
/* Add body last in case of leaf */
|
||||||
if (cvec_len(cvv) > 1 &&
|
if (cvec_len(cvv) > 1 &&
|
||||||
(yang_keyword_get(y) == Y_LEAF)){
|
(yang_keyword_get(y) == Y_LEAF)){
|
||||||
/* Add the body last */
|
/* Add the body last if there is remaining element that was not used in the
|
||||||
if (dbxml_body(xbot, cvv) < 0)
|
* earlier api-path transformation.
|
||||||
goto done;
|
* This is to handle differences between:
|
||||||
|
* DELETE <foo>bar</foo> and DELETE <foo/>
|
||||||
|
* 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 */
|
/* Loop over namespace context and add them to this leaf node */
|
||||||
cv = NULL;
|
cv = NULL;
|
||||||
while ((cv = cvec_each(nsctx, cv)) != NULL){
|
while ((cv = cvec_each(nsctx, cv)) != NULL){
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,7 @@ expand_dbvar(void *h,
|
||||||
char *reason = NULL;
|
char *reason = NULL;
|
||||||
cvec *nsc = NULL;
|
cvec *nsc = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
int cvvi = 0;
|
||||||
|
|
||||||
if (argv == NULL || cvec_len(argv) != 2){
|
if (argv == NULL || cvec_len(argv) != 2){
|
||||||
clicon_err(OE_PLUGIN, EINVAL, "requires arguments: <db> <xmlkeyfmt>");
|
clicon_err(OE_PLUGIN, EINVAL, "requires arguments: <db> <xmlkeyfmt>");
|
||||||
|
|
@ -150,7 +151,7 @@ expand_dbvar(void *h,
|
||||||
* api_path: --> /interface/eth0/address/.*
|
* api_path: --> /interface/eth0/address/.*
|
||||||
* xpath: --> /interface/[name="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;
|
goto done;
|
||||||
if (api_path2xpath(api_path, yspec, &xpath, &nsc, NULL) < 0)
|
if (api_path2xpath(api_path, yspec, &xpath, &nsc, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -711,6 +712,7 @@ cli_show_auto1(clicon_handle h,
|
||||||
char *prefix = NULL;
|
char *prefix = NULL;
|
||||||
enum rfc_6020 ys_keyword;
|
enum rfc_6020 ys_keyword;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
int cvvi = 0;
|
||||||
|
|
||||||
if (cvec_len(argv) < 3 || cvec_len(argv) > 4){
|
if (cvec_len(argv) < 3 || cvec_len(argv) > 4){
|
||||||
clicon_err(OE_PLUGIN, EINVAL, "Usage: <api-path-fmt>* <database> <format> <prefix>. (*) generated.");
|
clicon_err(OE_PLUGIN, EINVAL, "Usage: <api-path-fmt>* <database> <format> <prefix>. (*) generated.");
|
||||||
|
|
@ -734,7 +736,7 @@ cli_show_auto1(clicon_handle h,
|
||||||
clicon_err(OE_FATAL, 0, "No DB_SPEC");
|
clicon_err(OE_FATAL, 0, "No DB_SPEC");
|
||||||
goto done;
|
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;
|
goto done;
|
||||||
if (api_path2xpath(api_path, yspec, &xpath, &nsc, NULL) < 0)
|
if (api_path2xpath(api_path, yspec, &xpath, &nsc, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ typedef struct {
|
||||||
*/
|
*/
|
||||||
int xml_yang_root(cxobj *x, cxobj **xr);
|
int xml_yang_root(cxobj *x, cxobj **xr);
|
||||||
int yang2api_path_fmt(yang_stmt *ys, int inclkey, char **api_path_fmt);
|
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_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_path2xpath(char *api_path, yang_stmt *yspec, char **xpath, cvec **nsc, cxobj **xerr);
|
||||||
int api_path2xml(char *api_path, yang_stmt *yspec, cxobj *xtop,
|
int api_path2xml(char *api_path, yang_stmt *yspec, cxobj *xtop,
|
||||||
|
|
|
||||||
|
|
@ -424,6 +424,8 @@ yang2api_path_fmt(yang_stmt *ys,
|
||||||
* @param[in] api_path_fmt XML key format, eg /aaa/%s/name
|
* @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[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] 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 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @note first and last elements of cvv are not used,..
|
* @note first and last elements of cvv are not used,..
|
||||||
|
|
@ -446,16 +448,17 @@ yang2api_path_fmt(yang_stmt *ys,
|
||||||
int
|
int
|
||||||
api_path_fmt2api_path(const char *api_path_fmt,
|
api_path_fmt2api_path(const char *api_path_fmt,
|
||||||
cvec *cvv,
|
cvec *cvv,
|
||||||
char **api_path)
|
char **api_path,
|
||||||
|
int *cvv_i)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char c;
|
char c;
|
||||||
int esc=0;
|
int esc=0;
|
||||||
cbuf *cb = NULL;
|
cbuf *cb = NULL;
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
char *str;
|
char *str;
|
||||||
char *strenc=NULL;
|
char *strenc=NULL;
|
||||||
cg_var *cv;
|
cg_var *cv;
|
||||||
|
|
||||||
if ((cb = cbuf_new()) == NULL){
|
if ((cb = cbuf_new()) == NULL){
|
||||||
|
|
@ -498,6 +501,8 @@ api_path_fmt2api_path(const char *api_path_fmt,
|
||||||
clicon_err(OE_UNIX, errno, "strdup");
|
clicon_err(OE_UNIX, errno, "strdup");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (cvv_i) /* Last entry in cvv used */
|
||||||
|
*cvv_i = j;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (cb)
|
if (cb)
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ if [ $BE -ne 0 ]; then
|
||||||
new "start backend -s init -f $cfg"
|
new "start backend -s init -f $cfg"
|
||||||
start_backend -s init -f $cfg
|
start_backend -s init -f $cfg
|
||||||
|
|
||||||
new "waiting"
|
new "wait backend"
|
||||||
wait_backend
|
wait_backend
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
@ -69,6 +69,9 @@ expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><edit-config><target><ca
|
||||||
new "netconf commit"
|
new "netconf commit"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc $DEFAULTNS><commit/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
# race condition where backend is killed before flushed to disk
|
||||||
|
sleep $DEMSLEEP
|
||||||
|
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
# Check if premature kill
|
# Check if premature kill
|
||||||
pid=$(pgrep -u root -f clixon_backend)
|
pid=$(pgrep -u root -f clixon_backend)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue