diff --git a/apps/cli/cli_generate.c b/apps/cli/cli_generate.c index 39d95289..8e47315c 100644 --- a/apps/cli/cli_generate.c +++ b/apps/cli/cli_generate.c @@ -342,7 +342,7 @@ yang2cli_var_pattern(clicon_handle h, /* Forward */ static int yang2cli_stmt(clicon_handle h, yang_stmt *ys, enum genmodel_type gt, - int level, int state, cbuf *cb); + int level, int state, int show_tree, cbuf *cb); static int yang2cli_var_union(clicon_handle h, yang_stmt *ys, char *origtype, yang_stmt *ytype, char *helptext, cbuf *cb); @@ -633,6 +633,8 @@ yang2cli_var(clicon_handle h, * @param[in] gt CLI Generate style * @param[in] level Indentation level * @param[in] callback If set, include a "; cli_set()" callback, otherwise not + * @param[in] show_tree Is tree for show cli command + * @param[in] key_leaf Is leaf in a key in a list module * @param[out] cb Buffer where cligen code is written */ static int @@ -641,6 +643,8 @@ yang2cli_leaf(clicon_handle h, enum genmodel_type gt, int level, int callback, + int show_tree, + int key_leaf, cbuf *cb) { yang_stmt *yd; /* description */ @@ -663,12 +667,17 @@ yang2cli_leaf(clicon_handle h, if (helptext) cprintf(cb, "(\"%s\")", helptext); cprintf(cb, " "); + if ((show_tree == 0) || (key_leaf == 1)) { if (yang2cli_var(h, ys, helptext, cb) < 0) goto done; + } } else + if ((show_tree == 0) || (key_leaf == 1)) { if (yang2cli_var(h, ys, helptext, cb) < 0) goto done; + } + if (callback){ if (cli_callback_generate(h, ys, cb) < 0) goto done; @@ -688,6 +697,7 @@ yang2cli_leaf(clicon_handle h, * @param[in] gt CLI Generate style * @param[in] level Indentation level * @param[in] state Include syntax for state not only config + * @param[in] show_tree Is tree for show cli command * @param[out] cb Buffer where cligen code is written */ static int @@ -696,6 +706,7 @@ yang2cli_container(clicon_handle h, enum genmodel_type gt, int level, int state, + int show_tree, cbuf *cb) { yang_stmt *yc; @@ -727,7 +738,7 @@ yang2cli_container(clicon_handle h, yc = NULL; while ((yc = yn_each(ys, yc)) != NULL) - if (yang2cli_stmt(h, yc, gt, level+1, state, cb) < 0) + if (yang2cli_stmt(h, yc, gt, level+1, state, show_tree, cb) < 0) goto done; if (hide == 0) cprintf(cb, "%*s}\n", level*3, ""); @@ -744,6 +755,7 @@ yang2cli_container(clicon_handle h, * @param[in] gt CLI Generate style * @param[in] level Indentation level * @param[in] state Include syntax for state not only config + * @param[in] show_tree Is tree for show cli command * @param[out] cb Buffer where cligen code is written */ static int @@ -752,6 +764,7 @@ yang2cli_list(clicon_handle h, enum genmodel_type gt, int level, int state, + int show_tree, cbuf *cb) { yang_stmt *yc; @@ -763,6 +776,7 @@ yang2cli_list(clicon_handle h, int retval = -1; char *helptext = NULL; char *s; + int list_has_callback; cprintf(cb, "%*s%s", level*3, "", yang_argument_get(ys)); if ((yd = yang_find(ys, Y_DESCRIPTION, NULL)) != NULL){ @@ -788,9 +802,19 @@ yang2cli_list(clicon_handle h, /* Print key variable now, and skip it in loop below Note, only print callback on last statement */ + list_has_callback = cvec_next(cvk, cvi)?0:1; + if (show_tree == 1) { + if (list_has_callback) { + if (cli_callback_generate(h, ys, cb) < 0) + goto done; + cprintf(cb, ";\n"); + cprintf(cb, "{\n"); + } + } + if (yang2cli_leaf(h, yleaf, (gt==GT_VARS||gt==GT_HIDE)?GT_NONE:gt, level+1, - cvec_next(cvk, cvi)?0:1, cb) < 0) + list_has_callback, show_tree, 1, cb) < 0) goto done; } @@ -808,10 +832,13 @@ yang2cli_list(clicon_handle h, } if (cvi != NULL) continue; - if (yang2cli_stmt(h, yc, gt, level+1, state, cb) < 0) + if (yang2cli_stmt(h, yc, gt, level+1, state, show_tree, cb) < 0) goto done; } cprintf(cb, "%*s}\n", level*3, ""); + if ((show_tree == 1) && (list_has_callback)) { + cprintf(cb, "%*s}\n", level*3, ""); + } retval = 0; done: if (helptext) @@ -826,6 +853,7 @@ yang2cli_list(clicon_handle h, * @param[in] gt CLI Generate style * @param[in] level Indentation level * @param[in] state Include syntax for state not only config + * @param[in] show_tree Is tree for show cli command * @param[out] cb Buffer where cligen code is written @example choice interface-type { @@ -842,6 +870,7 @@ yang2cli_choice(clicon_handle h, enum genmodel_type gt, int level, int state, + int show_tree, cbuf *cb) { int retval = -1; @@ -851,7 +880,7 @@ yang2cli_choice(clicon_handle h, while ((yc = yn_each(ys, yc)) != NULL) { switch (yang_keyword_get(yc)){ case Y_CASE: - if (yang2cli_stmt(h, yc, gt, level+2, state, cb) < 0) + if (yang2cli_stmt(h, yc, gt, level+2, state, show_tree, cb) < 0) goto done; break; case Y_CONTAINER: @@ -859,7 +888,7 @@ yang2cli_choice(clicon_handle h, case Y_LEAF_LIST: case Y_LIST: default: - if (yang2cli_stmt(h, yc, gt, level+1, state, cb) < 0) + if (yang2cli_stmt(h, yc, gt, level+1, state, show_tree, cb) < 0) goto done; break; } @@ -875,6 +904,7 @@ yang2cli_choice(clicon_handle h, * @param[in] gt CLI Generate style * @param[in] level Indentation level * @param[in] state Include syntax for state not only config + * @param[in] show_tree Is tree for show cli command * @param[out] cb Buffer where cligen code is written */ static int @@ -883,6 +913,7 @@ yang2cli_stmt(clicon_handle h, enum genmodel_type gt, int level, int state, + int show_tree, cbuf *cb) { yang_stmt *yc; @@ -891,20 +922,20 @@ yang2cli_stmt(clicon_handle h, if (state || yang_config(ys)){ switch (yang_keyword_get(ys)){ case Y_CONTAINER: - if (yang2cli_container(h, ys, gt, level, state, cb) < 0) + if (yang2cli_container(h, ys, gt, level, state, show_tree, cb) < 0) goto done; break; case Y_LIST: - if (yang2cli_list(h, ys, gt, level, state, cb) < 0) + if (yang2cli_list(h, ys, gt, level, state, show_tree, cb) < 0) goto done; break; case Y_CHOICE: - if (yang2cli_choice(h, ys, gt, level, state, cb) < 0) + if (yang2cli_choice(h, ys, gt, level, state, show_tree, cb) < 0) goto done; break; case Y_LEAF_LIST: case Y_LEAF: - if (yang2cli_leaf(h, ys, gt, level, 1, cb) < 0) + if (yang2cli_leaf(h, ys, gt, level, 1, show_tree, 0, cb) < 0) goto done; break; case Y_CASE: @@ -912,7 +943,7 @@ yang2cli_stmt(clicon_handle h, case Y_MODULE: yc = NULL; while ((yc = yn_each(ys, yc)) != NULL) - if (yang2cli_stmt(h, yc, gt, level+1, state, cb) < 0) + if (yang2cli_stmt(h, yc, gt, level+1, state, show_tree, cb) < 0) goto done; break; default: /* skip */ @@ -930,6 +961,7 @@ yang2cli_stmt(clicon_handle h, * @param[in] gt CLI Generate style * @param[in] printgen Log generated CLIgen syntax * @param[in] state Also include state syntax + * @param[in] show_tree Is tree for show cli command * @param[out] ptnew CLIgen parse-tree * * Code generation styles: @@ -942,6 +974,7 @@ yang2cli(clicon_handle h, enum genmodel_type gt, int printgen, int state, + int show_tree, parse_tree *ptnew) { cbuf *cb = NULL; @@ -956,7 +989,7 @@ yang2cli(clicon_handle h, /* Traverse YANG, loop through all modules and generate CLI */ ymod = NULL; while ((ymod = yn_each(yspec, ymod)) != NULL) - if (yang2cli_stmt(h, ymod, gt, 0, state, cb) < 0) + if (yang2cli_stmt(h, ymod, gt, 0, state, show_tree, cb) < 0) goto done; if (printgen) clicon_log(LOG_NOTICE, "%s: Generated CLI spec:\n%s", __FUNCTION__, cbuf_get(cb)); diff --git a/apps/cli/cli_generate.h b/apps/cli/cli_generate.h index 819082d3..665c1bd6 100644 --- a/apps/cli/cli_generate.h +++ b/apps/cli/cli_generate.h @@ -53,6 +53,6 @@ * Prototypes */ int yang2cli(clicon_handle h, yang_stmt *yspec, enum genmodel_type gt, - int printgen, int state, parse_tree *ptnew); + int printgen, int state, int show_tree, parse_tree *ptnew); #endif /* _CLI_GENERATE_H_ */ diff --git a/apps/cli/cli_main.c b/apps/cli/cli_main.c index fe58b9e0..0be09a1b 100644 --- a/apps/cli/cli_main.c +++ b/apps/cli/cli_main.c @@ -242,6 +242,7 @@ cli_interactive(clicon_handle h) * @param[in] name Name of tree * @param[in] gt genmodel-type, ie HOW to generate the CLI * @param[in] printgen Print CLI syntax to stderr + * @param[in] show_tree Is tree for show cli command (1 - yes. 0 - no) * * Generate clispec (datamodel) from YANG dataspec and add to the set of cligen trees * (as a separate mode) @@ -259,7 +260,8 @@ autocli_tree(clicon_handle h, char *name, enum genmodel_type gt, int state, - int printgen) + int printgen, + int show_tree) { int retval = -1; parse_tree *pt = NULL; /* cli parse tree */ @@ -271,7 +273,7 @@ autocli_tree(clicon_handle h, } yspec = clicon_dbspec_yang(h); /* Generate tree (this is where the action is) */ - if (yang2cli(h, yspec, gt, printgen, state, pt) < 0) + if (yang2cli(h, yspec, gt, printgen, state, show_tree, pt) < 0) goto done; /* Append cligen tree and name it */ if (cligen_tree_add(cli_cligen(h), name, pt) < 0) @@ -300,7 +302,7 @@ autocli_start(clicon_handle h, { int retval = -1; int autocli_model = 0; - cbuf *treename = NULL; + cbuf *show_treename = NULL, *treename = NULL; enum genmodel_type gt; /* If autocli disabled quit */ @@ -308,26 +310,40 @@ autocli_start(clicon_handle h, goto ok; /* Get the autocli type, ie HOW the cli is generated (could be much more here) */ gt = clicon_cli_genmodel_type(h); + /* Create show_treename cbuf */ + if ((show_treename = cbuf_new()) == NULL){ + clicon_err(OE_UNIX, errno, "cbuf_new"); + goto done; + } /* Create treename cbuf */ if ((treename = cbuf_new()) == NULL){ clicon_err(OE_UNIX, errno, "cbuf_new"); goto done; } /* The tree name is by default @datamodel but can be changed by option (why would one do that?) */ - cprintf(treename, "%s", clicon_cli_model_treename(h)); - if (autocli_tree(h, cbuf_get(treename), gt, 0, printgen) < 0) + cprintf(treename, "%s", clicon_cli_model_treename(h)); + if (autocli_tree(h, cbuf_get(treename), gt, 0, printgen, 0) < 0) + goto done; + + /* The tree name is by default @datamodelshow but can be changed by option (why would one do that?) */ + cprintf(show_treename, "%s", clicon_cli_model_treename(h)); + cprintf(show_treename, "show"); + if (autocli_tree(h, cbuf_get(show_treename), gt, 0, printgen, 1) < 0) goto done; /* Create a tree for config+state. This tree's name has appended "state" to @datamodel (XXX) */ if (autocli_model > 1){ cprintf(treename, "state"); - if (autocli_tree(h, cbuf_get(treename), gt, 1, printgen) < 0) + if (autocli_tree(h, cbuf_get(treename), gt, 1, printgen, 1) < 0) goto done; } + ok: retval = 0; done: + if (show_treename) + cbuf_free(show_treename); if (treename) cbuf_free(treename); return retval; diff --git a/apps/cli/cli_show.c b/apps/cli/cli_show.c index cae26d0e..8967af92 100644 --- a/apps/cli/cli_show.c +++ b/apps/cli/cli_show.c @@ -704,10 +704,13 @@ cli_show_auto1(clicon_handle h, enum format_enum format = FORMAT_XML; cxobj *xt = NULL; cxobj *xp; + cxobj *xp_helper; cxobj *xerr; enum genmodel_type gt; char *api_path = NULL; char *prefix = NULL; + enum rfc_6020 ys_keyword; + int i = 0; if (cvec_len(argv) < 3 || cvec_len(argv) > 4){ clicon_err(OE_PLUGIN, 0, "Usage: * . (*) generated."); @@ -757,32 +760,46 @@ cli_show_auto1(clicon_handle h, clixon_netconf_error(xerr, "Get configuration", NULL); goto done; } - if ((xp = xpath_first(xt, nsc, "%s", xpath)) != NULL) + if ((xp = xpath_first(xt, nsc, "%s", xpath)) != NULL){ /* Print configuration according to format */ + ys_keyword = yang_keyword_get(xml_spec(xp)); + if (ys_keyword == Y_LIST) + xp_helper = xml_child_i(xml_parent(xp), i); + else + xp_helper = xp; + switch (format){ - case FORMAT_XML: - clicon_xml2file(stdout, xp, 0, 1); - break; - case FORMAT_JSON: - xml2json_cb(stdout, xp, 1, cligen_output); - break; - case FORMAT_TEXT: - xml2txt_cb(stdout, xp, cligen_output); /* tree-formed text */ - break; case FORMAT_CLI: if ((gt = clicon_cli_genmodel_type(h)) == GT_ERR) goto done; xml2cli_cb(stdout, xp, prefix, gt, cligen_output); /* cli syntax */ break; case FORMAT_NETCONF: - fprintf(stdout, "\n", - NETCONF_BASE_NAMESPACE); + fprintf(stdout, "\n"); clicon_xml2file(stdout, xp, 2, 1); fprintf(stdout, "]]>]]>\n"); break; - default: /* see cli_show_config() */ + default: + for (; i < xml_child_nr(xml_parent(xp)) ; ++i, xp_helper = xml_child_i(xml_parent(xp), i)) { + switch (format){ + case FORMAT_XML: + clicon_xml2file(stdout, xp_helper, 0, 1); + break; + case FORMAT_JSON: + xml2json_cb(stdout, xp_helper, 1, cligen_output); + break; + case FORMAT_TEXT: + xml2txt_cb(stdout, xp_helper, cligen_output); /* tree-formed text */ + break; + default: /* see cli_show_config() */ + break; + } + if (ys_keyword != Y_LIST) + break; + } break; } + } retval = 0; done: if (nsc)