diff --git a/CHANGELOG.md b/CHANGELOG.md index 83a75a6b..1556a53e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Clixon CHANGELOG -- Added validation for leafref forward and nackward references. +- Added completion for generated cli leafrefs for both absolute and relatve paths. + +- Added validation for leafref forward and backward references. - Added new backend plugin callback: "plugin_statedata()" for retreiving state data diff --git a/apps/cli/cli_main.c b/apps/cli/cli_main.c index f8c2a9c7..79b0a5ad 100644 --- a/apps/cli/cli_main.c +++ b/apps/cli/cli_main.c @@ -297,7 +297,8 @@ main(int argc, char **argv) char *dir = dirname(str); hash_del(clicon_options(h), (char*)"CLICON_YANG_MODULE_REVISION"); clicon_option_str_set(h, "CLICON_YANG_MODULE_MAIN", basename(optarg)); - clicon_option_str_set(h, "CLICON_YANG_DIR", strdup(dir)); + clicon_option_str_set(h, "CLICON_YANG_DIR", dir); + free(str); break; } default: diff --git a/apps/cli/cli_show.c b/apps/cli/cli_show.c index 05489770..134ee731 100644 --- a/apps/cli/cli_show.c +++ b/apps/cli/cli_show.c @@ -112,12 +112,24 @@ expand_dbvar(void *h, int j; int k; cg_var *cv; + yang_spec *yspec; + cxobj *xtop = NULL; /* xpath root */ + cxobj *xbot = NULL; /* xpath, NULL if datastore */ + yang_node *y = NULL; /* yang spec of xpath */ + yang_stmt *ytype; + yang_stmt *ypath; + cxobj *xcur; + char *xpathcur; if (argv == NULL || cvec_len(argv) != 2){ clicon_err(OE_PLUGIN, 0, "%s: requires arguments: ", __FUNCTION__); goto done; } + if ((yspec = clicon_dbspec_yang(h)) == NULL){ + clicon_err(OE_FATAL, 0, "No DB_SPEC"); + goto done; + } if ((cv = cvec_i(argv, 0)) == NULL){ clicon_err(OE_PLUGIN, 0, "%s: Error when accessing argument "); goto done; @@ -141,34 +153,46 @@ expand_dbvar(void *h, if (api_path_fmt2xpath(api_path, cvv, &xpath) < 0) goto done; /* XXX read whole configuration, why not send xpath? */ - if (clicon_rpc_get_config(h, dbstr, xpath, &xt) < 0) + if (clicon_rpc_get_config(h, dbstr, "/", &xt) < 0) goto done; if ((xerr = xpath_first(xt, "/rpc-error")) != NULL){ clicon_rpc_generate_error(xerr); goto done; } -#if 0 - /* Get xpath from datastore? - * 1. Get whole datastore, - * 2. Add tentative my location to xpath, - * 3. If leafref, compute relative xpath + xcur = xt; /* default top-of-tree */ + xpathcur = xpath; + /* Create config top-of-tree */ + if ((xtop = xml_new("config", NULL)) == NULL) + goto done; + xbot = xtop; + if (api_path && api_path2xml(api_path, yspec, xtop, &xbot, &y) < 0) + goto done; + /* Special case for leafref. Detect leafref via Yang-type, + * Get Yang path element, tentatively add the new syntax to the whole + * tree and apply the path to that. + * Last, the reference point for the xpath code below is changed to + * the point of the tentative new xml. + * Here the whole syntax tree is loaded, and it would be better to offload + * such operations to the datastore by a generic xpath function. */ - { - cxobj *xcur = NULL; /* xpath, NULL if datastore */ - // yang_node *y = NULL; /* yang spec of xpath */ - - if ((xcur = xpath_first(xt, xpath)) == NULL) - goto done; - - - } -#endif - + if ((ytype = yang_find((yang_node*)y, Y_TYPE, NULL)) != NULL) + if (strcmp(ytype->ys_argument, "leafref")==0){ + if ((ypath = yang_find((yang_node*)ytype, Y_PATH, NULL)) == NULL){ + clicon_err(OE_DB, 0, "Leafref %s requires path statement", ytype->ys_argument); + goto done; + } + xpathcur = ypath->ys_argument; + if (xml_merge(xt, xtop, yspec) < 0) + goto done; + if ((xcur = xpath_first(xt, xpath)) == NULL){ + clicon_err(OE_DB, 0, "xpath %s should return merged content", xpath); + goto done; + } + } /* One round to detect duplicates - * XXX The code below would benefit from some cleanup */ j = 0; - if (xpath_vec(xt, xpath, &xvec, &xlen) < 0) + if (xpath_vec(xcur, xpathcur, &xvec, &xlen) < 0) goto done; for (i = 0; i < xlen; i++) { char *str; @@ -211,6 +235,8 @@ expand_dbvar(void *h, done: if (xvec) free(xvec); + if (xtop) + xml_free(xtop); if (xt) xml_free(xt); if (xpath) diff --git a/test/test7.sh b/test/test7.sh index e7555e4a..d53a8f9f 100755 --- a/test/test7.sh +++ b/test/test7.sh @@ -37,14 +37,14 @@ module ietf-ip{ } leaf address { type leafref { - path "../../interface[name = current()/../ifname]" + path "../../interface[name=eth0]" + "/address/ip"; } } } } EOF - +# path "../../interface[name = current()/../ifname]" # kill old backend (if any) new "kill old backend"