Showing syntax using CLI commands was broekn and is fixed.

This commit is contained in:
Olof hagsand 2018-04-22 21:36:55 +02:00
parent 1913407e52
commit 50522df3d9
6 changed files with 67 additions and 70 deletions

View file

@ -103,6 +103,7 @@ enables saved files to be used as datastore without any editing. Thanks Matt.
* Added cli_show_version() * Added cli_show_version()
### Corrected Bugs ### Corrected Bugs
* Showing syntax using CLI commands was broekn and is fixed.
* Fixed issue https://github.com/clicon/clixon/issues/18 RPC response issues reported by Stephen Jones at Netgate * Fixed issue https://github.com/clicon/clixon/issues/18 RPC response issues reported by Stephen Jones at Netgate
* Fixed issue https://github.com/clicon/clixon/issues/17 special character in strings can break RPCs reported by David Cornejo at Netgate. * Fixed issue https://github.com/clicon/clixon/issues/17 special character in strings can break RPCs reported by David Cornejo at Netgate.
* This was a large rewright of XML parsing and output due to CharData not correctly encoded according to https://www.w3.org/TR/2008/REC-xml-20081126. * This was a large rewright of XML parsing and output due to CharData not correctly encoded according to https://www.w3.org/TR/2008/REC-xml-20081126.

View file

@ -50,7 +50,6 @@
/*! Controls how keywords a generated in CLI syntax / prints from object model /*! Controls how keywords a generated in CLI syntax / prints from object model
* Example YANG: * Example YANG:
* list a {a.b[] $!x $y:
* list a { * list a {
* key x; * key x;
* leaf x; * leaf x;
@ -63,7 +62,7 @@
enum genmodel_type{ enum genmodel_type{
GT_ERR =-1, /* Error */ GT_ERR =-1, /* Error */
GT_NONE=0, /* No extra keywords */ GT_NONE=0, /* No extra keywords */
GT_VARS, /* Keywords on non-index variables */ GT_VARS, /* Keywords on non-key variables */
GT_ALL, /* Keywords on all variables */ GT_ALL, /* Keywords on all variables */
}; };

View file

@ -89,19 +89,6 @@
#include "clixon_xml_sort.h" #include "clixon_xml_sort.h"
#include "clixon_xml_map.h" #include "clixon_xml_map.h"
/*
* A node is a leaf if it contains a body.
*/
static cxobj *
leaf(cxobj *xn)
{
cxobj *xc = NULL;
while ((xc = xml_child_each(xn, xc, CX_BODY)) != NULL)
break;
return xc;
}
/*! x is element and has eactly one child which in turn has none */ /*! x is element and has eactly one child which in turn has none */
static int static int
tleaf(cxobj *x) tleaf(cxobj *x)
@ -118,6 +105,7 @@ tleaf(cxobj *x)
/*! Translate XML -> TEXT /*! Translate XML -> TEXT
* @param[in] level print 4 spaces per level in front of each line * @param[in] level print 4 spaces per level in front of each line
* XXX rewrite using YANG and remove encrypted password KLUDGE
*/ */
int int
xml2txt(FILE *f, xml2txt(FILE *f,
@ -184,69 +172,60 @@ xml2cli(FILE *f,
{ {
int retval = -1; int retval = -1;
cxobj *xe = NULL; cxobj *xe = NULL;
char *term; cbuf *cbpre = NULL;
int bool; yang_stmt *ys;
int nr; int match;
int i; char *body;
cbuf *cbpre;
// yang_stmt *ys;
// ys = yang_spec(x); ys = xml_spec(x);
if (ys->ys_keyword == Y_LEAF || ys->ys_keyword == Y_LEAF_LIST){
if (prepend0)
fprintf(f, "%s", prepend0);
body = xml_body(x);
if (gt == GT_ALL || gt == GT_VARS)
fprintf(f, "%s ", xml_name(x));
if (index(body, ' '))
fprintf(f, "\"%s\"", body);
else
fprintf(f, "%s", body);
fprintf(f, "\n");
goto ok;
}
/* Create prepend variable string */ /* Create prepend variable string */
if ((cbpre = cbuf_new()) == NULL){ if ((cbpre = cbuf_new()) == NULL){
clicon_err(OE_PLUGIN, errno, "cbuf_new"); clicon_err(OE_PLUGIN, errno, "cbuf_new");
goto done; goto done;
} }
nr = xml_child_nr(x);
if (!nr){
if (xml_type(x) == CX_BODY)
term = xml_value(x);
else
term = xml_name(x);
if (prepend0)
fprintf(f, "%s ", prepend0);
if (index(term, ' '))
fprintf(f, "\"%s\"\n", term);
else
fprintf(f, "%s\n", term);
retval = 0;
goto done;
}
if (prepend0) if (prepend0)
cprintf(cbpre, "%s", prepend0); cprintf(cbpre, "%s", prepend0);
/* bool determines when to print a variable keyword: cprintf(cbpre, "%s ", xml_name(x));
!leaf T for all (ie parameter)
index GT_NONE F if (ys->ys_keyword == Y_LIST){
index GT_VARS F /* If list then first loop through keys */
index GT_ALL T xe = NULL;
!index GT_NONE F while ((xe = xml_child_each(x, xe, -1)) != NULL){
!index GT_VARS T if ((match = yang_key_match((yang_node*)ys, xml_name(xe))) < 0)
!index GT_ALL T
*/
bool = !leaf(x) || gt == GT_ALL || (gt == GT_VARS);
// bool = (!x->xn_index || gt == GT_ALL);
if (bool){
if (cbuf_len(cbpre))
cprintf(cbpre, " ");
cprintf(cbpre, "%s", xml_name(x));
}
xe = NULL;
/* First child is unique, then add that, before looping. */
i = 0;
while ((xe = xml_child_each(x, xe, -1)) != NULL){
/* Dont call this if it is index and there are other following */
if (0 && i < nr-1)
;
else
if (xml2cli(f, xe, cbuf_get(cbpre), gt) < 0)
goto done; goto done;
if (0){ /* assume index is first, otherwise need one more while */ if (!match)
continue;
if (gt == GT_ALL) if (gt == GT_ALL)
cprintf(cbpre, " %s", xml_name(xe)); cprintf(cbpre, "%s ", xml_name(xe));
cprintf(cbpre, " %s", xml_value(xml_child_i(xe, 0))); cprintf(cbpre, "%s ", xml_body(xe));
} }
i++;
} }
/* Then loop through all other (non-keys) */
xe = NULL;
while ((xe = xml_child_each(x, xe, -1)) != NULL){
if (ys->ys_keyword == Y_LIST){
if ((match = yang_key_match((yang_node*)ys, xml_name(xe))) < 0)
goto done;
if (match)
continue;
}
if (xml2cli(f, xe, cbuf_get(cbpre), gt) < 0)
goto done;
}
ok:
retval = 0; retval = 0;
done: done:
if (cbpre) if (cbpre)

View file

@ -58,7 +58,7 @@ new "cli configure"
expectfn "$clixon_cli -1 -f $cfg set interfaces interface eth/0/0" "^$" expectfn "$clixon_cli -1 -f $cfg set interfaces interface eth/0/0" "^$"
new "cli show configuration" new "cli show configuration"
expectfn "$clixon_cli -1 -f $cfg show conf cli" "^interfaces interface name eth/0/0" "interfaces interface enabled true$" expectfn "$clixon_cli -1 -f $cfg show conf cli" "^interfaces interface eth/0/0 enabled true"
new "cli configure using encoded chars data <&" new "cli configure using encoded chars data <&"
expectfn "$clixon_cli -1 -f $cfg set interfaces interface eth/0/0 description \"foo<&bar\"" "" expectfn "$clixon_cli -1 -f $cfg set interfaces interface eth/0/0 description \"foo<&bar\"" ""
@ -101,7 +101,8 @@ new "cli load"
expectfn "$clixon_cli -1 -f $cfg -l o load /tmp/foo" "^$" expectfn "$clixon_cli -1 -f $cfg -l o load /tmp/foo" "^$"
new "cli check load" new "cli check load"
expectfn "$clixon_cli -1 -f $cfg -l o show conf cli" "^interfaces interface name eth/0/0" "interfaces interface enabled true$" expectfn "$clixon_cli -1 -f $cfg -l o show conf cli" "^interfaces interface name eth/0/0 type bgp
interfaces interface eth/0/0 ipv4 enabled true"
new "cli debug" new "cli debug"
expectfn "$clixon_cli -1 -f $cfg -l o debug level 1" "^$" expectfn "$clixon_cli -1 -f $cfg -l o debug level 1" "^$"

View file

@ -144,7 +144,8 @@ new "netconf get replaced config"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><interfaces><interface><name>eth&amp; </name><type>t&lt; &gt; </type><enabled>true</enabled></interface><interface><name>eth1</name><type>eth</type><enabled>true</enabled></interface><interface><name>eth2</name><type>eth</type><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><interfaces><interface><name>eth&amp; </name><type>t&lt; &gt; </type><enabled>true</enabled></interface><interface><name>eth1</name><type>eth</type><enabled>true</enabled></interface><interface><name>eth2</name><type>eth</type><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>$"
new "cli show configuration eth& - encoding tests" new "cli show configuration eth& - encoding tests"
expectfn "$clixon_cli -1 -f $cfg -y $fyang show conf cli" "interfaces interface name eth&" expectfn "$clixon_cli -1 -f $cfg -y $fyang show conf cli" "interfaces interface eth& type t<>
interfaces interface eth& enabled true"
new "netconf discard-changes" new "netconf discard-changes"
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"

View file

@ -82,6 +82,22 @@ module clixon-config {
} }
} }
} }
typedef cli_genmodel_type{
description
"How to generate CLI from YANG model,
eg list a{ key x; leaf x; leaf y;}";
type enumeration{
enum NONE{
description "No extra keywords: a <x> <y>";
}
enum VARS{
description "Keywords on non-key variables: a <x> y <y>";
}
enum ALL{
description "Keywords on all variables: a x <x> y <y>";
}
}
}
typedef nacm_mode{ typedef nacm_mode{
description description
"Mode of RFC8341 Network Configuration Access Control Model. "Mode of RFC8341 Network Configuration Access Control Model.
@ -204,7 +220,7 @@ module clixon-config {
description "Generate code for CLI completion of existing db symbols"; description "Generate code for CLI completion of existing db symbols";
} }
leaf CLICON_CLI_GENMODEL_TYPE { leaf CLICON_CLI_GENMODEL_TYPE {
type string; type cli_genmodel_type;
default "VARS"; default "VARS";
description "How to generate and show CLI syntax: VARS|ALL"; description "How to generate and show CLI syntax: VARS|ALL";
} }