Auto-cli updates and sync with clixon-docs

This commit is contained in:
Olof hagsand 2020-06-15 16:07:04 +02:00
parent cea5746597
commit 5120409a56
13 changed files with 178 additions and 99 deletions

View file

@ -63,9 +63,9 @@
#include "cli_plugin.h"
#include "cli_generate.h"
/* This is the default callback function. But this is typically overwritten */
#define GENERATE_CALLBACK "overwrite_me"
/*
* Constants
*/
/* variable expand function */
#define GENERATE_EXPAND_XMLDB "expand_dbvar"
@ -725,7 +725,6 @@ yang2cli_container(clicon_handle h,
cprintf(cb, ";{\n");
}
yc = NULL;
while ((yc = yn_each(ys, yc)) != NULL)
if (yang2cli_stmt(h, yc, gt, level+1, state, cb) < 0)
@ -972,10 +971,10 @@ yang2cli(clicon_handle h,
goto done;
cvec_free(globals);
/* Resolve the expand callback functions in the generated syntax.
This "should" only be GENERATE_EXPAND_XMLDB
handle=NULL for global namespace, this means expand callbacks must be in
CLICON namespace, not in a cli frontend plugin.
*/
* This "should" only be GENERATE_EXPAND_XMLDB
* handle=NULL for global namespace, this means expand callbacks must be in
* CLICON namespace, not in a cli frontend plugin.
*/
if (cligen_expandv_str2fn(ptnew, (expandv_str2fn_t*)clixon_str2fn, NULL) < 0)
goto done;

View file

@ -37,6 +37,18 @@
#ifndef _CLI_GENERATE_H_
#define _CLI_GENERATE_H_
/*
* Constants
*/
/* This is the default "virtual" callback function of the auto-cli. It should be overwritten by
* a callback specified in a clispec, such as:
* @code
* set @datamodel, cli_set();
* @endcode
* where the virtual callback (overwrite_me) is overwritten by cli_set.
*/
#define GENERATE_CALLBACK "overwrite_me"
/*
* Prototypes
*/

View file

@ -236,6 +236,103 @@ cli_interactive(clicon_handle h)
return retval;
}
/*! Generate one autocli clispec tree
*
* @param[in] h Clixon handle
* @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
*
* Generate clispec (datamodel) from YANG dataspec and add to the set of cligen trees
* (as a separate mode)
* This tree is referenced from the main CLI spec (CLICON_CLISPEC_DIR) using the "tree reference"
* syntax, ie @datamodel
* @param[in] h Clixon handle
* @param[in] printgen Print CLI syntax generated from dbspec
* @retval 0 OK
* @retval -1 Error
*
* @note that yang2cli generates syntax for ALL modules under the loaded yangspec.
*/
static int
autocli_tree(clicon_handle h,
char *name,
enum genmodel_type gt,
int state,
int printgen)
{
int retval = -1;
parse_tree *pt = NULL; /* cli parse tree */
yang_stmt *yspec;
if ((pt = pt_new()) == NULL){
clicon_err(OE_UNIX, errno, "pt_new");
goto done;
}
yspec = clicon_dbspec_yang(h);
/* Generate tree (this is where the action is) */
if (yang2cli(h, yspec, gt, printgen, state, pt) < 0)
goto done;
/* Append cligen tree and name it */
if (cligen_tree_add(cli_cligen(h), name, pt) < 0)
goto done;
retval = 0;
done:
return retval;
}
/*! Generate autocli, ie if enabled, generate clispec from YANG and add to cligen parse-trees
*
* Generate clispec (datamodel) from YANG dataspec and add to the set of cligen trees
* (as a separate mode)
* This tree is referenced from the main CLI spec (CLICON_CLISPEC_DIR) using the "tree reference"
* syntax, ie @datamodel
* Also (if enabled) generate a second "state" tree called @datamodelstate
*
* @param[in] h Clixon handle
* @param[in] printgen Print CLI syntax generated from dbspec
* @retval 0 OK
* @retval -1 Error
*/
static int
autocli_start(clicon_handle h,
int printgen)
{
int retval = -1;
int autocli_model = 0;
cbuf *treename = NULL;
enum genmodel_type gt;
/* If autocli disabled quit */
if ((autocli_model = clicon_cli_genmodel(h)) == 0)
goto ok;
/* Get the autocli type, ie HOW the cli is generated (could be much more here) */
gt = clicon_cli_genmodel_type(h);
/* 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)
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)
goto done;
}
ok:
retval = 0;
done:
if (treename)
cbuf_free(treename);
return retval;
}
static void
usage(clicon_handle h,
char *argv0)
@ -536,49 +633,9 @@ main(int argc,
if (clicon_nsctx_global_set(h, nsctx_global) < 0)
goto done;
/* Create tree generated from dataspec. If no other trees exists, this is
* the only one.
* The following code creates the tree @datamodel
* This tree is referenced from the main CLI spec (CLICON_CLISPEC_DIR)
* using the "tree reference"
* syntax, ie @datamodel
* But note that yang2cli generates syntax for ALL modules, not just for
* <module>.
*/
if (clicon_cli_genmodel(h)){
parse_tree *pt = NULL; /* cli parse tree */
cbuf *cbtreename;
parse_tree *pts = NULL; /* cli parse tree */
if ((pt = pt_new()) == NULL){
clicon_err(OE_UNIX, errno, "pt_new");
goto done;
}
if ((cbtreename = cbuf_new()) == NULL){
clicon_err(OE_UNIX, errno, "cbuf_new");
goto done;
}
cprintf(cbtreename, "%s", clicon_cli_model_treename(h));
/* Create cli command tree from dbspec
* label this tree @datamodel per default
*/
if (yang2cli(h, yspec, clicon_cli_genmodel_type(h), printgen, 0, pt) < 0)
goto done;
cligen_tree_add(cli_cligen(h), cbuf_get(cbtreename), pt);
/* same for config+state
* label this tree @datamodelstate per default
*/
if ((pts = pt_new()) == NULL){
clicon_err(OE_UNIX, errno, "pt_new");
goto done;
}
cprintf(cbtreename, "state");
if (yang2cli(h, yspec, clicon_cli_genmodel_type(h), 0, 1, pts) < 0)
goto done;
cligen_tree_add(cli_cligen(h), cbuf_get(cbtreename), pts);
if (cbtreename)
cbuf_free(cbtreename);
}
/* Create autocli from YANG */
if (autocli_start(h, printgen) < 0)
goto done;
/* Initialize cli syntax */
if (cli_syntax_load(h) < 0)

View file

@ -66,6 +66,7 @@
#include "clixon_cli_api.h"
#include "cli_plugin.h"
#include "cli_handle.h"
#include "cli_generate.h"
/*
*
@ -177,7 +178,7 @@ cli_syntax_unload(clicon_handle h)
* @param[in] handle Handle to plugin .so module as returned by dlopen
* @param[out] error Static error string, if set indicates error
* @retval fn Function pointer
* @retval NULL FUnction not found or symbol NULL (check error for proper handling)
* @retval NULL Function not found or symbol NULL (check error for proper handling)
* @see see cli_plugin_load where (optional) handle opened
* @note the returned function is not type-checked which may result in segv at runtime
*/
@ -188,8 +189,15 @@ clixon_str2fn(char *name,
{
void *fn = NULL;
/* Reset error */
*error = NULL;
/* Special check for auto-cli. If the virtual callback is used, it should be overwritten later
* by a callback given in the clispec, eg: set @datamodel, cli_set();
*/
if (strcmp(name, GENERATE_CALLBACK) == 0)
return NULL;
/* First check given plugin if any */
if (handle) {

View file

@ -450,7 +450,7 @@ cli_show_config1(clicon_handle h,
cvec *nsc = NULL;
char *prefix = NULL;
if (cvec_len(argv) < 3 && cvec_len(argv) > 5){
if (cvec_len(argv) < 3 || cvec_len(argv) > 5){
clicon_err(OE_PLUGIN, 0, "Got %d arguments. Expected: <dbname>,<format>,<xpath>[,<namespace>, [<prefix>]]", cvec_len(argv));
goto done;
@ -708,7 +708,7 @@ cli_show_auto1(clicon_handle h,
char *api_path = NULL;
char *prefix = NULL;
if (cvec_len(argv) < 3 && cvec_len(argv) > 4){
if (cvec_len(argv) < 3 || cvec_len(argv) > 4){
clicon_err(OE_PLUGIN, 0, "Usage: <api-path-fmt>* <database> <format> <prefix>. (*) generated.");
goto done;
}
@ -801,6 +801,7 @@ cli_show_auto1(clicon_handle h,
* <format> "text"|"xml"|"json"|"cli"|"netconf" (see format_enum)
* <prefix> to print before cli syntax outptu
* @see cli_show_auto_state For config and state
* @note SHOULD be used: ... @datamodel, cli_show_auto(<dbname>,...) to get correct #args
*/
int
cli_show_auto(clicon_handle h,