* Fixed: [restconf GET json response does not encode top level node with namespace as per rfc #303](https://github.com/clicon/clixon/issues/303)
This commit is contained in:
parent
4631b02e00
commit
bf00fdf2c1
12 changed files with 57 additions and 11 deletions
|
|
@ -46,6 +46,8 @@ Expected: March 2022
|
|||
|
||||
Users may have to change how they access the system
|
||||
|
||||
* RESTCONF replies on the form: `{"data":...}` changed to: `{"ietf-restconf:data":...}`
|
||||
* See [restconf GET json response does not encode top level node with namespace as per rfc #303](https://github.com/clicon/clixon/issues/303)
|
||||
* YANG leafref `require-instance` default changed to `true`
|
||||
* This makes leafref validation stricter
|
||||
* See [statement: require-instance should be true if not present according to rfc7950 Sec 9.9.3](https://github.com/clicon/clixon/issues/302)
|
||||
|
|
@ -62,6 +64,7 @@ Users may have to change how they access the system
|
|||
|
||||
### Corrected Bugs
|
||||
|
||||
* Fixed: [restconf GET json response does not encode top level node with namespace as per rfc #303](https://github.com/clicon/clixon/issues/303)
|
||||
* Fixed: [statement: require-instance should be true if not present according to rfc7950 Sec 9.9.3](https://github.com/clicon/clixon/issues/302)
|
||||
* See also API changes
|
||||
* Fixed: input RPC validation of choice (non-case)
|
||||
|
|
|
|||
|
|
@ -238,6 +238,7 @@ api_yang_library_version(clicon_handle h,
|
|||
int retval = -1;
|
||||
cxobj *xt = NULL;
|
||||
cbuf *cb = NULL;
|
||||
yang_stmt *yspec;
|
||||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
if (restconf_reply_header(req, "Content-Type", "%s", restconf_media_int2str(media_out)) < 0)
|
||||
|
|
@ -250,6 +251,9 @@ api_yang_library_version(clicon_handle h,
|
|||
goto done;
|
||||
if (xml_rootchild(xt, 0, &xt) < 0)
|
||||
goto done;
|
||||
yspec = clicon_dbspec_yang(h);
|
||||
if (xml_bind_special(xt, yspec, "/rc:restconf/yang-library-version") < 0)
|
||||
goto done;
|
||||
if ((cb = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -49,5 +49,6 @@ int xml_bind_yang_rpc(cxobj *xrpc, yang_stmt *yspec, cxobj **xerr);
|
|||
int xml_bind_yang_rpc_reply(cxobj *xrpc, char *name, yang_stmt *yspec, cxobj **xerr);
|
||||
int xml_bind_yang0(cxobj *xt, yang_bind yb, yang_stmt *yspec, cxobj **xerr);
|
||||
int xml_bind_yang(cxobj *xt, yang_bind yb, yang_stmt *yspec, cxobj **xerr);
|
||||
int xml_bind_special(cxobj *xd, yang_stmt *yspec, char *schema_nodeid);
|
||||
|
||||
#endif /* _CLIXON_XML_BIND_H_ */
|
||||
|
|
|
|||
|
|
@ -784,6 +784,11 @@ xml2json1_cbuf(cbuf *cb,
|
|||
if (ys_real_module(ys, &ymod) < 0)
|
||||
goto done;
|
||||
modname = yang_argument_get(ymod);
|
||||
/* Special case for ietf-netconf -> ietf-restconf translation
|
||||
* A special case is for return data on the form {"data":...}
|
||||
*/
|
||||
if (strcmp(modname, "ietf-netconf")==0)
|
||||
modname = "ietf-restconf";
|
||||
if (modname0 && strcmp(modname, modname0) == 0)
|
||||
modname=NULL;
|
||||
else
|
||||
|
|
@ -1065,7 +1070,6 @@ xml2json_cbuf(cbuf *cb,
|
|||
pretty?"\n":"",
|
||||
pretty?level*JSON_INDENT:0,"",
|
||||
pretty?"\n":"");
|
||||
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
|
|
|
|||
|
|
@ -466,15 +466,19 @@ clicon_rpc_get_config(clicon_handle h,
|
|||
goto done;
|
||||
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
||||
goto done;
|
||||
yspec = clicon_dbspec_yang(h);
|
||||
/* Send xml error back: first check error, then ok */
|
||||
if ((xd = xpath_first(xret, NULL, "/rpc-reply/rpc-error")) != NULL)
|
||||
xd = xml_parent(xd); /* point to rpc-reply */
|
||||
else if ((xd = xpath_first(xret, NULL, "/rpc-reply/data")) == NULL){
|
||||
if ((xd = xml_new(NETCONF_OUTPUT_DATA, NULL, CX_ELMNT)) == NULL)
|
||||
goto done;
|
||||
if (xml_bind_special(xd, yspec, "/nc:get-config/output/data") < 0)
|
||||
goto done;
|
||||
}
|
||||
else{
|
||||
yspec = clicon_dbspec_yang(h);
|
||||
if (xml_bind_special(xd, yspec, "/nc:get-config/output/data") < 0)
|
||||
goto done;
|
||||
if ((ret = xml_bind_yang(xd, YB_MODULE, yspec, &xerr)) < 0)
|
||||
goto done;
|
||||
if (ret == 0){
|
||||
|
|
@ -838,15 +842,19 @@ clicon_rpc_get(clicon_handle h,
|
|||
goto done;
|
||||
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
||||
goto done;
|
||||
yspec = clicon_dbspec_yang(h);
|
||||
/* Send xml error back: first check error, then ok */
|
||||
if ((xd = xpath_first(xret, NULL, "/rpc-reply/rpc-error")) != NULL)
|
||||
xd = xml_parent(xd); /* point to rpc-reply */
|
||||
else if ((xd = xpath_first(xret, NULL, "/rpc-reply/data")) == NULL){
|
||||
if ((xd = xml_new(NETCONF_OUTPUT_DATA, NULL, CX_ELMNT)) == NULL)
|
||||
goto done;
|
||||
if (xml_bind_special(xd, yspec, "/nc:get/output/data") < 0)
|
||||
goto done;
|
||||
}
|
||||
else{
|
||||
yspec = clicon_dbspec_yang(h);
|
||||
if (xml_bind_special(xd, yspec, "/nc:get/output/data") < 0)
|
||||
goto done;
|
||||
if ((ret = xml_bind_yang(xd, YB_MODULE, yspec, &xerr)) < 0)
|
||||
goto done;
|
||||
if (ret == 0){
|
||||
|
|
@ -974,15 +982,19 @@ clicon_rpc_get_pageable_list(clicon_handle h,
|
|||
goto done;
|
||||
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
||||
goto done;
|
||||
yspec = clicon_dbspec_yang(h);
|
||||
/* Send xml error back: first check error, then ok */
|
||||
if ((xd = xpath_first(xret, NULL, "/rpc-reply/rpc-error")) != NULL)
|
||||
xd = xml_parent(xd); /* point to rpc-reply */
|
||||
else if ((xd = xpath_first(xret, NULL, "/rpc-reply/data")) == NULL){
|
||||
if ((xd = xml_new(NETCONF_OUTPUT_DATA, NULL, CX_ELMNT)) == NULL)
|
||||
goto done;
|
||||
if (xml_bind_special(xd, yspec, "/nc:get/output/data") < 0)
|
||||
goto done;
|
||||
}
|
||||
else{
|
||||
yspec = clicon_dbspec_yang(h);
|
||||
if (xml_bind_special(xd, yspec, "/nc:get/output/data") < 0)
|
||||
goto done;
|
||||
if ((ret = xml_bind_yang(xd, YB_MODULE, yspec, &xerr)) < 0)
|
||||
goto done;
|
||||
if (ret == 0){
|
||||
|
|
|
|||
|
|
@ -752,3 +752,22 @@ xml_bind_yang_rpc_reply(cxobj *xrpc,
|
|||
retval = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*! Special case explicit binding
|
||||
*/
|
||||
int
|
||||
xml_bind_special(cxobj *xd,
|
||||
yang_stmt *yspec,
|
||||
char *schema_nodeid)
|
||||
{
|
||||
int retval = -1;
|
||||
yang_stmt *yd;
|
||||
|
||||
if (yang_abs_schema_nodeid(yspec, schema_nodeid, &yd) < 0)
|
||||
goto done;
|
||||
if (yd)
|
||||
xml_spec_set(xd, yd);
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1170,7 +1170,9 @@ yang_find_schemanode(yang_stmt *yn,
|
|||
} /* Y_CHOICE */
|
||||
else
|
||||
if (yang_schemanode(ys)){
|
||||
if (yang_keyword_get(ys) == Y_INPUT || yang_keyword_get(ys) == Y_OUTPUT)
|
||||
if (strcmp(argument, "input") == 0 && yang_keyword_get(ys) == Y_INPUT)
|
||||
ysmatch = ys;
|
||||
else if (strcmp(argument, "output") == 0 && yang_keyword_get(ys) == Y_OUTPUT)
|
||||
ysmatch = ys;
|
||||
else if (argument == NULL)
|
||||
ysmatch = ys;
|
||||
|
|
@ -3122,7 +3124,7 @@ schema_nodeid_iterate(yang_stmt *yn,
|
|||
goto ok;
|
||||
}
|
||||
yp = ys; /* ys is matched */
|
||||
|
||||
ys = NULL;
|
||||
} /* while cv */
|
||||
assert(yp && yang_schemanode((yang_stmt*)yp));
|
||||
*yres = (yang_stmt*)yp;
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ new "wait restconf"
|
|||
wait_restconf
|
||||
|
||||
new "auth get"
|
||||
expectpart "$(curl -u andy:bar $CURLOPTS -X GET $RCPROTO://localhost/restconf/data)" 0 "HTTP/$HVER 200" '{"data":{"clixon-example:state":{"op":\["41","42","43"\]}'
|
||||
expectpart "$(curl -u andy:bar $CURLOPTS -X GET $RCPROTO://localhost/restconf/data)" 0 "HTTP/$HVER 200" '{"ietf-restconf:data":{"clixon-example:state":{"op":\["41","42","43"\]}'
|
||||
|
||||
new "Set x to 0"
|
||||
expectpart "$(curl -u andy:bar $CURLOPTS -X PUT -H "Content-Type: application/yang-data+json" -d '{"nacm-example:x": 0}' $RCPROTO://localhost/restconf/data/nacm-example:x)" 0 "HTTP/$HVER 201"
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ expectpart "$(curl -u andy:bar $CURLOPTS -X GET $RCPROTO://localhost/restconf/da
|
|||
|
||||
new "admin read top ok (all)"
|
||||
ret=$(curl -u andy:bar $CURLOPTS -X GET $RCPROTO://localhost/restconf/data)
|
||||
expect='{"data":{"clixon-example:table":'
|
||||
expect='{"ietf-restconf:data":{"clixon-example:table":'
|
||||
match=`echo $ret | grep --null -Eo "$expect"`
|
||||
if [ -z "$match" ]; then
|
||||
err "$expect" "$ret"
|
||||
|
|
@ -253,7 +253,7 @@ new "limit read state OK"
|
|||
expectpart "$(curl -u wilma:bar $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/clixon-example:state)" 0 "HTTP/$HVER 200" '{"clixon-example:state":{"op":\["41","42","43"\]}}'
|
||||
|
||||
new "limit read top ok (part)"
|
||||
expectpart "$(curl -u wilma:bar $CURLOPTS -X GET $RCPROTO://localhost/restconf/data)" 0 "HTTP/$HVER 200" '{"data":{"clixon-example:table":{"parameter":\[{"name":"key42","value":"val42"},{"name":"key43","value":"val43"}\]},"clixon-example:state":{"op":\["41","42","43"\]}}}'
|
||||
expectpart "$(curl -u wilma:bar $CURLOPTS -X GET $RCPROTO://localhost/restconf/data)" 0 "HTTP/$HVER 200" '{"ietf-restconf:data":{"clixon-example:table":{"parameter":\[{"name":"key42","value":"val42"},{"name":"key43","value":"val43"}\]},"clixon-example:state":{"op":\["41","42","43"\]}}}'
|
||||
|
||||
#user:guest
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ cat <<EOF > $cfg
|
|||
EOF
|
||||
|
||||
# See draft-wwlh-netconf-list-pagination-00 A.2 (except stats and audit-log)
|
||||
# XXX: "config" without
|
||||
cat <<'EOF' > $dir/startup_db
|
||||
{"config":
|
||||
{
|
||||
|
|
|
|||
|
|
@ -327,7 +327,7 @@ function testrun()
|
|||
fi
|
||||
|
||||
new "restconf get restconf/yang-library-version. RFC8040 3.3.3"
|
||||
expectpart "$(curl $CURLOPTS -X GET $proto://$addr/restconf/yang-library-version)" 0 "HTTP/$HVER 200" '{"yang-library-version":"2019-01-04"}'
|
||||
expectpart "$(curl $CURLOPTS -X GET $proto://$addr/restconf/yang-library-version)" 0 "HTTP/$HVER 200" '{"ietf-restconf:yang-library-version":"2019-01-04"}'
|
||||
|
||||
new "restconf get restconf/yang-library-version. RFC8040 3.3.3 (xml)"
|
||||
ret=$(curl $CURLOPTS -X GET -H "Accept: application/yang-data+xml" $proto://$addr/restconf/yang-library-version)
|
||||
|
|
|
|||
|
|
@ -247,7 +247,7 @@ new "restconf edit sub2"
|
|||
expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data -d '{"main:sub2":{"x":"foo","ext2":"foo"}}')" 0 "HTTP/$HVER 201"
|
||||
|
||||
new "restconf check main/sub1/sub2 contents"
|
||||
expectpart "$(curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data?content=config)" 0 "HTTP/$HVER 200" '{"data":{"main:main":{"ext":"foo","x":"foo"},"main:sub1":{"ext1":"foo","x":"foo"},"main:sub2":{"ext2":"foo","x":"foo"}'
|
||||
expectpart "$(curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data?content=config)" 0 "HTTP/$HVER 200" '{"ietf-restconf:data":{"main:main":{"ext":"foo","x":"foo"},"main:sub1":{"ext1":"foo","x":"foo"},"main:sub2":{"ext2":"foo","x":"foo"}'
|
||||
|
||||
new "restconf edit augment 0"
|
||||
expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/main:sub2 -d '{"main:aug0":"foo"}')" 0 "HTTP/$HVER 201"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue