Skip to content

Commit

Permalink
* Fixed: [restconf GET json response does not encode top level node w…
Browse files Browse the repository at this point in the history
…ith namespace as per rfc #303](#303)
  • Loading branch information
olofhagsand committed Feb 17, 2022
1 parent 4631b02 commit bf00fdf
Show file tree
Hide file tree
Showing 12 changed files with 57 additions and 11 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down
4 changes: 4 additions & 0 deletions apps/restconf/restconf_root.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions lib/clixon/clixon_xml_bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_ */
6 changes: 5 additions & 1 deletion lib/src/clixon_json.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -1065,7 +1070,6 @@ xml2json_cbuf(cbuf *cb,
pretty?"\n":"",
pretty?level*JSON_INDENT:0,"",
pretty?"\n":"");

retval = 0;
done:
return retval;
Expand Down
18 changes: 15 additions & 3 deletions lib/src/clixon_proto_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -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){
Expand Down Expand Up @@ -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){
Expand Down Expand Up @@ -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){
Expand Down
19 changes: 19 additions & 0 deletions lib/src/clixon_xml_bind.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
6 changes: 4 additions & 2 deletions lib/src/clixon_yang.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion test/test_nacm_ext.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 2 additions & 2 deletions test/test_nacm_module_read.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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

Expand Down
1 change: 1 addition & 0 deletions test/test_pagination_draft.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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":
{
Expand Down
2 changes: 1 addition & 1 deletion test/test_restconf.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion test/test_submodule.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down

0 comments on commit bf00fdf

Please sign in to comment.