example client-rpc similar to other example rpc:s

This commit is contained in:
Olof hagsand 2019-01-22 18:37:21 +01:00
parent 0e09996073
commit 7113026e17
6 changed files with 55 additions and 15 deletions

View file

@ -1676,7 +1676,7 @@ api_operations_post(clicon_handle h,
if (xml_parse_string(cbuf_get(cbret), NULL, &xret) < 0) if (xml_parse_string(cbuf_get(cbret), NULL, &xret) < 0)
goto done; goto done;
/* Local error: return it and quit */ /* Local error: return it and quit */
if ((xe = xpath_first(xret, "//rpc-error")) != NULL){ if ((xe = xpath_first(xret, "rpc-reply/rpc-error")) != NULL){
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml) < 0)
goto done; goto done;
goto ok; goto ok;
@ -1685,7 +1685,7 @@ api_operations_post(clicon_handle h,
else { /* Send to backend */ else { /* Send to backend */
if (clicon_rpc_netconf_xml(h, xtop, &xret, NULL) < 0) if (clicon_rpc_netconf_xml(h, xtop, &xret, NULL) < 0)
goto done; goto done;
if ((xe = xpath_first(xret, "rpc-error")) != NULL){ if ((xe = xpath_first(xret, "rpc-reply/rpc-error")) != NULL){
if (api_return_err(h, r, xe, pretty, use_xml) < 0) if (api_return_err(h, r, xe, pretty, use_xml) < 0)
goto done; goto done;
goto ok; goto ok;

View file

@ -65,12 +65,12 @@ module clixon-example {
This is a clixon implementation detail: some rpc:s This is a clixon implementation detail: some rpc:s
are better processed by the client for API or perf reasons"; are better processed by the client for API or perf reasons";
input { input {
leaf request { leaf x {
type string; type string;
} }
} }
output { output {
leaf result{ leaf x {
type string; type string;
} }
} }

View file

@ -65,13 +65,34 @@ plugin_exit(clicon_handle h)
/*! Local example netconf rpc callback /*! Local example netconf rpc callback
*/ */
int netconf_client_rpc(clicon_handle h, int netconf_client_rpc(clicon_handle h,
cxobj *xn, cxobj *xe,
cbuf *cbret, cbuf *cbret,
void *arg, void *arg,
void *regarg) void *regarg)
{ {
clicon_debug(1, "%s restconf", __FUNCTION__); int retval = -1;
cprintf(cbret, "<rpc-reply><result xmlns=\"urn:example:clixon\">ok</result></rpc-reply>"); cxobj *x = NULL;
char *namespace;
/* get namespace from rpc name, return back in each output parameter */
if ((namespace = xml_find_type_value(xe, NULL, "xmlns", CX_ATTR)) == NULL){
clicon_err(OE_XML, ENOENT, "No namespace given in rpc %s", xml_name(xe));
goto done;
}
cprintf(cbret, "<rpc-reply>");
if (!xml_child_nr_type(xe, CX_ELMNT))
cprintf(cbret, "<ok/>");
else while ((x = xml_child_each(xe, x, CX_ELMNT)) != NULL) {
if (xmlns_set(x, NULL, namespace) < 0)
goto done;
if (clicon_xml2cbuf(cbret, x, 0, 0) < 0)
goto done;
}
cprintf(cbret, "</rpc-reply>");
retval = 0;
done:
return retval;
return 0; return 0;
} }

View file

@ -268,15 +268,33 @@ example_restconf_credentials(clicon_handle h,
*/ */
int int
restconf_client_rpc(clicon_handle h, restconf_client_rpc(clicon_handle h,
cxobj *xn, cxobj *xe,
cbuf *cbret, cbuf *cbret,
void *arg, void *arg,
void *regarg) void *regarg)
{ {
// FCGX_Request *r = (FCGX_Request *)arg; int retval = -1;
clicon_debug(1, "%s", __FUNCTION__); cxobj *x = NULL;
cprintf(cbret, "<rpc-reply><result xmlns=\"urn:example:clixon\">ok</result></rpc-reply>"); char *namespace;
return 0;
/* get namespace from rpc name, return back in each output parameter */
if ((namespace = xml_find_type_value(xe, NULL, "xmlns", CX_ATTR)) == NULL){
clicon_err(OE_XML, ENOENT, "No namespace given in rpc %s", xml_name(xe));
goto done;
}
cprintf(cbret, "<rpc-reply>");
if (!xml_child_nr_type(xe, CX_ELMNT))
cprintf(cbret, "<ok/>");
else while ((x = xml_child_each(xe, x, CX_ELMNT)) != NULL) {
if (xmlns_set(x, NULL, namespace) < 0)
goto done;
if (clicon_xml2cbuf(cbret, x, 0, 0) < 0)
goto done;
}
cprintf(cbret, "</rpc-reply>");
retval = 0;
done:
return retval;
} }
/*! Start example restonf plugin. Set authentication method /*! Start example restonf plugin. Set authentication method

View file

@ -192,7 +192,7 @@ new "netconf empty rpc"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><empty xmlns="urn:example:clixon"/></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><empty xmlns="urn:example:clixon"/></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "netconf client-side rpc" new "netconf client-side rpc"
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><client-rpc xmlns="urn:example:clixon"><request>example</request></client-rpc></rpc>]]>]]>' '^<rpc-reply><result xmlns="urn:example:clixon">ok</result></rpc-reply>]]>]]>$' expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><client-rpc xmlns="urn:example:clixon"><x>val42</x></client-rpc></rpc>]]>]]>' '^<rpc-reply><x xmlns="urn:example:clixon">val42</x></rpc-reply>]]>]]>$'
if [ $BE -eq 0 ]; then if [ $BE -eq 0 ]; then
exit # BE exit # BE

View file

@ -228,6 +228,7 @@ new2 "restconf rpc using POST json"
expecteq "$(curl -s -X POST -d '{"clixon-example:input":{"x":42}}' http://localhost/restconf/operations/clixon-example:example)" '{"clixon-example:output": {"x": "42","y": "42"}} expecteq "$(curl -s -X POST -d '{"clixon-example:input":{"x":42}}' http://localhost/restconf/operations/clixon-example:example)" '{"clixon-example:output": {"x": "42","y": "42"}}
' '
new2 "restconf rpc using POST json wrong"
expecteq "$(curl -s -X POST -d '{"clixon-example:input":{"wrongelement":"ipv4"}}' http://localhost/restconf/operations/clixon-example:example)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "unknown-element","error-info": {"bad-element": "wrongelement"},"error-severity": "error"}}} ' expecteq "$(curl -s -X POST -d '{"clixon-example:input":{"wrongelement":"ipv4"}}' http://localhost/restconf/operations/clixon-example:example)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "unknown-element","error-info": {"bad-element": "wrongelement"},"error-severity": "error"}}} '
new2 "restconf rpc non-existing rpc without namespace" new2 "restconf rpc non-existing rpc without namespace"
@ -254,8 +255,8 @@ new2 "restconf rpc using wrong prefix"
expecteq "$(curl -s -X POST -d '{"wrong:input":{"routing-instance-name":"ipv4"}}' http://localhost/restconf/operations/wrong:example)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "operation-failed","error-severity": "error","error-message": "yang module not found"}}} ' expecteq "$(curl -s -X POST -d '{"wrong:input":{"routing-instance-name":"ipv4"}}' http://localhost/restconf/operations/wrong:example)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "operation-failed","error-severity": "error","error-message": "yang module not found"}}} '
new "restconf local client rpc using POST xml" new "restconf local client rpc using POST xml"
ret=$(curl -s -i -X POST -H "Accept: application/yang-data+xml" -d '{"clixon-example:input":{"request":"example"}}' http://localhost/restconf/operations/clixon-example:client-rpc) ret=$(curl -s -i -X POST -H "Accept: application/yang-data+xml" -d '{"clixon-example:input":{"x":"example"}}' http://localhost/restconf/operations/clixon-example:client-rpc)
expect='<output xmlns="urn:example:clixon"><result>ok</result></output>' expect='<output xmlns="urn:example:clixon"><x>example</x></output>'
match=`echo $ret | grep -EZo "$expect"` match=`echo $ret | grep -EZo "$expect"`
if [ -z "$match" ]; then if [ -z "$match" ]; then
err "$expect" "$ret" err "$expect" "$ret"