Replacing remaining badrequest() with proper restconf error msg.

This commit is contained in:
Olof hagsand 2018-04-22 20:13:54 +02:00
parent 3ed1c98556
commit 1913407e52
14 changed files with 153 additions and 75 deletions

View file

@ -424,19 +424,28 @@ api_data_post(clicon_handle h,
/* Parse input data as json or xml into xml */ /* Parse input data as json or xml into xml */
if (parse_xml){ if (parse_xml){
if (xml_parse_string(data, NULL, &xdata) < 0){ if (xml_parse_string(data, NULL, &xdata) < 0){
badrequest(r); if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0)
goto done;
if (api_return_err(h, r, xerr, pretty, use_xml) < 0)
goto done;
goto ok; goto ok;
} }
} }
else if (json_parse_str(data, &xdata) < 0){ else if (json_parse_str(data, &xdata) < 0){
badrequest(r); if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0)
goto done;
if (api_return_err(h, r, xerr, pretty, use_xml) < 0)
goto done;
goto ok; goto ok;
} }
/* 4.4.1: The message-body MUST contain exactly one instance of the /* 4.4.1: The message-body MUST contain exactly one instance of the
* expected data resource. * expected data resource.
*/ */
if (xml_child_nr(xdata) != 1){ if (xml_child_nr(xdata) != 1){
badrequest(r); if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0)
goto done;
if (api_return_err(h, r, xerr, pretty, use_xml) < 0)
goto done;
goto ok; goto ok;
} }
x = xml_child_i(xdata,0); x = xml_child_i(xdata,0);
@ -628,19 +637,28 @@ api_data_put(clicon_handle h,
/* Parse input data as json or xml into xml */ /* Parse input data as json or xml into xml */
if (parse_xml){ if (parse_xml){
if (xml_parse_string(data, NULL, &xdata) < 0){ if (xml_parse_string(data, NULL, &xdata) < 0){
badrequest(r); if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0)
goto done;
if (api_return_err(h, r, xerr, pretty, use_xml) < 0)
goto done;
goto ok; goto ok;
} }
} }
else if (json_parse_str(data, &xdata) < 0){ else if (json_parse_str(data, &xdata) < 0){
badrequest(r); if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0)
goto done;
if (api_return_err(h, r, xerr, pretty, use_xml) < 0)
goto done;
goto ok; goto ok;
} }
/* The message-body MUST contain exactly one instance of the /* The message-body MUST contain exactly one instance of the
* expected data resource. * expected data resource.
*/ */
if (xml_child_nr(xdata) != 1){ if (xml_child_nr(xdata) != 1){
badrequest(r); if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0)
goto done;
if (api_return_err(h, r, xerr, pretty, use_xml) < 0)
goto done;
goto ok; goto ok;
} }
x = xml_child_i(xdata,0); x = xml_child_i(xdata,0);
@ -662,13 +680,19 @@ api_data_put(clicon_handle h,
else { else {
/* Check same symbol in api-path as data */ /* Check same symbol in api-path as data */
if (strcmp(xml_name(x), xml_name(xbot))){ if (strcmp(xml_name(x), xml_name(xbot))){
badrequest(r); if (netconf_operation_failed_xml(&xerr, "protocol", "Not same symbol in api-path as data") < 0)
goto done;
if (api_return_err(h, r, xerr, pretty, use_xml) < 0)
goto done;
goto ok; goto ok;
} }
/* If list or leaf-list, api-path keys must match data keys */ /* If list or leaf-list, api-path keys must match data keys */
if (y && (y->yn_keyword == Y_LIST ||y->yn_keyword == Y_LEAF_LIST)){ if (y && (y->yn_keyword == Y_LIST ||y->yn_keyword == Y_LEAF_LIST)){
if (match_list_keys((yang_stmt*)y, x, xbot) < 0){ if (match_list_keys((yang_stmt*)y, x, xbot) < 0){
badrequest(r); if (netconf_operation_failed_xml(&xerr, "protocol", "api-path keys do not match data keys") < 0)
goto done;
if (api_return_err(h, r, xerr, pretty, use_xml) < 0)
goto done;
goto ok; goto ok;
} }
} }
@ -1055,12 +1079,18 @@ api_operations_post(clicon_handle h,
/* Parse input data as json or xml into xml */ /* Parse input data as json or xml into xml */
if (parse_xml){ if (parse_xml){
if (xml_parse_string(data, NULL, &xdata) < 0){ if (xml_parse_string(data, NULL, &xdata) < 0){
badrequest(r); if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0)
goto done;
if (api_return_err(h, r, xerr, pretty, use_xml) < 0)
goto done;
goto ok; goto ok;
} }
} }
else if (json_parse_str(data, &xdata) < 0){ else if (json_parse_str(data, &xdata) < 0){
badrequest(r); if (netconf_malformed_message_xml(&xerr, clicon_err_reason) < 0)
goto done;
if (api_return_err(h, r, xerr, pretty, use_xml) < 0)
goto done;
goto ok; goto ok;
} }
yinput = yang_find((yang_node*)yrpc, Y_INPUT, NULL); yinput = yang_find((yang_node*)yrpc, Y_INPUT, NULL);

View file

@ -743,7 +743,7 @@ WARN_LOGFILE =
# spaces. # spaces.
# Note: If this tag is empty the current directory is searched. # Note: If this tag is empty the current directory is searched.
INPUT = ../lib/src/ ../lib/clicon/ ../apps/cli/ ../apps/config/ ../apps/netconf ../apps/dbctrl ../datastore INPUT = ../lib/src/ ../lib/clicon/ ../apps/cli/ ../apps/config/ ../apps/netconf ../apps/dbctrl ../datastore ../datastore/text
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses

View file

@ -743,7 +743,7 @@ WARN_LOGFILE =
# spaces. # spaces.
# Note: If this tag is empty the current directory is searched. # Note: If this tag is empty the current directory is searched.
INPUT = ../lib/src/ ../lib/clicon/ ../apps/cli/ ../apps/backend/ ../apps/restconf/ ../apps/netconf ../apps/dbctrl ../datastore INPUT = ../lib/src/ ../lib/clicon/ ../apps/cli/ ../apps/backend/ ../apps/restconf/ ../apps/netconf ../apps/dbctrl ../datastore ../datastore/text
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses

View file

@ -93,27 +93,22 @@ Routing notification
The example includes a restonf, netconf, CLI and two backend plugins. The example includes a restonf, netconf, CLI and two backend plugins.
Each plugin is initiated with an API struct followed by a plugin init function. Each plugin is initiated with an API struct followed by a plugin init function.
The content of the API struct is different depending on what kind of plugin it is. Some fields are The content of the API struct is different depending on what kind of plugin it is.
meaningful only for some plugins. The plugin init function may also include registering RPC functions, see below is for a backend.
The plugin init function may also include registering RPC functions.
``` ```
static clixon_plugin_api api = { static clixon_plugin_api api = {
"example", /* name */ "example", /* name */
clixon_plugin_init, clixon_plugin_init,
plugin_start, plugin_start,
plugin_exit, plugin_exit,
NULL, /* cli prompt N/A for backend */ .ca_reset=plugin_reset,/* reset */
NULL, /* cli suspend N/A for backend */ .ca_statedata=plugin_statedata, /* statedata */
NULL, /* cli interrupt N/A for backend */ .ca_trans_begin=NULL, /* trans begin */
NULL, /* auth N/A for backend */ .ca_trans_validate=transaction_validate,/* trans validate */
plugin_reset, .ca_trans_complete=NULL, /* trans complete */
plugin_statedata, .ca_trans_commit=transaction_commit, /* trans commit */
transaction_begin, .ca_trans_end=NULL, /* trans end */
transaction_validate, .ca_trans_abort=NULL /* trans abort */
transaction_complete,
transaction_commit,
transaction_end,
transaction_abort
}; };
clixon_plugin_api * clixon_plugin_api *

View file

@ -260,11 +260,11 @@ plugin_start(clicon_handle h,
clixon_plugin_api *clixon_plugin_init(clicon_handle h); clixon_plugin_api *clixon_plugin_init(clicon_handle h);
static clixon_plugin_api api = { static clixon_plugin_api api = {
"example", /* name */ /*--- Common fields. ---*/ "example", /* name */
clixon_plugin_init, /* init */ clixon_plugin_init, /* init */
plugin_start, /* start */ plugin_start, /* start */
NULL, /* exit */ NULL, /* exit */
.ca_reset=plugin_reset,/* reset */ /*--- Backend plugin only ---*/ .ca_reset=plugin_reset, /* reset */
.ca_statedata=plugin_statedata, /* statedata */ .ca_statedata=plugin_statedata, /* statedata */
.ca_trans_begin=NULL, /* trans begin */ .ca_trans_begin=NULL, /* trans begin */
.ca_trans_validate=transaction_validate,/* trans validate */ .ca_trans_validate=transaction_validate,/* trans validate */

View file

@ -61,5 +61,6 @@ int netconf_operation_not_supported(cbuf *cb, char *type, char *message);
int netconf_operation_failed(cbuf *cb, char *type, char *message); int netconf_operation_failed(cbuf *cb, char *type, char *message);
int netconf_operation_failed_xml(cxobj **xret, char *type, char *message); int netconf_operation_failed_xml(cxobj **xret, char *type, char *message);
int netconf_malformed_message(cbuf *cb, char *message); int netconf_malformed_message(cbuf *cb, char *message);
int netconf_malformed_message_xml(cxobj **xret, char *message);
#endif /* _CLIXON_NETCONF_LIB_H */ #endif /* _CLIXON_NETCONF_LIB_H */

View file

@ -49,10 +49,16 @@
*/ */
/*! 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 syntax a.b[] $!x $y: * Example YANG:
* NONE: a b <x> <y>; * list a {a.b[] $!x $y:
* VARS: a b <x> y <y>; * list a {
* ALL: a b x <x> y <y>; * key x;
* leaf x;
* leaf y;
* }
* NONE: a <x> <y>;
* VARS: a <x> y <y>;
* ALL: a x <x> y <y>;
*/ */
enum genmodel_type{ enum genmodel_type{
GT_ERR =-1, /* Error */ GT_ERR =-1, /* Error */

View file

@ -31,6 +31,9 @@
***** END LICENSE BLOCK ***** ***** END LICENSE BLOCK *****
* Yang functions
* @see https://tools.ietf.org/html/rfc6020 YANG 1.0
* @see https://tools.ietf.org/html/rfc7950 YANG 1.1
*/ */
#ifndef _CLIXON_YANG_H_ #ifndef _CLIXON_YANG_H_

View file

@ -526,22 +526,25 @@ netconf_access_denied_xml(cxobj **xret,
char *message) char *message)
{ {
int retval =-1; int retval =-1;
cbuf *cbret = NULL; cxobj *xerr;
if ((cbret = cbuf_new()) == NULL){ if (*xret == NULL){
clicon_err(OE_XML, errno, "cbuf_new"); if ((*xret = xml_new("rpc-reply", NULL, NULL)) == NULL)
goto done; goto done;
} }
if (netconf_access_denied(cbret, type, message) < 0) else if (xml_name_set(*xret, "rpc-reply") < 0)
goto done; goto done;
if (xml_parse_string(cbuf_get(cbret), NULL, xret) < 0) if ((xerr = xml_new("rpc-error", *xret, NULL)) == NULL)
goto done; goto done;
if (xml_rootchild(*xret, 0, xret) < 0) if (xml_parse_va(&xerr, NULL, "<error-tag>access-denied</error-tag>"
"<error-type>%s</error-type>"
"<error-severity>error</error-severity>", type) < 0)
goto done;
if (message && xml_parse_va(&xerr, NULL, "<error-message>%s</error-message>",
message) < 0)
goto done; goto done;
retval = 0; retval = 0;
done: done:
if (cbret)
cbuf_free(cbret);
return retval; return retval;
} }
@ -835,22 +838,25 @@ netconf_operation_failed_xml(cxobj **xret,
char *message) char *message)
{ {
int retval =-1; int retval =-1;
cbuf *cbret = NULL; cxobj *xerr;
if ((cbret = cbuf_new()) == NULL){ if (*xret == NULL){
clicon_err(OE_XML, errno, "cbuf_new"); if ((*xret = xml_new("rpc-reply", NULL, NULL)) == NULL)
goto done; goto done;
} }
if (netconf_operation_failed(cbret, type, message) < 0) else if (xml_name_set(*xret, "rpc-reply") < 0)
goto done; goto done;
if (xml_parse_string(cbuf_get(cbret), NULL, xret) < 0) if ((xerr = xml_new("rpc-error", *xret, NULL)) == NULL)
goto done; goto done;
if (xml_rootchild(*xret, 0, xret) < 0) if (xml_parse_va(&xerr, NULL, "<error-tag>operation-failed</error-tag>"
"<error-type>%s</error-type>"
"<error-severity>error</error-severity>", type) < 0)
goto done;
if (message && xml_parse_va(&xerr, NULL, "<error-message>%s</error-message>",
message) < 0)
goto done; goto done;
retval = 0; retval = 0;
done: done:
if (cbret)
cbuf_free(cbret);
return retval; return retval;
} }
@ -892,3 +898,39 @@ netconf_malformed_message(cbuf *cb,
clicon_err(OE_XML, errno, "cprintf"); clicon_err(OE_XML, errno, "cprintf");
goto done; goto done;
} }
/*! Create Netconf malformed-message error XML tree according to RFC 6241 App A
*
* A message could not be handled because it failed to be parsed correctly.
* For example, the message is not well-formed XML or it uses an
* invalid character set.
* @param[out] xret Error XML tree
* @param[in] message Error message
* @note New in :base:1.1
*/
int
netconf_malformed_message_xml(cxobj **xret,
char *message)
{
int retval =-1;
cxobj *xerr;
if (*xret == NULL){
if ((*xret = xml_new("rpc-reply", NULL, NULL)) == NULL)
goto done;
}
else if (xml_name_set(*xret, "rpc-reply") < 0)
goto done;
if ((xerr = xml_new("rpc-error", *xret, NULL)) == NULL)
goto done;
if (xml_parse_va(&xerr, NULL, "<error-tag>malformed-message</error-tag>"
"<error-type>rpc</error-type>"
"<error-severity>error</error-severity>") < 0)
goto done;
if (message && xml_parse_va(&xerr, NULL, "<error-message>%s</error-message>",
message) < 0)
goto done;
retval = 0;
done:
return retval;
}

View file

@ -34,8 +34,9 @@
***** END LICENSE BLOCK ***** ***** END LICENSE BLOCK *****
* Database specification parser cli syntax * Yang parser. Hopefully useful but not complete
* (Cloned from cligen parser) * @see https://tools.ietf.org/html/rfc6020 YANG 1.0
* @see https://tools.ietf.org/html/rfc7950 YANG 1.1
*/ */
#ifndef _CLIXON_YANG_PARSE_H_ #ifndef _CLIXON_YANG_PARSE_H_
#define _CLIXON_YANG_PARSE_H_ #define _CLIXON_YANG_PARSE_H_

View file

@ -1,8 +1,4 @@
/* /*
* Yang 1.0 parser according to RFC6020.
* It is hopefully useful but not complete
* RFC7950 defines Yang version 1.1
*
***** BEGIN LICENSE BLOCK ***** ***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2018 Olof Hagsand and Benny Holmgren Copyright (C) 2009-2018 Olof Hagsand and Benny Holmgren
@ -34,8 +30,9 @@
***** END LICENSE BLOCK ***** ***** END LICENSE BLOCK *****
* Database specification parser cli syntax * Yang parser. Hopefully useful but not complete
* (Cloned from cligen parser) * @see https://tools.ietf.org/html/rfc6020 YANG 1.0
* @see https://tools.ietf.org/html/rfc7950 YANG 1.1
*/ */
%{ %{

View file

@ -1,7 +1,4 @@
/* /*
* Yang 1.0 parser according to RFC6020.
* It is hopefully useful but not complete
* RFC7950 defines Yang version 1.1
* *
***** BEGIN LICENSE BLOCK ***** ***** BEGIN LICENSE BLOCK *****
@ -34,6 +31,9 @@
***** END LICENSE BLOCK ***** ***** END LICENSE BLOCK *****
* Yang parser. Hopefully useful but not complete
* @see https://tools.ietf.org/html/rfc6020 YANG 1.0
* @see https://tools.ietf.org/html/rfc7950 YANG 1.1
*/ */

View file

@ -137,7 +137,7 @@ expectfn "curl -s -I http://localhost/restconf/data" "HTTP/1.1 200 OK"
#Content-Type: application/yang-data+json" #Content-Type: application/yang-data+json"
new2 "restconf empty rpc" new2 "restconf empty rpc"
expecteq "$(curl -s -X POST -d {\"input\":{\"name\":\"\"}} http://localhost/restconf/operations/ex:empty)" '' expecteq "$(curl -s -X POST -d {\"input\":{\"name\":\"\"}} http://localhost/restconf/operations/ex:empty)" ""
new2 "restconf get empty config + state json" new2 "restconf get empty config + state json"
expecteq "$(curl -sSG http://localhost/restconf/data)" '{"data": {"interfaces-state": {"interface": [{"name": "eth0","type": "eth","if-index": 42}]}}} expecteq "$(curl -sSG http://localhost/restconf/data)" '{"data": {"interfaces-state": {"interface": [{"name": "eth0","type": "eth","if-index": 42}]}}}
@ -213,11 +213,11 @@ expecteq "$(curl -s -G http://localhost/restconf/data)" '{"data": {"interfaces":
new2 "restconf Re-post eth/0/0 which should generate error" new2 "restconf Re-post eth/0/0 which should generate error"
expecteq "$(curl -s -X POST -d '{"interface":{"name":"eth/0/0","type":"eth","enabled":true}}' http://localhost/restconf/data/interfaces)" '{"ietf-restconf:errors" : {"error": {"error-tag": "data-exists","error-type": "application","error-severity": "error","error-message": "Data already exists; cannot create new resource"}}} ' expecteq "$(curl -s -X POST -d '{"interface":{"name":"eth/0/0","type":"eth","enabled":true}}' http://localhost/restconf/data/interfaces)" '{"ietf-restconf:errors" : {"error": {"error-tag": "data-exists","error-type": "application","error-severity": "error","error-message": "Data already exists; cannot create new resource"}}} '
new2 "Add leaf description using POST" new "Add leaf description using POST"
expecteq "$(curl -s -X POST -d '{"description":"The-first-interface"}' http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0)" "" expecteq "$(curl -s -X POST -d '{"description":"The-first-interface"}' http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0)" ""
new "Add nothing using POST" new "Add nothing using POST"
expectfn 'curl -s -X POST http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0' "data is in some way badly formed" expectfn 'curl -s -X POST http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0' '"ietf-restconf:errors" : {"error": {"rpc-error": {"error-tag": "malformed-message","error-type": "rpc","error-severity": "error","error-message": " on line 1: syntax error at or before:'
new2 "restconf Check description added" new2 "restconf Check description added"
expecteq "$(curl -s -G http://localhost/restconf/data)" '{"data": {"interfaces": {"interface": [{"name": "eth/0/0","description": "The-first-interface","type": "eth","enabled": true}]},"interfaces-state": {"interface": [{"name": "eth0","type": "eth","if-index": 42}]}}} expecteq "$(curl -s -G http://localhost/restconf/data)" '{"data": {"interfaces": {"interface": [{"name": "eth/0/0","description": "The-first-interface","type": "eth","enabled": true}]},"interfaces-state": {"interface": [{"name": "eth0","type": "eth","if-index": 42}]}}}
@ -232,7 +232,7 @@ expectfn 'curl -s -G http://localhost/restconf/data' $state
new2 "restconf Re-Delete eth/0/0 using none should generate error" new2 "restconf Re-Delete eth/0/0 using none should generate error"
expecteq "$(curl -s -X DELETE http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0)" '{"ietf-restconf:errors" : {"error": {"error-tag": "data-missing","error-type": "application","error-severity": "error","error-message": "Data does not exist; cannot delete resource"}}} ' expecteq "$(curl -s -X DELETE http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0)" '{"ietf-restconf:errors" : {"error": {"error-tag": "data-missing","error-type": "application","error-severity": "error","error-message": "Data does not exist; cannot delete resource"}}} '
new2 "restconf Add subtree eth/0/0 using PUT" new "restconf Add subtree eth/0/0 using PUT"
expecteq "$(curl -s -X PUT -d '{"interface":{"name":"eth/0/0","type":"eth","enabled":true}}' http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0)" "" expecteq "$(curl -s -X PUT -d '{"interface":{"name":"eth/0/0","type":"eth","enabled":true}}' http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0)" ""
new2 "restconf get subtree" new2 "restconf get subtree"
@ -243,9 +243,12 @@ new2 "restconf rpc using POST json"
expecteq "$(curl -s -X POST -d '{"input":{"routing-instance-name":"ipv4"}}' http://localhost/restconf/operations/rt:fib-route)" '{"output": {"route": {"address-family": "ipv4","next-hop": {"next-hop-list": "2.3.4.5"}}}} expecteq "$(curl -s -X POST -d '{"input":{"routing-instance-name":"ipv4"}}' http://localhost/restconf/operations/rt:fib-route)" '{"output": {"route": {"address-family": "ipv4","next-hop": {"next-hop-list": "2.3.4.5"}}}}
' '
# Cant get this to work due to quoting
#new2 "restconf rpc using POST wrong JSON"
#expecteq "$(curl -s -X POST -d '{"input":{"routing-instance-name":ipv4}}' http://localhost/restconf/operations/rt:fib-route)" '{"ietf-restconf:errors" : {"error": {"rpc-error": {"error-tag": "operation-failed","error-type": "protocol","error-severity": "error","error-message": " on line 1: syntax error at or before: i"}}}} '
new2 "restconf rpc using POST json w/o mandatory element" new2 "restconf rpc using POST json w/o mandatory element"
expecteq "$(curl -s -X POST -d '{"input":{"wrongelement":"ipv4"}}' http://localhost/restconf/operations/rt:fib-route)" '{"ietf-restconf:errors" : {"error": {"rpc-error": {"error-tag": "operation-failed","error-type": "protocol","error-severity": "error","error-message": "Missing mandatory variable: routing-instance-name"}}}} ' expecteq "$(curl -s -X POST -d '{"input":{"wrongelement":"ipv4"}}' http://localhost/restconf/operations/rt:fib-route)" '{"ietf-restconf:errors" : {"error": {"rpc-error": {"error-tag": "operation-failed","error-type": "protocol","error-severity": "error","error-message": "Missing mandatory variable: routing-instance-name"}}}} '
new2 "restconf rpc non-existing rpc w/o namespace" new2 "restconf rpc non-existing rpc w/o namespace"
expecteq "$(curl -s -X POST -d '{}' http://localhost/restconf/operations/kalle)" '{"ietf-restconf:errors" : {"error": {"rpc-error": {"error-tag": "operation-failed","error-type": "protocol","error-severity": "error","error-message": "yang node not found"}}}} ' expecteq "$(curl -s -X POST -d '{}' http://localhost/restconf/operations/kalle)" '{"ietf-restconf:errors" : {"error": {"rpc-error": {"error-tag": "operation-failed","error-type": "protocol","error-severity": "error","error-message": "yang node not found"}}}} '

View file

@ -134,7 +134,7 @@ new "restconf PUT add interface"
expectfn 'curl -s -X PUT -d {"interface":{"name":"TEST","type":"eth0"}} http://localhost/restconf/data/cont1/interface=TEST' "" expectfn 'curl -s -X PUT -d {"interface":{"name":"TEST","type":"eth0"}} http://localhost/restconf/data/cont1/interface=TEST' ""
new "restconf PUT change key error" new "restconf PUT change key error"
expectfn 'curl -is -X PUT -d {"interface":{"name":"ALPHA","type":"eth0"}} http://localhost/restconf/data/cont1/interface=TEST' "Bad request" expectfn 'curl -is -X PUT -d {"interface":{"name":"ALPHA","type":"eth0"}} http://localhost/restconf/data/cont1/interface=TEST' '{"ietf-restconf:errors" : {"error": {"rpc-error": {"error-tag": "operation-failed","error-type": "protocol","error-severity": "error","error-message": "api-path keys do not match data keys"}}}}'
new "Kill restconf daemon" new "Kill restconf daemon"
sudo pkill -u www-data clixon_restconf sudo pkill -u www-data clixon_restconf