From 798a9fbfcbd267e6cdd02e4728ffbab3f6b852a3 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Mon, 1 Jan 2024 21:56:51 +0100 Subject: [PATCH] Reworked exand/completion code for mountpoints Fixed: [Tab completion mounted devices with lists](https://github.com/clicon/clixon-controller/issues/72) --- CHANGELOG.md | 1 + apps/cli/cli_show.c | 63 ++++++++-------- lib/src/clixon_path.c | 115 +++++++++++++++-------------- lib/src/clixon_yang_schema_mount.c | 1 + 4 files changed, 92 insertions(+), 88 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9bf4d76..dfeede38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,7 @@ Developers may need to change their code ### Corrected Bugs +* Fixed: [Tab completion mounted devices with lists](https://github.com/clicon/clixon-controller/issues/72) * Fixed: kill-session cleanup when client none existant, and for all db:s * Fixed: [Using the characters '<' and '>' might cause an invalid diff](https://github.com/clicon/clixon-controller/issues/73) diff --git a/apps/cli/cli_show.c b/apps/cli/cli_show.c index a02bb91c..06205f46 100644 --- a/apps/cli/cli_show.c +++ b/apps/cli/cli_show.c @@ -48,7 +48,6 @@ #include #include #include - #include #include #include @@ -242,8 +241,6 @@ expand_dbvar(void *h, yang_stmt *ytype; char *mtpoint = NULL; yang_stmt *yspec0 = NULL; - yang_stmt *yspec; - yang_stmt *yu = NULL; cvec *nsc0 = NULL; char *str; int grouping_treeref; @@ -280,13 +277,14 @@ expand_dbvar(void *h, } if (grouping_treeref && (callback_cvv = cligen_callback_arguments_get(cli_cligen(h))) != NULL){ - /* Concatenate callback arguments to a singel prepend string */ + /* Concatenate callback arguments to a single prepend string */ if (cvec_concat_cb(callback_cvv, api_path_fmt_cb) < 0) goto done; } cprintf(api_path_fmt_cb, "%s", cv_string_get(cv)); api_path_fmt = cbuf_get(api_path_fmt_cb); - if (cvec_len(argv) > 2){ + if (cvec_len(argv) > 2){ /* mountpoint */ + /* api_path_fmt is without top-level */ cv = cvec_i(argv, 2); str = cv_string_get(cv); if (strncmp(str, "mtpoint:", strlen("mtpoint:")) != 0){ @@ -294,13 +292,18 @@ expand_dbvar(void *h, goto done; } mtpoint = str + strlen("mtpoint:"); + /* Get and combined api-path01 */ + if (mtpoint_paths(yspec0, mtpoint, api_path_fmt, &api_path_fmt01) < 0) + goto done; + if (api_path_fmt2api_path(api_path_fmt01, cvv, &api_path, &cvvi) < 0) + goto done; } - /* api_path_fmt = /interface/%s/address/%s - * api_path: --> /interface/eth0/address/.* - * xpath: --> /interface/[name="eth0"]/address - */ - if (api_path_fmt2api_path(api_path_fmt, cvv, &api_path, &cvvi) < 0) - goto done; + else{ + if (api_path_fmt2api_path(api_path_fmt, cvv, &api_path, &cvvi) < 0) + goto done; + } + if (api_path == NULL) + goto ok; /* Create config top-of-tree */ if ((xtop = xml_new(DATASTORE_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL) goto done; @@ -309,32 +312,28 @@ expand_dbvar(void *h, * xpath2xml would have worked!! * XXX: but y is just the first in this list, there could be other y:s? */ - yspec = yspec0; /* may be reset to mount yspec below */ - if (api_path){ - if (mtpoint){ - if (yang_path_arg(yspec0, mtpoint, &yu) < 0) - goto done; - if (yang_mount_get(yu, mtpoint, &yspec) < 0) - goto done; - } - if ((ret = api_path2xml(api_path, yspec, xtop, YC_DATANODE, 0, &xbot, &y, &xerr)) < 0) - goto done; - if (ret == 0){ - clixon_err_netconf(h, OE_NETCONF, 0, xerr, "Expand datastore symbol"); - goto done; - } - } - if (y==NULL) - goto ok; - /* Transform api-path to xpath for netconf */ - if (api_path2xpath(api_path, yspec, &xpath, &nsc, NULL) < 0) + if ((ret = api_path2xml(api_path, yspec0, xtop, YC_DATANODE, 0, &xbot, &y, &xerr)) < 0) goto done; + if (ret == 0){ + clixon_err_netconf(h, OE_NETCONF, 0, xerr, "Expand datastore symbol"); + goto done; + } + if (y == NULL){ + clixon_err(OE_YANG, 0, "y is NULL"); + goto done; + } + /* Transform api-path to xpath for netconf */ + if ((ret = api_path2xpath(api_path, yspec0, &xpath, &nsc, &xerr)) < 0) + goto done; + if (ret == 0){ + clixon_err_netconf(h, OE_NETCONF, 0, xerr, "Expand datastore symbol"); + goto done; + } if ((cbxpath = cbuf_new()) == NULL){ clixon_err(OE_UNIX, errno, "cbuf_new"); goto done; } if (mtpoint){ - cprintf(cbxpath, "%s", mtpoint); if (xml_nsctx_yangspec(yspec0, &nsc0) < 0) goto done; cv = NULL; /* Append nsc0 to nsc */ @@ -383,7 +382,7 @@ expand_dbvar(void *h, if (clicon_rpc_get_config(h, NULL, dbstr, cbuf_get(cbxpath), nsc, NULL, &xt) < 0) goto done; if ((xe = xpath_first(xt, NULL, "/rpc-error")) != NULL){ - clixon_err_netconf(h, OE_NETCONF, 0, xerr, "Get configuration"); + clixon_err_netconf(h, OE_NETCONF, 0, xe, "Get configuration"); goto ok; } if (xpath_vec(xt, nsc, "%s", &xvec, &xlen, cbuf_get(cbxpath)) < 0) diff --git a/lib/src/clixon_path.c b/lib/src/clixon_path.c index c03d3ea8..9bc8b16b 100644 --- a/lib/src/clixon_path.c +++ b/lib/src/clixon_path.c @@ -618,7 +618,6 @@ api_path_fmt2xpath(char *api_path_fmt, /*! Translate from restconf api-path(cvv) to xml xpath(cbuf) and namespace context * * @param[in] api_path URI-encoded path expression" (RFC8040 3.5.3) as cvec - * @param[in] offset Offset of cvec, where api-path starts * @param[in] yspec Yang spec * @param[in,out] xpath The xpath as cbuf (must be created and may have content) * @param[out] nsc Namespace context of xpath (free w xml_nsctx_free) @@ -652,12 +651,11 @@ api_path_fmt2xpath(char *api_path_fmt, * @see api_path2xpath Using strings as parameters */ static int -api_path2xpath_cvv(cvec *api_path, - int offset, - yang_stmt *yspec, - cbuf *xpath, - cvec **nscp, - cxobj **xerr) +api_path2xpath_cvv(cvec *api_path, + yang_stmt *yspec, + cbuf *xpath, + cvec **nscp, + cxobj **xerr) { int retval = -1; int i; @@ -682,6 +680,7 @@ api_path2xpath_cvv(cvec *api_path, char *decval; int ret; int root; + int ymtpoint; /* y is potential mount-point */ cprintf(xpath, "/"); /* Initialize namespace context */ @@ -691,8 +690,9 @@ api_path2xpath_cvv(cvec *api_path, clixon_err(OE_UNIX, errno, "cbuf_new"); goto done; } + ymtpoint = 0; root = 1; /* root or mountpoint */ - for (i=offset; i 0) + cprintf(xpath, "/"); + if (xprefix) + cprintf(xpath, "%s:", xprefix); + cprintf(xpath, "%s", name); /* Check if has value, means '=' */ if (cv_type_get(cv) == CGV_STRING){ /* val is uri percent encoded, eg x%2Cy,z */ @@ -759,11 +794,6 @@ api_path2xpath_cvv(cvec *api_path, cvk = yang_cvec_get(y); /* Use Y_LIST cache, see ys_populate_list() */ cvi = NULL; /* Iterate over individual yang keys */ - if (i != offset) - cprintf(xpath, "/"); - if (xprefix) - cprintf(xpath, "%s:", xprefix); - cprintf(xpath, "%s", name); vi = 0; while ((cvi = cvec_each(cvk, cvi)) != NULL && vi