* Auto-CLI enhancements
* A generated clispec including state (default @datanodestate) also generated along with the config clispec tree (default @datanode) * New mode `GT_HIDE` set by option `CLICON_CLI_GENMODEL_TYPE` to collapse non-presence containers that only contain a single list * Added a prfix for cli_show_config/cli_show_auto so that it can produce parseable output * Thanks dcornejo@netgate.com for trying it out and suggestions
This commit is contained in:
parent
e2d9c046af
commit
e898dda016
16 changed files with 319 additions and 86 deletions
|
|
@ -58,20 +58,24 @@
|
|||
*/
|
||||
/*! Controls how keywords a generated in CLI syntax / prints from object model
|
||||
* Example YANG:
|
||||
* container c{
|
||||
* list a {
|
||||
* key x;
|
||||
* leaf x;
|
||||
* leaf y;
|
||||
* }
|
||||
* NONE: a <x> <y>;
|
||||
* VARS: a <x> y <y>;
|
||||
* ALL: a x <x> y <y>;
|
||||
* }
|
||||
* NONE: c a <x> <y>;
|
||||
* VARS: c a <x> y <y>;
|
||||
* ALL: c a x <x> y <y>;
|
||||
* HIDE: a x <x> y <y>;
|
||||
*/
|
||||
enum genmodel_type{
|
||||
GT_ERR =-1, /* Error */
|
||||
GT_NONE=0, /* No extra keywords */
|
||||
GT_VARS, /* Keywords on non-key variables */
|
||||
GT_ALL, /* Keywords on all variables */
|
||||
GT_HIDE, /* Keywords on all variables and hide container around lists */
|
||||
};
|
||||
|
||||
/*! See clixon-config.yang type startup_mode */
|
||||
|
|
|
|||
|
|
@ -245,6 +245,7 @@ int yang_config(yang_stmt *ys);
|
|||
int yang_config_ancestor(yang_stmt *ys);
|
||||
int yang_features(clicon_handle h, yang_stmt *yt);
|
||||
cvec *yang_arg2cvec(yang_stmt *ys, char *delimi);
|
||||
int yang_container_cli_hide(yang_stmt *ys, int gt);
|
||||
int yang_key_match(yang_stmt *yn, char *name);
|
||||
|
||||
int yang_type_cache_regexp_set(yang_stmt *ytype, int rxmode, cvec *regexps);
|
||||
|
|
|
|||
|
|
@ -1305,8 +1305,9 @@ netconf_module_load(clicon_handle h)
|
|||
/* Load yang spec */
|
||||
if (yang_spec_parse_module(h, "ietf-netconf", NULL, yspec)< 0)
|
||||
goto done;
|
||||
if (yang_spec_parse_module(h, "clixon-rfc5277", NULL, yspec)< 0)
|
||||
goto done;
|
||||
if (clicon_option_bool(h, "CLICON_STREAM_DISCOVERY_RFC5277"))
|
||||
if (yang_spec_parse_module(h, "clixon-rfc5277", NULL, yspec)< 0)
|
||||
goto done;
|
||||
/* YANG module revision change management */
|
||||
if (clicon_option_bool(h, "CLICON_XML_CHANGELOG"))
|
||||
if (yang_spec_parse_module(h, "clixon-xml-changelog", NULL, yspec)< 0)
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ static const map_str2int cli_genmodel_map[] = {
|
|||
{"NONE", GT_NONE},
|
||||
{"VARS", GT_VARS},
|
||||
{"ALL", GT_ALL},
|
||||
{"HIDE", GT_HIDE},
|
||||
{NULL, -1}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ xml2cli(FILE *f,
|
|||
if (yang_keyword_get(ys) == Y_LEAF || yang_keyword_get(ys) == Y_LEAF_LIST){
|
||||
if (prepend0)
|
||||
fprintf(f, "%s", prepend0);
|
||||
if (gt == GT_ALL || gt == GT_VARS)
|
||||
if (gt == GT_ALL || gt == GT_VARS || gt == GT_HIDE)
|
||||
fprintf(f, "%s ", xml_name(x));
|
||||
if ((body = xml_body(x)) != NULL){
|
||||
if (index(body, ' '))
|
||||
|
|
@ -224,7 +224,12 @@ xml2cli(FILE *f,
|
|||
}
|
||||
if (prepend0)
|
||||
cprintf(cbpre, "%s", prepend0);
|
||||
cprintf(cbpre, "%s ", xml_name(x));
|
||||
|
||||
/* If non-presence container && HIDE mode && only child is
|
||||
* a list, then skip container keyword
|
||||
* See also yang2cli_container */
|
||||
if (yang_container_cli_hide(ys, gt) == 0)
|
||||
cprintf(cbpre, "%s ", xml_name(x));
|
||||
|
||||
if (yang_keyword_get(ys) == Y_LIST){
|
||||
/* If list then first loop through keys */
|
||||
|
|
|
|||
|
|
@ -2537,6 +2537,54 @@ yang_arg2cvec(yang_stmt *ys,
|
|||
return cvv;
|
||||
}
|
||||
|
||||
/*! Check if yang is subject to generated cli GT_HIDE boolean
|
||||
* The yang should be:
|
||||
* 1) a non-presence container
|
||||
* 2) parent of a (single) list XXX: or could multiple lists work?
|
||||
* 3) no other data node children
|
||||
* @retval 0 No, does not satisfy the GT_HIDE condition
|
||||
* @retval 1 Yes, satisfies the GT_HIDE condition
|
||||
* @see clixon-config.yang HIDE enumeration type
|
||||
*/
|
||||
int
|
||||
yang_container_cli_hide(yang_stmt *ys,
|
||||
enum genmodel_type gt)
|
||||
{
|
||||
yang_stmt *yc = NULL;
|
||||
int i;
|
||||
enum rfc_6020 keyw;
|
||||
|
||||
keyw = yang_keyword_get(ys);
|
||||
/* HIDE mode */
|
||||
if (gt != GT_HIDE)
|
||||
return 0;
|
||||
/* A container */
|
||||
if (yang_keyword_get(ys) != Y_CONTAINER)
|
||||
return 0;
|
||||
/* Non-presence */
|
||||
if (yang_find(ys, Y_PRESENCE, NULL) != NULL)
|
||||
return 0;
|
||||
/* Ensure a single list child and no other data nodes */
|
||||
i = 0; /* Number of list nodes */
|
||||
while ((yc = yn_each(ys, yc)) != NULL) {
|
||||
keyw = yang_keyword_get(yc);
|
||||
/* case/choice could hide anything so disqualify those */
|
||||
if (keyw == Y_CASE || keyw == Y_CHOICE)
|
||||
break;
|
||||
if (!yang_datanode(yc)) /* Allowed, check next */
|
||||
continue;
|
||||
if (keyw != Y_LIST) /* Another datanode than list */
|
||||
break;
|
||||
if (i++>0) /* More than one list (or could this work?) */
|
||||
break;
|
||||
}
|
||||
if (yc != NULL) /* break from loop */
|
||||
return 0;
|
||||
if (i != 1) /* List found */
|
||||
return 0;
|
||||
return 1; /* Passed all tests: yes you can hide this keyword */
|
||||
}
|
||||
|
||||
/*! Check if yang node yn has key-stmt as child which matches name
|
||||
*
|
||||
* The function looks at the LIST argument string (not actual children)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue