* Added linenumbers to all YANG symbols for better debug and errors

* Improved error messages for YANG identityref:s and leafref:s by adding original line numbers
This commit is contained in:
Olof hagsand 2021-08-03 12:53:37 +02:00 committed by Alan Yaniger
parent efcfb176ae
commit 8675620d22
11 changed files with 105 additions and 17 deletions

View file

@ -50,6 +50,11 @@ Users may have to change how they access the system
* Removed default of `CLICON_RESTCONF_INSTALLDIR`
* The default behaviour is changed to use the config $(sbindir) to locate `clixon_restconf` when starting restconf internally
### Minor features
* Added linenumbers to all YANG symbols for better debug and errors
* Improved error messages for YANG identityref:s and leafref:s by adding original line numbers
### Corrected Bugs
* Fixed: The auto-cli identityref did not expand identities in grouping/usecases properly.

View file

@ -212,6 +212,10 @@ char *yang_when_xpath_get(yang_stmt *ys);
int yang_when_xpath_set(yang_stmt *ys, char *xpath);
cvec *yang_when_nsc_get(yang_stmt *ys);
int yang_when_nsc_set(yang_stmt *ys, cvec *nsc);
const char *yang_filename_get(yang_stmt *ys);
int yang_filename_set(yang_stmt *ys, const char *filename);
int yang_linenum_get(yang_stmt *ys);
int yang_linenum_set(yang_stmt *ys, int linenum);
/* Other functions */
yang_stmt *yspec_new(void);

View file

@ -119,7 +119,14 @@ validate_leafref(cxobj *xt,
if ((leafrefbody = xml_body(xt)) == NULL)
goto ok;
if ((ypath = yang_find(ytype, Y_PATH, NULL)) == NULL){
if (xret && netconf_missing_element_xml(xret, "application", yang_argument_get(ytype), "Leafref requires path statement") < 0)
if ((cberr = cbuf_new()) == NULL){
clicon_err(OE_UNIX, errno, "cbuf_new");
goto done;
}
cprintf(cberr, "Leafref requires path statement");
if (xret && netconf_missing_element_xml(xret, "application",
yang_argument_get(ytype),
cbuf_get(cberr)) < 0)
goto done;
goto fail;
}
@ -142,7 +149,11 @@ validate_leafref(cxobj *xt,
goto done;
}
ymod = ys_module(ys);
cprintf(cberr, "Leafref validation failed: No leaf %s matching path %s in module %s", leafrefbody, path, yang_argument_get(ymod));
cprintf(cberr, "Leafref validation failed: No leaf %s matching path %s in %s.yang:%d",
leafrefbody,
path,
yang_argument_get(ymod),
yang_linenum_get(ys));
if (xret && netconf_bad_element_xml(xret, "application", leafrefbody, cbuf_get(cberr)) < 0)
goto done;
goto fail;
@ -241,8 +252,11 @@ validate_identityref(cxobj *xt,
#endif
}
if (ymod == NULL){
cprintf(cberr, "Identityref validation failed, %s not derived from %s",
node, yang_argument_get(ybaseid));
cprintf(cberr, "Identityref validation failed, %s not derived from %s in %s.yang:%d",
node,
yang_argument_get(ybaseid),
yang_argument_get(ys_module(ybaseid)),
yang_linenum_get(ybaseid));
if (xret && netconf_operation_failed_xml(xret, "application", cbuf_get(cberr)) < 0)
goto done;
goto fail;
@ -254,8 +268,11 @@ validate_identityref(cxobj *xt,
*/
idrefvec = yang_cvec_get(ybaseid);
if (cvec_find(idrefvec, idref) == NULL){
cprintf(cberr, "Identityref validation failed, %s not derived from %s",
node, yang_argument_get(ybaseid));
cprintf(cberr, "Identityref validation failed, %s not derived from %s in %s.yang:%d",
node,
yang_argument_get(ybaseid),
yang_argument_get(ys_module(ybaseid)),
yang_linenum_get(ybaseid));
if (xret && netconf_operation_failed_xml(xret, "application", cbuf_get(cberr)) < 0)
goto done;
goto fail;

View file

@ -416,6 +416,61 @@ yang_when_nsc_set(yang_stmt *ys,
return retval;
}
/*! Get yang filename for error/debug purpose
*
* @param[in] ys Yang statement
* @retval filename
* @note there maye not always be a "filename" in case the yang is read from memory
*/
const char *
yang_filename_get(yang_stmt *ys)
{
return ys->ys_filename;
}
/*! Set yang filename for error/debug purpose
*
* @param[in] ys Yang statement
* @param[in] filename
* @retval 0 OK
* @retval -1 Error
* @note there maye not always be a "filename" in case the yang is read from memory
*/
int
yang_filename_set(yang_stmt *ys,
const char *filename)
{
if ((ys->ys_filename = strdup(filename)) == NULL){
clicon_err(OE_UNIX, errno, "strdup");
return -1;
}
return 0;
}
/*! Get line number of yang filename for error/debug purpose
*
* @param[in] ys Yang statement
* @retval linenum
*/
int
yang_linenum_get(yang_stmt *ys)
{
return ys->ys_linenum;
}
/*! Set line number of yang filename for error/debug purpose
*
* @param[in] ys Yang statement
* @param[in] linenum
*/
int
yang_linenum_set(yang_stmt *ys,
int linenum)
{
ys->ys_linenum = linenum;
return 0;
}
/* End access functions */
/*! Create new yang specification
@ -498,6 +553,8 @@ ys_free1(yang_stmt *ys,
cvec_free(ys->ys_when_nsc);
if (ys->ys_stmt)
free(ys->ys_stmt);
if (ys->ys_filename)
free(ys->ys_filename);
if (self)
free(ys);
return 0;

View file

@ -93,7 +93,8 @@ struct yang_stmt{
char *ys_when_xpath; /* Special conditional for a "when"-associated augment/uses xpath */
cvec *ys_when_nsc; /* Special conditional for a "when"-associated augment/uses namespace ctx */
int _ys_vector_i; /* internal use: yn_each */
char *ys_filename; /* For debug/errors: filename (only (sub)modules) */
int ys_linenum; /* For debug/errors: line number (in ys_filename) */
};

View file

@ -318,6 +318,7 @@ ysp_add(clixon_yang_yacc *yy,
goto err;
if (ys_parse_sub(ys, extra) < 0) /* Check statement-specific syntax */
goto err2; /* dont free since part of tree */
yang_linenum_set(ys, yy->yy_linenum); /* For error/debugging */
// done:
return ys;
err:
@ -662,7 +663,7 @@ yin_element_stmt1 : K_YIN_ELEMENT bool_str stmtend {free($2);}
/* Identity */
identity_stmt : K_IDENTITY identifier_str ';'
{ if (ysp_add(_yy, Y_IDENTITY, $2, NULL) == NULL) _YYERROR("identity_stmt");
{ if (ysp_add(_yy, Y_IDENTITY, $2, NULL) == NULL) _YYERROR("identity_stmt");
_PARSE_DEBUG("identity-stmt -> IDENTITY string ;"); }
| K_IDENTITY identifier_str

View file

@ -773,6 +773,9 @@ yang_parse_str(char *str,
goto done;
}
ymod = yy.yy_module;
/* Add filename for debugging and errors, see also ys_linenum on (each symbol?) */
if (yang_filename_set(ymod, name) < 0)
goto done;
done:
ystack_pop(&yy);
if (yy.yy_stack)

View file

@ -64,7 +64,7 @@ module example-crypto-base {
EOF
cat <<EOF > $dir/example-des.yang
module example-des {
module example-des {
yang-version 1.1;
namespace "urn:example:des";
prefix "des";
@ -81,7 +81,7 @@ cat <<EOF > $dir/example-des.yang
base "crypto:symmetric-key";
description "Triple DES crypto algorithm.";
}
}
}
EOF
cat <<EOF > $fyang
@ -252,7 +252,7 @@ new "Set crypto to foo:bar"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><crypto xmlns=\"urn:example:my-crypto\">foo:bar</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
new "netconf validate (expect fail)"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>operation-failed</error-tag><error-severity>error</error-severity><error-message>Identityref validation failed, foo:bar not derived from crypto-alg</error-message></rpc-error></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>operation-failed</error-tag><error-severity>error</error-severity><error-message>Identityref validation failed, foo:bar not derived from crypto-alg in example-crypto-base.yang:[0-9]*</error-message></rpc-error></rpc-reply>]]>]]>$"
new "cli set crypto to mc:aes"
expectpart "$($clixon_cli -1 -f $cfg -l o set crypto mc:aes)" 0 "^$"
@ -282,7 +282,7 @@ new "Netconf set undefined acl-type"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><acls xmlns=\"urn:example:my-crypto\"><acl><name>x</name><type>undefined</type></acl></acls></config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
new "netconf validate fail"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>operation-failed</error-tag><error-severity>error</error-severity><error-message>Identityref validation failed, undefined not derived from acl-base</error-message></rpc-error></rpc-reply>]]>]]>"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>operation-failed</error-tag><error-severity>error</error-severity><error-message>Identityref validation failed, undefined not derived from acl-base in example-my-crypto.yang:[0-9]*</error-message></rpc-error></rpc-reply>]]>]]>"
new "netconf discard-changes"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><discard-changes/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"

View file

@ -140,7 +140,7 @@ new "leafref add non-existing ref"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><default-address xmlns=\"urn:example:clixon\"><absname>eth3</absname><address>10.0.4.6</address></default-address></config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
new "leafref validate"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>eth3</bad-element></error-info><error-severity>error</error-severity><error-message>Leafref validation failed: No leaf eth3 matching path /if:interfaces/if:interface/if:name in module example</error-message></rpc-error></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>eth3</bad-element></error-info><error-severity>error</error-severity><error-message>Leafref validation failed: No leaf eth3 matching path /if:interfaces/if:interface/if:name in example.yang:[0-9]*</error-message></rpc-error></rpc-reply>]]>]]>$"
#new "leafref wrong ref"
#expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><default-address xmlns=\"urn:example:clixon\"><wrong>eth3</wrong><address>10.0.4.6</address></default-address></config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
@ -170,7 +170,7 @@ new "leafref delete leaf"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><interfaces xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\" xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><interface nc:operation=\"delete\"><name>eth0</name></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
new "leafref validate (should fail)"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>eth0</bad-element></error-info><error-severity>error</error-severity><error-message>Leafref validation failed: No leaf eth0 matching path /if:interfaces/if:interface/if:name in module example</error-message></rpc-error></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>eth0</bad-element></error-info><error-severity>error</error-severity><error-message>Leafref validation failed: No leaf eth0 matching path /if:interfaces/if:interface/if:name in example.yang:[0-9]*</error-message></rpc-error></rpc-reply>]]>]]>$"
new "leafref discard-changes"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><discard-changes/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"

View file

@ -209,7 +209,7 @@ new "leafref augment+leafref config wrong ref"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config>$XML</config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
new "leafref augment+leafref validate wrong ref"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>xxx</bad-element></error-info><error-severity>error</error-severity><error-message>Leafref validation failed: No leaf xxx matching path /ex:sender/ex:name in module augment</error-message></rpc-error></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>xxx</bad-element></error-info><error-severity>error</error-severity><error-message>Leafref validation failed: No leaf xxx matching path /ex:sender/ex:name in augment.yang:[0-9]*</error-message></rpc-error></rpc-reply>]]>]]>$"
new "netconf discard-changes"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><discard-changes/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"

View file

@ -168,10 +168,10 @@ expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><commit/></
# Leafref wrong
new "netconf get / config+state should fail"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get content=\"all\"><filter type=\"xpath\" select=\"/\"/></get></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>operation-failed</error-tag><error-info><bad-element>x</bad-element></error-info><error-severity>error</error-severity><error-message>Leafref validation failed: No leaf x matching path /ex:sender-config/ex:name in module leafref. Internal error, state callback returned invalid XML</error-message></rpc-error></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get content=\"all\"><filter type=\"xpath\" select=\"/\"/></get></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>operation-failed</error-tag><error-info><bad-element>x</bad-element></error-info><error-severity>error</error-severity><error-message>Leafref validation failed: No leaf x matching path /ex:sender-config/ex:name in leafref.yang:[0-9]*. Internal error, state callback returned invalid XML</error-message></rpc-error></rpc-reply>]]>]]>$"
new "netconf get / state-only should fail"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get content=\"nonconfig\"><filter type=\"xpath\" select=\"/\"/></get></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>operation-failed</error-tag><error-info><bad-element>x</bad-element></error-info><error-severity>error</error-severity><error-message>Leafref validation failed: No leaf x matching path /ex:sender-config/ex:name in module leafref. Internal error, state callback returned invalid XML</error-message></rpc-error></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get content=\"nonconfig\"><filter type=\"xpath\" select=\"/\"/></get></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><rpc-error><error-type>application</error-type><error-tag>operation-failed</error-tag><error-info><bad-element>x</bad-element></error-info><error-severity>error</error-severity><error-message>Leafref validation failed: No leaf x matching path /ex:sender-config/ex:name in leafref.yang:[0-9]*. Internal error, state callback returned invalid XML</error-message></rpc-error></rpc-reply>]]>]]>$"
new "netconf get / config-only ok"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get content=\"config\"><filter type=\"xpath\" select=\"/\"/></get></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><data><sender-config xmlns=\"urn:example:example\"><name>y</name></sender-config></data></rpc-reply>]]>]]>$"