Fixed side-effect of RESTCONF PUT key-match patch
This commit is contained in:
parent
519fac186c
commit
97079b0a88
2 changed files with 45 additions and 34 deletions
|
|
@ -636,11 +636,14 @@ api_data_post(clicon_handle h,
|
||||||
|
|
||||||
/*! Check matching keys
|
/*! Check matching keys
|
||||||
*
|
*
|
||||||
|
* Check that x1 and x2 (both of type list/leaf-list) share the same key statements
|
||||||
|
* I.e that if x1=<list><key>b</key></list> then x2 = <list><key>b</key></list> as
|
||||||
|
* well
|
||||||
* @param[in] y Yang statement, should be list or leaf-list
|
* @param[in] y Yang statement, should be list or leaf-list
|
||||||
* @param[in] xdata XML data tree
|
* @param[in] x1 First XML tree (eg data tree)
|
||||||
* @param[in] xapipath XML api-path tree
|
* @param[in] x2 Second XML tree (eg api-path tree)
|
||||||
* @retval 0 Yes, keys match
|
* @retval 0 Yes, keys match
|
||||||
* @retval -1 No keys do not match
|
* @retval -1 No keys do not match
|
||||||
* If the target resource represents a YANG leaf-list, then the PUT
|
* If the target resource represents a YANG leaf-list, then the PUT
|
||||||
* method MUST NOT change the value of the leaf-list instance.
|
* method MUST NOT change the value of the leaf-list instance.
|
||||||
*
|
*
|
||||||
|
|
@ -651,17 +654,18 @@ api_data_post(clicon_handle h,
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
match_list_keys(yang_stmt *y,
|
match_list_keys(yang_stmt *y,
|
||||||
cxobj *xdata,
|
cxobj *x1,
|
||||||
cxobj *xapipath)
|
cxobj *x2)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cvec *cvk = NULL; /* vector of index keys */
|
cvec *cvk = NULL; /* vector of index keys */
|
||||||
cg_var *cvi;
|
cg_var *cvi;
|
||||||
char *keyname;
|
char *keyname;
|
||||||
cxobj *xkeya; /* xml key object in api-path */
|
cxobj *xkey1; /* xml key object of x1 */
|
||||||
cxobj *xkeyd; /* xml key object in data */
|
cxobj *xkey2; /* xml key object of x2 */
|
||||||
char *keya;
|
char *key1;
|
||||||
char *keyd;
|
char *key2;
|
||||||
|
|
||||||
|
|
||||||
clicon_debug(1, "%s", __FUNCTION__);
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
switch (yang_keyword_get(y)){
|
switch (yang_keyword_get(y)){
|
||||||
|
|
@ -670,24 +674,24 @@ match_list_keys(yang_stmt *y,
|
||||||
cvi = NULL;
|
cvi = NULL;
|
||||||
while ((cvi = cvec_each(cvk, cvi)) != NULL) {
|
while ((cvi = cvec_each(cvk, cvi)) != NULL) {
|
||||||
keyname = cv_string_get(cvi);
|
keyname = cv_string_get(cvi);
|
||||||
if ((xkeya = xml_find(xapipath, keyname)) == NULL)
|
if ((xkey2 = xml_find(x2, keyname)) == NULL)
|
||||||
goto done; /* No key in api-path */
|
goto done; /* No key in api-path */
|
||||||
if ((keya = xml_body(xkeya)) == NULL)
|
if ((key2 = xml_body(xkey2)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if ((xkeyd = xml_find(xdata, keyname)) == NULL)
|
if ((xkey1 = xml_find(x1, keyname)) == NULL)
|
||||||
goto done; /* No key in data */
|
goto done; /* No key in data */
|
||||||
if ((keyd = xml_body(xkeyd)) == NULL)
|
if ((key1 = xml_body(xkey1)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (strcmp(keya, keyd) != 0)
|
if (strcmp(key2, key1) != 0)
|
||||||
goto done; /* keys dont match */
|
goto done; /* keys dont match */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Y_LEAF_LIST:
|
case Y_LEAF_LIST:
|
||||||
if ((keya = xml_body(xapipath)) == NULL)
|
if ((key2 = xml_body(x2)) == NULL)
|
||||||
goto done; /* No key in api-path */
|
goto done; /* No key in api-path */
|
||||||
if ((keyd = xml_body(xdata)) == NULL)
|
if ((key1 = xml_body(x1)) == NULL)
|
||||||
goto done; /* No key in data */
|
goto done; /* No key in data */
|
||||||
if (strcmp(keya, keyd) != 0)
|
if (strcmp(key2, key1) != 0)
|
||||||
goto done; /* keys dont match */
|
goto done; /* keys dont match */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -884,26 +888,27 @@ api_data_put(clicon_handle h,
|
||||||
* That is why the conditional is somewhat hairy
|
* That is why the conditional is somewhat hairy
|
||||||
*/
|
*/
|
||||||
xparent = xml_parent(xbot);
|
xparent = xml_parent(xbot);
|
||||||
#if 1
|
|
||||||
if (debug){
|
|
||||||
cbuf *ccc=cbuf_new();
|
|
||||||
if (clicon_xml2cbuf(ccc, xtop, 0, 0) < 0)
|
|
||||||
goto done;
|
|
||||||
clicon_debug(1, "%s AAA XPATH:%s", __FUNCTION__, cbuf_get(ccc));
|
|
||||||
}
|
|
||||||
if (debug){
|
|
||||||
cbuf *ccc=cbuf_new();
|
|
||||||
if (clicon_xml2cbuf(ccc, xdata, 0, 0) < 0)
|
|
||||||
goto done;
|
|
||||||
clicon_debug(1, "%s DATA:%s", __FUNCTION__, cbuf_get(ccc));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (y){
|
if (y){
|
||||||
yp = yang_parent_get(y);
|
yp = yang_parent_get(y);
|
||||||
|
/* Ensure list keys match between uri and data */
|
||||||
if (((yang_keyword_get(y) == Y_LIST || yang_keyword_get(y) == Y_LEAF_LIST) &&
|
if (((yang_keyword_get(y) == Y_LIST || yang_keyword_get(y) == Y_LEAF_LIST) &&
|
||||||
match_list_keys(y, x, xbot) < 0) ||
|
match_list_keys(y, x, xbot) < 0)){
|
||||||
(yp && yang_keyword_get(yp) == Y_LIST &&
|
if (netconf_operation_failed_xml(&xerr, "protocol", "api-path keys do not match data keys") < 0)
|
||||||
|
goto done;
|
||||||
|
if ((xe = xpath_first(xerr, "rpc-error")) == NULL){
|
||||||
|
clicon_err(OE_XML, EINVAL, "rpc-error not found (internal error)");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (api_return_err(h, r, xe, pretty, use_xml) < 0)
|
||||||
|
goto done;
|
||||||
|
goto ok;
|
||||||
|
|
||||||
|
}
|
||||||
|
/* Ensure list keys match between uri and data of parents
|
||||||
|
* XXX: this may only be a special case of immediate parent
|
||||||
|
*/
|
||||||
|
if ((yp && yang_keyword_get(yp) == Y_LIST &&
|
||||||
|
xml_parent(x) != xdata &&
|
||||||
match_list_keys(yp, xml_parent(x), xparent) < 0)){
|
match_list_keys(yp, xml_parent(x), xparent) < 0)){
|
||||||
if (netconf_operation_failed_xml(&xerr, "protocol", "api-path keys do not match data keys") < 0)
|
if (netconf_operation_failed_xml(&xerr, "protocol", "api-path keys do not match data keys") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -174,6 +174,12 @@ expectfn 'curl -s -X PUT -d {"interface":{"name":"TEST","type":"eth0"}} http://l
|
||||||
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/example:cont1/interface=TEST' 0 '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "operation-failed","error-severity": "error","error-message": "api-path keys do not match data keys"}}}'
|
expectfn 'curl -is -X PUT -d {"interface":{"name":"ALPHA","type":"eth0"}} http://localhost/restconf/data/example:cont1/interface=TEST' 0 '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "operation-failed","error-severity": "error","error-message": "api-path keys do not match data keys"}}}'
|
||||||
|
|
||||||
|
new "restconf PUT change type to eth0 (non-key sub-element to list)"
|
||||||
|
expectfn 'curl -s -X PUT -d {"example:type":"eth0"} http://localhost/restconf/data/example:cont1/interface=local0/type' 0 ""
|
||||||
|
|
||||||
|
new "restconf GET datastore eth"
|
||||||
|
expectfn "curl -s -X GET http://localhost/restconf/data/example:cont1/interface=local0" 0 '{"example:interface": \[{"name": "local0","type": "eth0"}\]}'
|
||||||
|
|
||||||
#--------------- json type tests
|
#--------------- json type tests
|
||||||
new "restconf POST type x3"
|
new "restconf POST type x3"
|
||||||
expectfn 'curl -s -X POST -d {"example:types":{"tint":42,"tdec64":42.123,"tbool":false,"tstr":"str"}} http://localhost/restconf/data' 0 ''
|
expectfn 'curl -s -X POST -d {"example:types":{"tint":42,"tdec64":42.123,"tbool":false,"tstr":"str"}} http://localhost/restconf/data' 0 ''
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue