From c5991c98441de03c167045f9cc9953cffa4ea3b3 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Tue, 5 Jun 2018 16:45:43 +0200 Subject: [PATCH] * Added a generated CLI show command that works on the generated parse tree with auto completion. * A typical call is: show @datamodel:example, cli_show_auto("candidate", "json"); * The example contains a more elaborate example. * Thanks ngashok for request, see https://github.com/clicon/clixon/issues/24 --- CHANGELOG.md | 4 ++ apps/cli/cli_generate.c | 1 + apps/cli/cli_show.c | 88 ++++++++++++++++++++++++++++++++++++++- apps/cli/clixon_cli_api.h | 2 + example/example_cli.cli | 5 ++- 5 files changed, 98 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9edfa55..c73fdc88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ * Example extended with inclusion of iana-if-type RFC 7224 interface identities * Applications which have not strictly enforced the identities may now have problems with validation and may need to be modified. ### Minor changes: +* Added a generated CLI show command that works on the generated parse tree with auto completion. + * A typical call is: show @datamodel:example, cli_show_auto("candidate", "json"); + * The example contains a more elaborate example. + * Thanks ngashok for request, see https://github.com/clicon/clixon/issues/24 * Added xmlns validation * for eg * Added yang identityref runtime validation diff --git a/apps/cli/cli_generate.c b/apps/cli/cli_generate.c index d4a2aca9..24c52c2f 100644 --- a/apps/cli/cli_generate.c +++ b/apps/cli/cli_generate.c @@ -141,6 +141,7 @@ cli_expand_var_generate(clicon_handle h, * @param[in] ys yang_stmt of the node at hand * @param[in] cb0 The string where the result format string is inserted. * @see cli_dbxml This is where the xmlkeyfmt string is used + * @see pt_callback_reference in CLIgen where the actual callback overwrites the template */ static int cli_callback_generate(clicon_handle h, diff --git a/apps/cli/cli_show.c b/apps/cli/cli_show.c index 94a4c7c4..52821f7a 100644 --- a/apps/cli/cli_show.c +++ b/apps/cli/cli_show.c @@ -417,7 +417,7 @@ show_yang(clicon_handle h, * @param[in] argv String vector: [] * Format of argv: * "running"|"candidate"|"startup" - * "text"|"xml"|"json"|"cli"|"netconf" (see format_enum) + * "text"|"xml"|"json"|"cli"|"netconf" (see format_enum) * xpath expression, that may contain one %, eg "/sender[name=%s]" * optional name of variable in cvv. If set, xpath must have a '%s' * @code @@ -600,6 +600,92 @@ int cli_show_version(clicon_handle h, cvec *vars, cvec *argv) return 0; } +/*! Generic show configuration CLIGEN callback using generated CLI syntax + * Format of argv: + * Generated API PATH + * "running"|"candidate"|"startup" + * "text"|"xml"|"json"|"cli"|"netconf" (see format_enum) + */ +int +cli_show_auto(clicon_handle h, + cvec *cvv, + cvec *argv) +{ + int retval = 1; + yang_spec *yspec; + char *api_path_fmt; /* xml key format */ + // char *api_path = NULL; /* xml key */ + char *db; + char *xpath; + char *formatstr; + enum format_enum format = FORMAT_XML; + cxobj *xt = NULL; + cxobj *xp; + cxobj *xerr; + enum genmodel_type gt; + + if (cvec_len(argv) != 3){ + clicon_err(OE_PLUGIN, 0, "%s: Usage: * . (*) generated.", __FUNCTION__); + goto done; + } + /* First argv argument: API_path format */ + api_path_fmt = cv_string_get(cvec_i(argv, 0)); + /* Second argv argument: Database */ + db = cv_string_get(cvec_i(argv, 1)); + /* Third format: output format */ + formatstr = cv_string_get(cvec_i(argv, 2)); + if ((format = format_str2int(formatstr)) < 0){ + clicon_err(OE_PLUGIN, 0, "Not valid format: %s", formatstr); + goto done; + } + if ((yspec = clicon_dbspec_yang(h)) == NULL){ + clicon_err(OE_FATAL, 0, "No DB_SPEC"); + goto done; + } + + // if (api_path_fmt2api_path(api_path_fmt, cvv, &api_path) < 0) + // goto done; + if (api_path_fmt2xpath(api_path_fmt, cvv, &xpath) < 0) + goto done; + /* Get configuration from database */ + if (clicon_rpc_get_config(h, db, xpath, &xt) < 0) + goto done; + if ((xerr = xpath_first(xt, "/rpc-error")) != NULL){ + clicon_rpc_generate_error("Get configuration", xerr); + goto done; + } + if ((xp = xpath_first(xt, xpath)) != NULL) + /* Print configuration according to format */ + switch (format){ + case FORMAT_XML: + clicon_xml2file(stdout, xp, 0, 1); + break; + case FORMAT_JSON: + xml2json(stdout, xp, 1); + break; + case FORMAT_TEXT: + xml2txt(stdout, xp, 0); /* tree-formed text */ + break; + case FORMAT_CLI: + if ((gt = clicon_cli_genmodel_type(h)) == GT_ERR) + goto done; + xml2cli(stdout, xp, NULL, gt); /* cli syntax */ + break; + case FORMAT_NETCONF: + fprintf(stdout, "\n"); + clicon_xml2file(stdout, xp, 2, 1); + fprintf(stdout, "]]>]]>\n"); + break; + default: /* see cli_show_config() */ + break; + } + retval = 0; + done: + if (xt) + xml_free(xt); + return retval; +} + #ifdef COMPAT_CLIV int show_yangv(clicon_handle h, cvec *vars, cvec *argv) { diff --git a/apps/cli/clixon_cli_api.h b/apps/cli/clixon_cli_api.h index 713ea521..c31645ba 100644 --- a/apps/cli/clixon_cli_api.h +++ b/apps/cli/clixon_cli_api.h @@ -142,6 +142,8 @@ int show_conf_xpath(clicon_handle h, cvec *cvv, cvec *argv); int cli_show_config(clicon_handle h, cvec *cvv, cvec *argv); +int cli_show_auto(clicon_handle h, cvec *cvv, cvec *argv); + #ifdef COMPAT_CLIV int cli_setv(clicon_handle h, cvec *vars, cvec *argv); int cli_mergev(clicon_handle h, cvec *vars, cvec *argv); diff --git a/example/example_cli.cli b/example/example_cli.cli index 8853aed2..1040f834 100644 --- a/example/example_cli.cli +++ b/example/example_cli.cli @@ -42,13 +42,16 @@ show("Show a particular state of the system"){ xml("Show configuration as XML"), cli_show_config("candidate", "xml", "/");{ @datamodel:example, cli_show_auto("candidate", "text"); } + cli("Show configuration as CLI commands"), cli_show_config("candidate", "cli", "/");{ + @datamodel:example, cli_show_auto("candidate", "cli"); + } netconf("Show configuration as netconf edit-config operation"), cli_show_config("candidate", "netconf", "/");{ @datamodel:example, cli_show_auto("candidate", "netconf"); } text("Show configuration as text"), cli_show_config("candidate","text","/");{ @datamodel:example, cli_show_auto("candidate", "text"); } - json("Show configuration as cli commands"), cli_show_config("candidate", "json", "/");{ + json("Show configuration as JSON"), cli_show_config("candidate", "json", "/");{ @datamodel:example, cli_show_auto("candidate", "json"); } }