Fixed empty restconf data segv; error restconf quit; etc
This commit is contained in:
parent
4a57b60935
commit
cd33380368
7 changed files with 90 additions and 43 deletions
|
|
@ -11,8 +11,13 @@
|
||||||
* Clixon XML C-lib prior to 3.4.0. As enabled with `configure --with-xml-compat`
|
* Clixon XML C-lib prior to 3.4.0. As enabled with `configure --with-xml-compat`
|
||||||
|
|
||||||
* new configuration option: CLICON_RESTCONF_PRETTY
|
* new configuration option: CLICON_RESTCONF_PRETTY
|
||||||
* Changed RESTCONF GET to return object referenced. ie, GET /restconf/data/X returns X.
|
* Changed RESTCONF GET to return object referenced. ie, GET /restconf/data/X returns X. Thanks Stephen Jones for getting this right.
|
||||||
|
|
||||||
|
* Default configure file added by Matt Smith. Config file is selected in the following priority order:
|
||||||
|
* Provide -f option when starting a program.
|
||||||
|
* Provide --with-configfile=FILE when configuring
|
||||||
|
* /etc/clixon.xml
|
||||||
|
|
||||||
### Corrected Bugs
|
### Corrected Bugs
|
||||||
* Corrected "No yang spec" printed on tty on leafref CLI usage
|
* Corrected "No yang spec" printed on tty on leafref CLI usage
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@ api_data_get_err(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
if ((xtag = xpath_first(xerr, "/error-tag")) == NULL){
|
if ((xtag = xpath_first(xerr, "/error-tag")) == NULL){
|
||||||
notfound(r); /* bad reply? */
|
notfound(r); /* bad reply? */
|
||||||
goto done;
|
goto ok;
|
||||||
}
|
}
|
||||||
code = restconf_err2code(xml_body(xtag));
|
code = restconf_err2code(xml_body(xtag));
|
||||||
if ((reason_phrase = restconf_code2reason(code)) == NULL)
|
if ((reason_phrase = restconf_code2reason(code)) == NULL)
|
||||||
|
|
@ -180,6 +180,7 @@ api_data_get_err(clicon_handle h,
|
||||||
FCGX_FPrintF(r->out, " %s", cbuf_get(cbj));
|
FCGX_FPrintF(r->out, " %s", cbuf_get(cbj));
|
||||||
FCGX_FPrintF(r->out, " }\r\n");
|
FCGX_FPrintF(r->out, " }\r\n");
|
||||||
FCGX_FPrintF(r->out, "}\r\n");
|
FCGX_FPrintF(r->out, "}\r\n");
|
||||||
|
ok:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (cbj)
|
if (cbj)
|
||||||
|
|
@ -247,13 +248,13 @@ api_data_get2(clicon_handle h,
|
||||||
/* We know "data" is element pi-1 */
|
/* We know "data" is element pi-1 */
|
||||||
if (api_path2xpath_cvv(yspec, pcvec, pi, cbpath) < 0){
|
if (api_path2xpath_cvv(yspec, pcvec, pi, cbpath) < 0){
|
||||||
notfound(r);
|
notfound(r);
|
||||||
goto done;
|
goto ok;
|
||||||
}
|
}
|
||||||
path = cbuf_get(cbpath);
|
path = cbuf_get(cbpath);
|
||||||
clicon_debug(1, "%s path:%s", __FUNCTION__, path);
|
clicon_debug(1, "%s path:%s", __FUNCTION__, path);
|
||||||
if (clicon_rpc_get(h, path, &xret) < 0){
|
if (clicon_rpc_get(h, path, &xret) < 0){
|
||||||
notfound(r);
|
notfound(r);
|
||||||
goto done;
|
goto ok;
|
||||||
}
|
}
|
||||||
/* We get return via netconf which is complete tree from root
|
/* We get return via netconf which is complete tree from root
|
||||||
* We need to cut that tree to only the object.
|
* We need to cut that tree to only the object.
|
||||||
|
|
@ -431,7 +432,8 @@ api_data_post(clicon_handle h,
|
||||||
__FUNCTION__,
|
__FUNCTION__,
|
||||||
api_path, data);
|
api_path, data);
|
||||||
media_content_type = FCGX_GetParam("HTTP_CONTENT_TYPE", r->envp);
|
media_content_type = FCGX_GetParam("HTTP_CONTENT_TYPE", r->envp);
|
||||||
if (strcmp(media_content_type, "application/yang-data+xml")==0)
|
if (media_content_type &&
|
||||||
|
strcmp(media_content_type, "application/yang-data+xml")==0)
|
||||||
parse_xml++;
|
parse_xml++;
|
||||||
if ((yspec = clicon_dbspec_yang(h)) == NULL){
|
if ((yspec = clicon_dbspec_yang(h)) == NULL){
|
||||||
clicon_err(OE_FATAL, 0, "No DB_SPEC");
|
clicon_err(OE_FATAL, 0, "No DB_SPEC");
|
||||||
|
|
@ -443,18 +445,19 @@ api_data_post(clicon_handle h,
|
||||||
if ((xtop = xml_new("config", NULL, NULL)) == NULL)
|
if ((xtop = xml_new("config", NULL, NULL)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
xbot = xtop;
|
xbot = xtop;
|
||||||
|
/* xbot is resulting xml tree on exit */
|
||||||
if (api_path && api_path2xml(api_path, yspec, xtop, 0, &xbot, &y) < 0)
|
if (api_path && api_path2xml(api_path, yspec, xtop, 0, &xbot, &y) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* 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){
|
||||||
clicon_debug(1, "%s json parse fail: %s", __FUNCTION__, data);
|
badrequest(r);
|
||||||
goto done;
|
goto ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (json_parse_str(data, &xdata) < 0){
|
else if (json_parse_str(data, &xdata) < 0){
|
||||||
clicon_debug(1, "%s json parse fail: %s", __FUNCTION__, data);
|
badrequest(r);
|
||||||
goto done;
|
goto ok;
|
||||||
}
|
}
|
||||||
/* Add xdata to xbot */
|
/* Add xdata to xbot */
|
||||||
x = NULL;
|
x = NULL;
|
||||||
|
|
@ -477,14 +480,13 @@ api_data_post(clicon_handle h,
|
||||||
cbuf_get(cbx)) < 0){
|
cbuf_get(cbx)) < 0){
|
||||||
// notfound(r); /* XXX */
|
// notfound(r); /* XXX */
|
||||||
conflict(r);
|
conflict(r);
|
||||||
goto done;
|
goto ok;
|
||||||
}
|
}
|
||||||
if (clicon_rpc_validate(h, "candidate") < 0){
|
if (clicon_rpc_validate(h, "candidate") < 0){
|
||||||
if (clicon_rpc_discard_changes(h) < 0)
|
if (clicon_rpc_discard_changes(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
badrequest(r);
|
badrequest(r);
|
||||||
retval = 0;
|
goto ok;
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
if (clicon_rpc_commit(h) < 0)
|
if (clicon_rpc_commit(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -492,6 +494,7 @@ api_data_post(clicon_handle h,
|
||||||
FCGX_FPrintF(r->out, "Content-Type: text/plain\r\n");
|
FCGX_FPrintF(r->out, "Content-Type: text/plain\r\n");
|
||||||
// XXX api_path can be null FCGX_FPrintF(r->out, "Location: %s\r\n", api_path);
|
// XXX api_path can be null FCGX_FPrintF(r->out, "Location: %s\r\n", api_path);
|
||||||
FCGX_FPrintF(r->out, "\r\n");
|
FCGX_FPrintF(r->out, "\r\n");
|
||||||
|
ok:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
||||||
|
|
@ -550,7 +553,8 @@ api_data_put(clicon_handle h,
|
||||||
__FUNCTION__,
|
__FUNCTION__,
|
||||||
api_path, data);
|
api_path, data);
|
||||||
media_content_type = FCGX_GetParam("HTTP_CONTENT_TYPE", r->envp);
|
media_content_type = FCGX_GetParam("HTTP_CONTENT_TYPE", r->envp);
|
||||||
if (strcmp(media_content_type, "application/yang-data+xml")==0)
|
if (media_content_type &&
|
||||||
|
strcmp(media_content_type, "application/yang-data+xml")==0)
|
||||||
parse_xml++;
|
parse_xml++;
|
||||||
if ((yspec = clicon_dbspec_yang(h)) == NULL){
|
if ((yspec = clicon_dbspec_yang(h)) == NULL){
|
||||||
clicon_err(OE_FATAL, 0, "No DB_SPEC");
|
clicon_err(OE_FATAL, 0, "No DB_SPEC");
|
||||||
|
|
@ -567,18 +571,17 @@ 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){
|
||||||
clicon_debug(1, "%s json parse fail: %s", __FUNCTION__, data);
|
badrequest(r);
|
||||||
goto done;
|
goto ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (json_parse_str(data, &xdata) < 0){
|
else if (json_parse_str(data, &xdata) < 0){
|
||||||
clicon_debug(1, "%s json parse fail: %s", __FUNCTION__, data);
|
badrequest(r);
|
||||||
goto done;
|
goto ok;
|
||||||
}
|
}
|
||||||
if (xml_child_nr(xdata) != 1){
|
if (xml_child_nr(xdata) != 1){
|
||||||
badrequest(r);
|
badrequest(r);
|
||||||
retval = 0;
|
goto ok;
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
x = xml_child_i(xdata,0);
|
x = xml_child_i(xdata,0);
|
||||||
if ((xa = xml_new("operation", x, NULL)) == NULL)
|
if ((xa = xml_new("operation", x, NULL)) == NULL)
|
||||||
|
|
@ -600,21 +603,21 @@ api_data_put(clicon_handle h,
|
||||||
OP_NONE,
|
OP_NONE,
|
||||||
cbuf_get(cbx)) < 0){
|
cbuf_get(cbx)) < 0){
|
||||||
notfound(r);
|
notfound(r);
|
||||||
goto done;
|
goto ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clicon_rpc_validate(h, "candidate") < 0){
|
if (clicon_rpc_validate(h, "candidate") < 0){
|
||||||
if (clicon_rpc_discard_changes(h) < 0)
|
if (clicon_rpc_discard_changes(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
badrequest(r);
|
badrequest(r);
|
||||||
retval = 0;
|
goto ok;
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
if (clicon_rpc_commit(h) < 0)
|
if (clicon_rpc_commit(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
FCGX_SetExitStatus(201, r->out); /* Created */
|
FCGX_SetExitStatus(201, r->out); /* Created */
|
||||||
FCGX_FPrintF(r->out, "Content-Type: text/plain\r\n");
|
FCGX_FPrintF(r->out, "Content-Type: text/plain\r\n");
|
||||||
FCGX_FPrintF(r->out, "\r\n");
|
FCGX_FPrintF(r->out, "\r\n");
|
||||||
|
ok:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
||||||
|
|
@ -703,13 +706,14 @@ api_data_delete(clicon_handle h,
|
||||||
OP_NONE,
|
OP_NONE,
|
||||||
cbuf_get(cbx)) < 0){
|
cbuf_get(cbx)) < 0){
|
||||||
notfound(r);
|
notfound(r);
|
||||||
goto done;
|
goto ok;
|
||||||
}
|
}
|
||||||
if (clicon_rpc_commit(h) < 0)
|
if (clicon_rpc_commit(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
FCGX_SetExitStatus(201, r->out);
|
FCGX_SetExitStatus(201, r->out);
|
||||||
FCGX_FPrintF(r->out, "Content-Type: text/plain\r\n");
|
FCGX_FPrintF(r->out, "Content-Type: text/plain\r\n");
|
||||||
FCGX_FPrintF(r->out, "\r\n");
|
FCGX_FPrintF(r->out, "\r\n");
|
||||||
|
ok:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (cbx)
|
if (cbx)
|
||||||
|
|
@ -762,12 +766,15 @@ api_operation_post(clicon_handle h,
|
||||||
int parse_xml = 0; /* By default expect and parse JSON */
|
int parse_xml = 0; /* By default expect and parse JSON */
|
||||||
char *media_accept;
|
char *media_accept;
|
||||||
int use_xml = 0; /* By default return JSON */
|
int use_xml = 0; /* By default return JSON */
|
||||||
|
int pretty;
|
||||||
|
|
||||||
clicon_debug(1, "%s json:\"%s\" path:\"%s\"", __FUNCTION__, data, path);
|
clicon_debug(1, "%s json:\"%s\" path:\"%s\"", __FUNCTION__, data, path);
|
||||||
|
pretty = clicon_option_bool(h, "CLICON_RESTCONF_PRETTY");
|
||||||
if ((media_accept = FCGX_GetParam("HTTP_ACCEPT", r->envp)) &&
|
if ((media_accept = FCGX_GetParam("HTTP_ACCEPT", r->envp)) &&
|
||||||
strcmp(media_accept, "application/yang-data+xml")==0)
|
strcmp(media_accept, "application/yang-data+xml")==0)
|
||||||
use_xml++;
|
use_xml++;
|
||||||
if ((media_content_type = FCGX_GetParam("HTTP_CONTENT_TYPE", r->envp)) &&
|
media_content_type = FCGX_GetParam("HTTP_CONTENT_TYPE", r->envp);
|
||||||
|
if (media_content_type &&
|
||||||
strcmp(media_content_type, "application/yang-data+xml")==0)
|
strcmp(media_content_type, "application/yang-data+xml")==0)
|
||||||
parse_xml++;
|
parse_xml++;
|
||||||
clicon_debug(1, "%s accept:\"%s\" content-type:\"%s\"",
|
clicon_debug(1, "%s accept:\"%s\" content-type:\"%s\"",
|
||||||
|
|
@ -785,7 +792,7 @@ api_operation_post(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
if (yrpc == NULL){
|
if (yrpc == NULL){
|
||||||
retval = notfound(r);
|
retval = notfound(r);
|
||||||
goto done;
|
goto ok;
|
||||||
}
|
}
|
||||||
/* Create an xml message:
|
/* Create an xml message:
|
||||||
* <"rpc"><operation><input-args>...
|
* <"rpc"><operation><input-args>...
|
||||||
|
|
@ -801,13 +808,13 @@ api_operation_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){
|
||||||
clicon_debug(1, "%s json parse fail: %s", __FUNCTION__, data);
|
badrequest(r);
|
||||||
goto done;
|
goto ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (json_parse_str(data, &xdata) < 0){
|
else if (json_parse_str(data, &xdata) < 0){
|
||||||
clicon_debug(1, "%s json parse fail: %s", __FUNCTION__, data);
|
badrequest(r);
|
||||||
goto done;
|
goto ok;
|
||||||
}
|
}
|
||||||
/* xdata should have format <top><input> */
|
/* xdata should have format <top><input> */
|
||||||
if ((xinput = xpath_first(xdata, "/input")) != NULL){
|
if ((xinput = xpath_first(xdata, "/input")) != NULL){
|
||||||
|
|
@ -854,9 +861,10 @@ api_operation_post(clicon_handle h,
|
||||||
if ((cbx = cbuf_new()) == NULL)
|
if ((cbx = cbuf_new()) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
xoutput=xpath_first(xret, "/");
|
xoutput=xpath_first(xret, "/");
|
||||||
|
xml_name_set(xoutput, "output");
|
||||||
if ((youtput = yang_find((yang_node*)yrpc, Y_OUTPUT, NULL)) != NULL &&
|
if ((youtput = yang_find((yang_node*)yrpc, Y_OUTPUT, NULL)) != NULL &&
|
||||||
xoutput){
|
xoutput){
|
||||||
xml_name_set(xoutput, "output");
|
|
||||||
clicon_debug(1, "%s xoutput:%s", __FUNCTION__, cbuf_get(cbx));
|
clicon_debug(1, "%s xoutput:%s", __FUNCTION__, cbuf_get(cbx));
|
||||||
cbuf_reset(cbx);
|
cbuf_reset(cbx);
|
||||||
xml_spec_set(xoutput, youtput); /* needed for xml_spec_populate */
|
xml_spec_set(xoutput, youtput); /* needed for xml_spec_populate */
|
||||||
|
|
@ -874,16 +882,17 @@ api_operation_post(clicon_handle h,
|
||||||
FCGX_FPrintF(r->out, "\r\n");
|
FCGX_FPrintF(r->out, "\r\n");
|
||||||
if (xoutput){
|
if (xoutput){
|
||||||
if (use_xml){
|
if (use_xml){
|
||||||
if (clicon_xml2cbuf(cbx, xoutput, 0, 1) < 0)
|
if (clicon_xml2cbuf(cbx, xoutput, 0, pretty) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (xml2json_cbuf(cbx, xoutput, 1) < 0)
|
if (xml2json_cbuf(cbx, xoutput, pretty) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
clicon_debug(1, "%s xoutput:%s", __FUNCTION__, cbuf_get(cbx));
|
clicon_debug(1, "%s xoutput:%s", __FUNCTION__, cbuf_get(cbx));
|
||||||
FCGX_FPrintF(r->out, "%s", cbx?cbuf_get(cbx):"");
|
FCGX_FPrintF(r->out, "%s", cbx?cbuf_get(cbx):"");
|
||||||
FCGX_FPrintF(r->out, "\r\n\r\n");
|
FCGX_FPrintF(r->out, "\r\n\r\n");
|
||||||
}
|
}
|
||||||
|
ok:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,18 @@ fib_route(clicon_handle h, /* Clicon handle */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Smallest possible RPC declaration for test */
|
||||||
|
static int
|
||||||
|
empty(clicon_handle h, /* Clicon handle */
|
||||||
|
cxobj *xe, /* Request: <rpc><xn></rpc> */
|
||||||
|
struct client_entry *ce, /* Client session */
|
||||||
|
cbuf *cbret, /* Reply eg <rpc-reply>... */
|
||||||
|
void *arg) /* Argument given at register */
|
||||||
|
{
|
||||||
|
cprintf(cbret, "<rpc-reply/>");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*! IETF Routing route-count rpc */
|
/*! IETF Routing route-count rpc */
|
||||||
static int
|
static int
|
||||||
route_count(clicon_handle h,
|
route_count(clicon_handle h,
|
||||||
|
|
@ -201,6 +213,11 @@ plugin_init(clicon_handle h)
|
||||||
"route-count"/* Xml tag when callback is made */
|
"route-count"/* Xml tag when callback is made */
|
||||||
) < 0)
|
) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
if (backend_rpc_cb_register(h, empty,
|
||||||
|
NULL,
|
||||||
|
"empty"/* Xml tag when callback is made */
|
||||||
|
) < 0)
|
||||||
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
||||||
|
|
@ -623,7 +623,7 @@ json_parse(char *str,
|
||||||
* @param[in] str String containing JSON
|
* @param[in] str String containing JSON
|
||||||
* @param[out] xt On success a top of XML parse tree is created with name 'top'
|
* @param[out] xt On success a top of XML parse tree is created with name 'top'
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error with clicon_err called
|
* @retval -1 Error with clicon_err called. Includes parse errors
|
||||||
*
|
*
|
||||||
* @code
|
* @code
|
||||||
* cxobj *cx = NULL;
|
* cxobj *cx = NULL;
|
||||||
|
|
|
||||||
|
|
@ -1355,8 +1355,8 @@ xml_parse_file(int fd,
|
||||||
* @param[in] str String containing XML definition.
|
* @param[in] str String containing XML definition.
|
||||||
* @param[in] yspec Yang specification, or NULL
|
* @param[in] yspec Yang specification, or NULL
|
||||||
* @param[in,out] xt Pointer to XML parse tree. If empty will be created.
|
* @param[in,out] xt Pointer to XML parse tree. If empty will be created.
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error with clicon_err called
|
* @retval -1 Error with clicon_err called. Includes parse error
|
||||||
*
|
*
|
||||||
* @code
|
* @code
|
||||||
* cxobj *xt = NULL;
|
* cxobj *xt = NULL;
|
||||||
|
|
|
||||||
|
|
@ -1750,6 +1750,7 @@ xml_merge1(cxobj *x0,
|
||||||
/*! Merge XML trees x1 into x0 according to yang spec yspec
|
/*! Merge XML trees x1 into x0 according to yang spec yspec
|
||||||
* @note both x0 and x1 need to be top-level trees
|
* @note both x0 and x1 need to be top-level trees
|
||||||
* @see text_modify_top as more generic variant (in datastore text)
|
* @see text_modify_top as more generic variant (in datastore text)
|
||||||
|
* @note returns -1 if YANG do not match, you may want to have a softer error
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xml_merge(cxobj *x0,
|
xml_merge(cxobj *x0,
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,12 @@
|
||||||
cfg=$dir/conf.xml
|
cfg=$dir/conf.xml
|
||||||
fyang=$dir/restconf.yang
|
fyang=$dir/restconf.yang
|
||||||
|
|
||||||
|
# <CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
||||||
cat <<EOF > $cfg
|
cat <<EOF > $cfg
|
||||||
<config>
|
<config>
|
||||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||||
<CLICON_YANG_DIR>/usr/local/share/routing/yang</CLICON_YANG_DIR>
|
<CLICON_YANG_DIR>/usr/local/share/routing/yang</CLICON_YANG_DIR>
|
||||||
<CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
<CLICON_YANG_MODULE_MAIN>$fyang</CLICON_YANG_MODULE_MAIN>
|
||||||
<CLICON_CLISPEC_DIR>/usr/local/lib/routing/clispec</CLICON_CLISPEC_DIR>
|
<CLICON_CLISPEC_DIR>/usr/local/lib/routing/clispec</CLICON_CLISPEC_DIR>
|
||||||
<CLICON_BACKEND_DIR>/usr/local/lib/routing/backend</CLICON_BACKEND_DIR>
|
<CLICON_BACKEND_DIR>/usr/local/lib/routing/backend</CLICON_BACKEND_DIR>
|
||||||
<CLICON_RESTCONF_DIR>/usr/local/lib/routing/restconf</CLICON_RESTCONF_DIR>
|
<CLICON_RESTCONF_DIR>/usr/local/lib/routing/restconf</CLICON_RESTCONF_DIR>
|
||||||
|
|
@ -28,6 +29,7 @@ EOF
|
||||||
|
|
||||||
cat <<EOF > $fyang
|
cat <<EOF > $fyang
|
||||||
module example{
|
module example{
|
||||||
|
prefix ex;
|
||||||
import ietf-ip {
|
import ietf-ip {
|
||||||
prefix ip;
|
prefix ip;
|
||||||
}
|
}
|
||||||
|
|
@ -38,6 +40,16 @@ module example{
|
||||||
prefix "inet";
|
prefix "inet";
|
||||||
revision-date "2013-07-15";
|
revision-date "2013-07-15";
|
||||||
}
|
}
|
||||||
|
rpc empty {
|
||||||
|
}
|
||||||
|
rpc input {
|
||||||
|
input {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rpc output {
|
||||||
|
output {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|
@ -60,7 +72,7 @@ new "kill old restconf daemon"
|
||||||
sudo pkill -u www-data clixon_restconf
|
sudo pkill -u www-data clixon_restconf
|
||||||
|
|
||||||
new "start restconf daemon"
|
new "start restconf daemon"
|
||||||
sudo start-stop-daemon -S -q -o -b -x /www-data/clixon_restconf -d /www-data -c www-data -- -Df $cfg # -D
|
sudo start-stop-daemon -S -q -o -b -x /www-data/clixon_restconf -d /www-data -c www-data -- -Df $cfg -D
|
||||||
|
|
||||||
sleep 1
|
sleep 1
|
||||||
|
|
||||||
|
|
@ -76,13 +88,15 @@ expectfn "curl -sS -I http://localhost/restconf/data" "HTTP/1.1 200 OK"
|
||||||
new "restconf root discovery"
|
new "restconf root discovery"
|
||||||
expectfn "curl -sS -X GET http://localhost/.well-known/host-meta" "<Link rel='restconf' href='/restconf'/>"
|
expectfn "curl -sS -X GET http://localhost/.well-known/host-meta" "<Link rel='restconf' href='/restconf'/>"
|
||||||
|
|
||||||
|
new "restconf empty rpc"
|
||||||
|
expectfn 'curl -sS -X POST -d {"input":{"name":""}} http://localhost/restconf/operations/ex:empty' '{"output": null}'
|
||||||
|
|
||||||
#new "restconf get restconf json XXX"
|
#new "restconf get restconf json XXX"
|
||||||
#expectfn "curl -sSG http://localhost/restconf" "{\"restconf\" : $state }"
|
#expectfn "curl -sSG http://localhost/restconf" "{\"restconf\" : $state }"
|
||||||
|
|
||||||
#new "restconf get restconf/yang-library-version json XXX"
|
#new "restconf get restconf/yang-library-version json XXX"
|
||||||
#expectfn "curl -sSG http://localhost/restconf/yang-library-version" "{\"restconf\" : $state }"
|
#expectfn "curl -sSG http://localhost/restconf/yang-library-version" "{\"restconf\" : $state }"
|
||||||
|
|
||||||
|
|
||||||
new "restconf get empty config + state json"
|
new "restconf get empty config + state json"
|
||||||
expectfn "curl -sSG http://localhost/restconf/data" "{\"data\": $state}"
|
expectfn "curl -sSG http://localhost/restconf/data" "{\"data\": $state}"
|
||||||
|
|
||||||
|
|
@ -145,6 +159,9 @@ expectfn 'curl -sS -X POST -d {"interface":{"name":"eth/0/0","type":"eth","enabl
|
||||||
new "Add leaf description using POST"
|
new "Add leaf description using POST"
|
||||||
expectfn 'curl -sS -X POST -d {"description":"The-first-interface"} http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0' ""
|
expectfn 'curl -sS -X POST -d {"description":"The-first-interface"} http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0' ""
|
||||||
|
|
||||||
|
new "Add nothing using POST"
|
||||||
|
expectfn 'curl -sS -X POST http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0' "data is in some way badly formed"
|
||||||
|
|
||||||
new "restconf Check description added"
|
new "restconf Check description added"
|
||||||
expectfn "curl -sS -G http://localhost/restconf/data" '{"interfaces": {"interface": {"name": "eth/0/0","description": "The-first-interface","type": "eth","enabled": "true"}}
|
expectfn "curl -sS -G http://localhost/restconf/data" '{"interfaces": {"interface": {"name": "eth/0/0","description": "The-first-interface","type": "eth","enabled": "true"}}
|
||||||
$'
|
$'
|
||||||
|
|
@ -165,15 +182,13 @@ new "restconf get subtree"
|
||||||
expectfn "curl -sS -G http://localhost/restconf/data" '{"interfaces": {"interface": {"name": "eth/0/0","type": "eth","enabled": "true"}},"interfaces-state": {"interface": {"name": "eth0","type": "eth","if-index": "42"}}}
|
expectfn "curl -sS -G http://localhost/restconf/data" '{"interfaces": {"interface": {"name": "eth/0/0","type": "eth","enabled": "true"}},"interfaces-state": {"interface": {"name": "eth0","type": "eth","if-index": "42"}}}
|
||||||
$'
|
$'
|
||||||
|
|
||||||
new "restconf operation rpc using POST json"
|
new "restconf rpc using POST json"
|
||||||
expectfn 'curl -sS -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" } } } } '
|
expectfn 'curl -sS -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"}}}}'
|
||||||
|
|
||||||
exit # XXX
|
|
||||||
|
|
||||||
new "restconf rpc using POST xml"
|
new "restconf rpc using POST xml"
|
||||||
# Cant get shell macros to work, inline matching from lib.sh
|
# Cant get shell macros to work, inline matching from lib.sh
|
||||||
ret=$(curl -sS -X POST -H "Accept: application/yang-data+xml" -d '{"input":{"routing-instance-name":"ipv4"}}' http://localhost/restconf/operations/rt:fib-route)
|
ret=$(curl -sS -X POST -H "Accept: application/yang-data+xml" -d '{"input":{"routing-instance-name":"ipv4"}}' http://localhost/restconf/operations/rt:fib-route)
|
||||||
expect="<output> <route> <address-family>ipv4</address-family> <next-hop> <next-hop-list>2.3.4.5</next-hop-li t> </next-hop> </route> </output> "
|
expect="<output><route><address-family>ipv4</address-family><next-hop><next-hop-list>2.3.4.5</next-hop-list></next-hop></route></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"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue