* Pagination according to new draft
* count/skip -> limit/offset * ietf-yang-metadata RFC 7952 support, placeholder parsing and extension
This commit is contained in:
parent
77bacc93bb
commit
0c7f2043f3
26 changed files with 751 additions and 620 deletions
|
|
@ -81,6 +81,11 @@ Users may have to change how they access the system
|
||||||
* Added linenumbers to all YANG symbols for better debug and errors
|
* Added linenumbers to all YANG symbols for better debug and errors
|
||||||
* Improved error messages for YANG identityref:s and leafref:s by adding original line numbers
|
* Improved error messages for YANG identityref:s and leafref:s by adding original line numbers
|
||||||
|
|
||||||
|
### Minor features
|
||||||
|
|
||||||
|
* ietf-yang-metadata RFC 7952 support, placeholder parsing and extension
|
||||||
|
* No actual json/xml semantics
|
||||||
|
|
||||||
### Corrected Bugs
|
### Corrected Bugs
|
||||||
|
|
||||||
* Partly Fixed: [String concatenation in YANG model leads to syntax error](https://github.com/clicon/clixon/issues/265)
|
* Partly Fixed: [String concatenation in YANG model leads to syntax error](https://github.com/clicon/clixon/issues/265)
|
||||||
|
|
|
||||||
|
|
@ -359,6 +359,7 @@ client_statedata(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
cbuf_reset(cb);
|
cbuf_reset(cb);
|
||||||
|
/* XXX This code does not filter state data with xpath */
|
||||||
cprintf(cb, "<restconf-state xmlns=\"%s\"/>", namespace);
|
cprintf(cb, "<restconf-state xmlns=\"%s\"/>", namespace);
|
||||||
if (clixon_xml_parse_string(cbuf_get(cb), YB_MODULE, yspec, xret, NULL) < 0)
|
if (clixon_xml_parse_string(cbuf_get(cb), YB_MODULE, yspec, xret, NULL) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1422,8 +1423,10 @@ from_client_get_pageable_list(clicon_handle h,
|
||||||
int i;
|
int i;
|
||||||
cxobj *xerr = NULL;
|
cxobj *xerr = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
uint32_t count = 0;
|
uint32_t limit = 0;
|
||||||
uint32_t skip = 0;
|
uint32_t offset = 0;
|
||||||
|
size_t total = 0;
|
||||||
|
uint32_t remaining = 0;
|
||||||
char *direction = NULL;
|
char *direction = NULL;
|
||||||
char *sort = NULL;
|
char *sort = NULL;
|
||||||
char *where = NULL;
|
char *where = NULL;
|
||||||
|
|
@ -1435,6 +1438,7 @@ from_client_get_pageable_list(clicon_handle h,
|
||||||
char *ns;
|
char *ns;
|
||||||
clixon_path *path_tree = NULL;
|
clixon_path *path_tree = NULL;
|
||||||
clixon_path *cp;
|
clixon_path *cp;
|
||||||
|
cxobj *xa; /* attribute */
|
||||||
|
|
||||||
clicon_debug(1, "%s", __FUNCTION__);
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
username = clicon_username_get(h);
|
username = clicon_username_get(h);
|
||||||
|
|
@ -1458,11 +1462,11 @@ from_client_get_pageable_list(clicon_handle h,
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* count */
|
/* limit */
|
||||||
if ((ret = element2value(h, xe, "count", "unbounded", cbret, &count)) < 0)
|
if ((ret = element2value(h, xe, "limit", "unbounded", cbret, &limit)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* skip */
|
/* offset */
|
||||||
if (ret && (ret = element2value(h, xe, "skip", "none", cbret, &skip)) < 0)
|
if (ret && (ret = element2value(h, xe, "offset", "none", cbret, &offset)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* direction */
|
/* direction */
|
||||||
if (ret && (x = xml_find_type(xe, NULL, "direction", CX_ELMNT)) != NULL){
|
if (ret && (x = xml_find_type(xe, NULL, "direction", CX_ELMNT)) != NULL){
|
||||||
|
|
@ -1496,13 +1500,17 @@ from_client_get_pageable_list(clicon_handle h,
|
||||||
if (xml_nsctx_node(x, &nsc) < 0)
|
if (xml_nsctx_node(x, &nsc) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (xpath == NULL){
|
||||||
|
clicon_err(OE_NETCONF, 0, "Missing list-target/xpath, is mandatory");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
if ((xtop = xml_new("top", NULL, CX_ELMNT)) == NULL)
|
if ((xtop = xml_new("top", NULL, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
/* Parse xpath -> stuctured path tree */
|
/* Parse xpath -> stuctured path tree */
|
||||||
if ((ret = clixon_instance_id_parse(yspec, &path_tree, "%s", xpath)) < 0)
|
if ((ret = clixon_instance_id_parse(yspec, &path_tree, &xerr, "%s", xpath)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
if (clicon_xml2cbuf(cbret, xerr, 0, 0, -1) < 0)
|
if (xerr && clicon_xml2cbuf(cbret, xerr, 0, 0, -1) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
|
|
@ -1524,40 +1532,51 @@ from_client_get_pageable_list(clicon_handle h,
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
/* Build a "predicate" cbuf
|
/* Build a "predicate" cbuf
|
||||||
* This solution uses xpath predicates to translate "count" and "skip" to
|
* This solution uses xpath predicates to translate "limit" and "offset" to
|
||||||
* relational operators <>.
|
* relational operators <>.
|
||||||
*/
|
*/
|
||||||
if ((cb = cbuf_new()) == NULL){
|
if ((cb = cbuf_new()) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* This uses xpath. Maybe count/limit should use parameters */
|
/* This uses xpath. Maybe limit should use parameters */
|
||||||
cprintf(cb, "%s", xpath);
|
cprintf(cb, "%s", xpath);
|
||||||
if (where)
|
if (where)
|
||||||
cprintf(cb, "[%s]", where);
|
cprintf(cb, "[%s]", where);
|
||||||
if (skip){
|
if (offset){
|
||||||
cprintf(cb, "[%u <= position()", skip);
|
cprintf(cb, "[%u <= position()", offset);
|
||||||
if (count)
|
if (limit)
|
||||||
cprintf(cb, " and position() < %u", count+skip);
|
cprintf(cb, " and position() < %u", limit+offset);
|
||||||
cprintf(cb, "]");
|
cprintf(cb, "]");
|
||||||
}
|
}
|
||||||
else if (count)
|
else if (limit)
|
||||||
cprintf(cb, "[position() < %u]", count);
|
cprintf(cb, "[position() < %u]", limit);
|
||||||
|
|
||||||
/* Split into CT or CF */
|
/* Split into CT or CF */
|
||||||
if (yang_config_ancestor(y) == 1){ /* CT */
|
if (yang_config_ancestor(y) == 1){ /* CT */
|
||||||
if (content == CONTENT_CONFIG || content == CONTENT_ALL){
|
if (content == CONTENT_CONFIG || content == CONTENT_ALL){
|
||||||
if ((ret = xmldb_get0(h, datastore, YB_MODULE, nsc, cbuf_get(cb), 1, &xret, NULL, &xerr)) < 0) {
|
if ((ret = xmldb_get0(h, datastore, YB_MODULE, nsc, xpath, 1, &xret, NULL, &xerr)) < 0) {
|
||||||
if (netconf_operation_failed(cbret, "application", "read registry")< 0)
|
if (netconf_operation_failed(cbret, "application", "read registry")< 0)
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
if (clicon_xml2cbuf(cbret, xerr, 0, 0, -1) < 0)
|
if (clicon_xml2cbuf(cbret, xerr, 0, 0, -1) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
|
/* First get number of hits */
|
||||||
|
if (xpath_vec(xret, nsc, "%s", &xvec, &total, xpath) < 0)
|
||||||
|
goto done;
|
||||||
|
if (xvec){
|
||||||
|
free(xvec);
|
||||||
|
xvec = NULL;
|
||||||
|
}
|
||||||
|
if (total < (offset + limit))
|
||||||
|
remaining = 0;
|
||||||
|
else
|
||||||
|
remaining = total - (offset + limit);
|
||||||
|
}
|
||||||
/* There may be CF data in a CT collection */
|
/* There may be CF data in a CT collection */
|
||||||
if (content == CONTENT_ALL){
|
if (content == CONTENT_ALL){
|
||||||
if ((ret = client_statedata(h, cbuf_get(cb), nsc, content, &xret)) < 0)
|
if ((ret = client_statedata(h, cbuf_get(cb), nsc, content, &xret)) < 0)
|
||||||
|
|
@ -1576,7 +1595,8 @@ from_client_get_pageable_list(clicon_handle h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (clicon_option_bool(h, "CLICON_VALIDATE_STATE_XML")){
|
if (0 && clicon_option_bool(h, "CLICON_VALIDATE_STATE_XML")){
|
||||||
|
/* XXX: subset in collection may not have mandatory variables */
|
||||||
/* Check XML by validating it. return internal error with error cause
|
/* Check XML by validating it. return internal error with error cause
|
||||||
* Primarily intended for user-supplied state-data.
|
* Primarily intended for user-supplied state-data.
|
||||||
* The whole config tree must be present in case the state data references config data
|
* The whole config tree must be present in case the state data references config data
|
||||||
|
|
@ -1614,7 +1634,7 @@ from_client_get_pageable_list(clicon_handle h,
|
||||||
* Actually this is a safety catch, should really be done in plugins
|
* Actually this is a safety catch, should really be done in plugins
|
||||||
* and modules_state functions.
|
* and modules_state functions.
|
||||||
*/
|
*/
|
||||||
if (xpath_vec(xret, nsc, "%s", &xvec, &xlen, xpath?xpath:"/") < 0)
|
if (xpath_vec(xret, nsc, "%s", &xvec, &xlen, cbuf_get(cb)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* Pre-NACM access step */
|
/* Pre-NACM access step */
|
||||||
|
|
@ -1632,6 +1652,21 @@ from_client_get_pageable_list(clicon_handle h,
|
||||||
/* Add namespace */
|
/* Add namespace */
|
||||||
if (xmlns_set(x, NULL, ns) < 0)
|
if (xmlns_set(x, NULL, ns) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
if (i == 0 && remaining != total){
|
||||||
|
/* Add remaining annotation to first element
|
||||||
|
* If no elements were removed, this annotation MUST NOT appear
|
||||||
|
*/
|
||||||
|
if ((xa = xml_new("remaining", x, CX_ATTR)) == NULL)
|
||||||
|
goto done;
|
||||||
|
cbuf_reset(cb); /* reuse */
|
||||||
|
cprintf(cb, "%u", remaining);
|
||||||
|
if (xml_value_set(xa, cbuf_get(cb)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (xml_prefix_set(xa, "lpg") < 0)
|
||||||
|
goto done;
|
||||||
|
if (xmlns_set(x, "lpg", "urn:ietf:params:xml:ns:yang:ietf-list-pagination") < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
/* Top level is data, so add 1 to depth if significant */
|
/* Top level is data, so add 1 to depth if significant */
|
||||||
if (clicon_xml2cbuf(cbret, x, 0, 0, depth>0?depth+1:depth) < 0)
|
if (clicon_xml2cbuf(cbret, x, 0, 0, depth>0?depth+1:depth) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -2291,7 +2326,7 @@ backend_rpc_init(clicon_handle h)
|
||||||
#ifdef LIST_PAGINATION
|
#ifdef LIST_PAGINATION
|
||||||
/* draft-ietf-netconf-restconf-collection-00 */
|
/* draft-ietf-netconf-restconf-collection-00 */
|
||||||
if (rpc_callback_register(h, from_client_get_pageable_list, NULL,
|
if (rpc_callback_register(h, from_client_get_pageable_list, NULL,
|
||||||
NETCONF_COLLECTION_NAMESPACE, "get-pageable-list") < 0)
|
NETCONF_COLLECTION_NAMESPACE, "get-pagable-list") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
#endif
|
#endif
|
||||||
/* In backend_client.? RPC from RFC 5277 */
|
/* In backend_client.? RPC from RFC 5277 */
|
||||||
|
|
|
||||||
|
|
@ -767,6 +767,9 @@ main(int argc,
|
||||||
if (netconf_module_features(h) < 0)
|
if (netconf_module_features(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
/* In case ietf-yang-metadata is loaded by application, handle annotation extension */
|
||||||
|
if (yang_metadata_init(h) < 0)
|
||||||
|
goto done;
|
||||||
/* External NACM file?
|
/* External NACM file?
|
||||||
* Note, loads yang -> extensions -> plugins
|
* Note, loads yang -> extensions -> plugins
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -237,8 +237,9 @@ clixon_plugin_daemon_all(clicon_handle h)
|
||||||
*
|
*
|
||||||
* @param[in] cp Plugin handle
|
* @param[in] cp Plugin handle
|
||||||
* @param[in] h clicon handle
|
* @param[in] h clicon handle
|
||||||
|
* @param[in] nsc namespace context for xpath
|
||||||
* @param[in] xpath String with XPATH syntax. or NULL for all
|
* @param[in] xpath String with XPATH syntax. or NULL for all
|
||||||
* @param[out] xret If retval=1, state tree created and returned: <config>...
|
* @param[out] xp If retval=1, state tree created and returned: <config>...
|
||||||
* @retval -1 Fatal error
|
* @retval -1 Fatal error
|
||||||
* @retval 0 Statedata callback failed. no XML tree returned
|
* @retval 0 Statedata callback failed. no XML tree returned
|
||||||
* @retval 1 OK if callback found (and called) xret is set
|
* @retval 1 OK if callback found (and called) xret is set
|
||||||
|
|
@ -254,6 +255,7 @@ clixon_plugin_statedata_one(clixon_plugin_t *cp,
|
||||||
plgstatedata_t *fn; /* Plugin statedata fn */
|
plgstatedata_t *fn; /* Plugin statedata fn */
|
||||||
cxobj *x = NULL;
|
cxobj *x = NULL;
|
||||||
|
|
||||||
|
clicon_debug(1, "%s %s", __FUNCTION__, clixon_plugin_name_get(cp));
|
||||||
if ((fn = clixon_plugin_api_get(cp)->ca_statedata) != NULL){
|
if ((fn = clixon_plugin_api_get(cp)->ca_statedata) != NULL){
|
||||||
if ((x = xml_new(XML_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL)
|
if ((x = xml_new(XML_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -263,7 +265,6 @@ clixon_plugin_statedata_one(clixon_plugin_t *cp,
|
||||||
__FUNCTION__, clixon_plugin_name_get(cp));
|
__FUNCTION__, clixon_plugin_name_get(cp));
|
||||||
goto fail; /* Dont quit here on user callbacks */
|
goto fail; /* Dont quit here on user callbacks */
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (xp && x)
|
if (xp && x)
|
||||||
*xp = x;
|
*xp = x;
|
||||||
|
|
@ -328,10 +329,8 @@ clixon_plugin_statedata_all(clicon_handle h,
|
||||||
x = NULL;
|
x = NULL;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#if 1
|
|
||||||
if (clicon_debug_get())
|
if (clicon_debug_get())
|
||||||
clicon_log_xml(LOG_DEBUG, x, "%s STATE:", __FUNCTION__);
|
clicon_log_xml(LOG_DEBUG, x, "%s %s STATE:", __FUNCTION__, clixon_plugin_name_get(cp));
|
||||||
#endif
|
|
||||||
/* XXX: ret == 0 invalid yang binding should be handled as internal error */
|
/* XXX: ret == 0 invalid yang binding should be handled as internal error */
|
||||||
if ((ret = xml_bind_yang(x, YB_MODULE, yspec, &xerr)) < 0)
|
if ((ret = xml_bind_yang(x, YB_MODULE, yspec, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -633,6 +633,9 @@ main(int argc,
|
||||||
*/
|
*/
|
||||||
if (netconf_module_features(h) < 0)
|
if (netconf_module_features(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
/* In case ietf-yang-metadata is loaded by application, handle annotation extension */
|
||||||
|
if (yang_metadata_init(h) < 0)
|
||||||
|
goto done;
|
||||||
/* Set default namespace according to CLICON_NAMESPACE_NETCONF_DEFAULT */
|
/* Set default namespace according to CLICON_NAMESPACE_NETCONF_DEFAULT */
|
||||||
xml_nsctx_namespace_netconf_default(h);
|
xml_nsctx_namespace_netconf_default(h);
|
||||||
/* Create top-level and store as option */
|
/* Create top-level and store as option */
|
||||||
|
|
|
||||||
|
|
@ -800,7 +800,9 @@ main(int argc,
|
||||||
/* Initialize plugin module by creating a handle holding plugin and callback lists */
|
/* Initialize plugin module by creating a handle holding plugin and callback lists */
|
||||||
if (clixon_plugin_module_init(h) < 0)
|
if (clixon_plugin_module_init(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
/* In case ietf-yang-metadata is loaded by application, handle annotation extension */
|
||||||
|
if (yang_metadata_init(h) < 0)
|
||||||
|
goto done;
|
||||||
/* Create top-level yang spec and store as option */
|
/* Create top-level yang spec and store as option */
|
||||||
if ((yspec = yspec_new()) == NULL)
|
if ((yspec = yspec_new()) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -370,7 +370,9 @@ main(int argc,
|
||||||
*/
|
*/
|
||||||
if (netconf_module_features(h) < 0)
|
if (netconf_module_features(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
/* In case ietf-yang-metadata is loaded by application, handle annotation extension */
|
||||||
|
if (yang_metadata_init(h) < 0)
|
||||||
|
goto done;
|
||||||
/* Create top-level yang spec and store as option */
|
/* Create top-level yang spec and store as option */
|
||||||
if ((yspec = yspec_new()) == NULL)
|
if ((yspec = yspec_new()) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -1724,7 +1724,9 @@ restconf_clixon_init(clicon_handle h,
|
||||||
*/
|
*/
|
||||||
if (netconf_module_features(h) < 0)
|
if (netconf_module_features(h) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
/* In case ietf-yang-metadata is loaded by application, handle annotation extension */
|
||||||
|
if (yang_metadata_init(h) < 0)
|
||||||
|
goto done;
|
||||||
/* Create top-level yang spec and store as option */
|
/* Create top-level yang spec and store as option */
|
||||||
if ((yspec = yspec_new()) == NULL)
|
if ((yspec = yspec_new()) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -359,8 +359,8 @@ api_data_collection(clicon_handle h,
|
||||||
yang_stmt *y = NULL;
|
yang_stmt *y = NULL;
|
||||||
cbuf *cbrpc = NULL;
|
cbuf *cbrpc = NULL;
|
||||||
char *depth;
|
char *depth;
|
||||||
char *count;
|
char *limit;
|
||||||
char *skip;
|
char *offset;
|
||||||
char *direction;
|
char *direction;
|
||||||
char *sort;
|
char *sort;
|
||||||
char *where;
|
char *where;
|
||||||
|
|
@ -435,14 +435,14 @@ api_data_collection(clicon_handle h,
|
||||||
}
|
}
|
||||||
/* Clixon extensions and collection attributes */
|
/* Clixon extensions and collection attributes */
|
||||||
depth = cvec_find_str(qvec, "depth");
|
depth = cvec_find_str(qvec, "depth");
|
||||||
count = cvec_find_str(qvec, "count");
|
limit = cvec_find_str(qvec, "limit");
|
||||||
skip = cvec_find_str(qvec, "skip");
|
offset = cvec_find_str(qvec, "offset");
|
||||||
direction = cvec_find_str(qvec, "direction");
|
direction = cvec_find_str(qvec, "direction");
|
||||||
sort = cvec_find_str(qvec, "sort");
|
sort = cvec_find_str(qvec, "sort");
|
||||||
where = cvec_find_str(qvec, "where");
|
where = cvec_find_str(qvec, "where");
|
||||||
|
|
||||||
if (clicon_rpc_get_pageable_list(h, "running", xpath, y, nsc, content,
|
if (clicon_rpc_get_pageable_list(h, "running", xpath, y, nsc, content,
|
||||||
depth, count, skip, direction, sort, where,
|
depth, limit, offset, direction, sort, where,
|
||||||
&xret) < 0){
|
&xret) < 0){
|
||||||
if (netconf_operation_failed_xml(&xerr, "protocol", clicon_err_reason) < 0)
|
if (netconf_operation_failed_xml(&xerr, "protocol", clicon_err_reason) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -149,7 +149,7 @@ How to debug
|
||||||
|
|
||||||
Send debug level in run-time to backend:
|
Send debug level in run-time to backend:
|
||||||
```
|
```
|
||||||
echo "<rpc username=\"root\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><debug xmlns=\"http://clicon.org/lib\"><level>1</level></debug></rpc>]]>]]>" | clixon_netconf -q
|
echo "<rpc username=\"root\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><debug xmlns=\"http://clicon.org/lib\"><level>1</level></debug></rpc>]]>]]>" | clixon_netconf -q -o CLICON_NETCONF_HELLO_OPTIONAL=true
|
||||||
```
|
```
|
||||||
|
|
||||||
### Set backend debug
|
### Set backend debug
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@
|
||||||
|
|
||||||
/*! Enable list pagination drafts
|
/*! Enable list pagination drafts
|
||||||
* draft-wwlh-netconf-list-pagination-00,
|
* draft-wwlh-netconf-list-pagination-00,
|
||||||
* draft-wwlh-netconf-list-pagination-nc-00
|
* draft-wwlh-netconf-list-pagination-nc-01
|
||||||
* draft-wwlh-netconf-list-pagination-rc-00
|
* draft-wwlh-netconf-list-pagination-rc-01
|
||||||
*/
|
*/
|
||||||
#define LIST_PAGINATION
|
#define LIST_PAGINATION
|
||||||
|
|
|
||||||
|
|
@ -91,12 +91,12 @@ int clixon_xml_find_api_path(cxobj *xt, yang_stmt *yt, cxobj ***xvec, int *xlen,
|
||||||
int clixon_xml_find_instance_id(cxobj *xt, yang_stmt *yt, cxobj ***xvec, int *xlen, const char *format,
|
int clixon_xml_find_instance_id(cxobj *xt, yang_stmt *yt, cxobj ***xvec, int *xlen, const char *format,
|
||||||
...) __attribute__ ((format (printf, 5, 6)));;
|
...) __attribute__ ((format (printf, 5, 6)));;
|
||||||
int clixon_instance_id_bind(yang_stmt *yt, cvec *nsctx, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
|
int clixon_instance_id_bind(yang_stmt *yt, cvec *nsctx, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
|
||||||
int clixon_instance_id_parse(yang_stmt *yt, clixon_path **cplistp, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
|
int clixon_instance_id_parse(yang_stmt *yt, clixon_path **cplistp, cxobj **xerr, const char *format, ...) __attribute__ ((format (printf, 4, 5)));
|
||||||
#else
|
#else
|
||||||
int clixon_xml_find_api_path(cxobj *xt, yang_stmt *yt, cxobj ***xvec, int *xlen, const char *format, ...);
|
int clixon_xml_find_api_path(cxobj *xt, yang_stmt *yt, cxobj ***xvec, int *xlen, const char *format, ...);
|
||||||
int clixon_xml_find_instance_id(cxobj *xt, yang_stmt *yt, cxobj ***xvec, int *xlen, const char *format, ...);
|
int clixon_xml_find_instance_id(cxobj *xt, yang_stmt *yt, cxobj ***xvec, int *xlen, const char *format, ...);
|
||||||
int clixon_instance_id_bind(yang_stmt *yt, cvec *nsctx, const char *format, ...);
|
int clixon_instance_id_bind(yang_stmt *yt, cvec *nsctx, const char *format, ...);
|
||||||
int clixon_instance_id_parse(yang_stmt *yt, clixon_path **cplistp, const char *format, ...);
|
int clixon_instance_id_parse(yang_stmt *yt, clixon_path **cplistp, cxobj **xerr, const char *format, ...);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _CLIXON_PATH_H_ */
|
#endif /* _CLIXON_PATH_H_ */
|
||||||
|
|
|
||||||
|
|
@ -76,5 +76,6 @@ yang_stmt *yang_find_module_by_namespace(yang_stmt *yspec, char *ns);
|
||||||
yang_stmt *yang_find_module_by_namespace_revision(yang_stmt *yspec, const char *ns, const char *revision);
|
yang_stmt *yang_find_module_by_namespace_revision(yang_stmt *yspec, const char *ns, const char *revision);
|
||||||
yang_stmt *yang_find_module_by_name_revision(yang_stmt *yspec, const char *name, const char *revision);
|
yang_stmt *yang_find_module_by_name_revision(yang_stmt *yspec, const char *name, const char *revision);
|
||||||
yang_stmt *yang_find_module_by_name(yang_stmt *yspec, char *name);
|
yang_stmt *yang_find_module_by_name(yang_stmt *yspec, char *name);
|
||||||
|
int yang_metadata_init(clicon_handle h);
|
||||||
|
|
||||||
#endif /* _CLIXON_YANG_MODULE_H_ */
|
#endif /* _CLIXON_YANG_MODULE_H_ */
|
||||||
|
|
|
||||||
|
|
@ -1256,9 +1256,9 @@ _json_parse(char *str,
|
||||||
/* RFC 7951 Section 4: A namespace-qualified member name MUST be used for all
|
/* RFC 7951 Section 4: A namespace-qualified member name MUST be used for all
|
||||||
* members of a top-level JSON object
|
* members of a top-level JSON object
|
||||||
*/
|
*/
|
||||||
if (yspec && xml_prefix(x) == NULL
|
if (yspec && xml_prefix(x) == NULL &&
|
||||||
/* && yb != YB_MODULE_NEXT XXX Dont know what this is for */
|
/* XXX: For top-level config file: */
|
||||||
){
|
(yb != YB_NONE || strcmp(xml_name(x),DATASTORE_TOP_SYMBOL)!=0)){
|
||||||
if ((cberr = cbuf_new()) == NULL){
|
if ((cberr = cbuf_new()) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
#include <cligen/cligen.h>
|
#include <cligen/cligen.h>
|
||||||
|
|
@ -72,6 +73,8 @@
|
||||||
#include "clixon_xpath.h"
|
#include "clixon_xpath.h"
|
||||||
#include "clixon_yang_module.h"
|
#include "clixon_yang_module.h"
|
||||||
#include "clixon_yang_parse_lib.h"
|
#include "clixon_yang_parse_lib.h"
|
||||||
|
#include "clixon_plugin.h"
|
||||||
|
|
||||||
#include "clixon_netconf_lib.h"
|
#include "clixon_netconf_lib.h"
|
||||||
|
|
||||||
/*! Create Netconf in-use error XML tree according to RFC 6241 Appendix A
|
/*! Create Netconf in-use error XML tree according to RFC 6241 Appendix A
|
||||||
|
|
@ -1485,6 +1488,7 @@ netconf_module_features(clicon_handle h)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Load generic yang specs, ie ietf netconf yang module and set enabled features
|
/*! Load generic yang specs, ie ietf netconf yang module and set enabled features
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
|
|
@ -1530,6 +1534,15 @@ netconf_module_load(clicon_handle h)
|
||||||
/* Load netconf list pagination */
|
/* Load netconf list pagination */
|
||||||
if (yang_spec_parse_module(h, "ietf-netconf-list-pagination", NULL, yspec)< 0)
|
if (yang_spec_parse_module(h, "ietf-netconf-list-pagination", NULL, yspec)< 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
#if 0
|
||||||
|
/* XXX Clixon test harness problem: when loading ietf-list-pagination, it loads
|
||||||
|
* ietf-system-capabilities which in turn loads ietf-netconf-acm. As this is a
|
||||||
|
* system module (always loaded) it means all test-cases
|
||||||
|
*/
|
||||||
|
/* Load list pagination */
|
||||||
|
if (yang_spec_parse_module(h, "ietf-list-pagination", NULL, yspec)< 0)
|
||||||
|
goto done;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
|
|
||||||
|
|
@ -1403,9 +1403,8 @@ api_path_resolve(clixon_path *cplist,
|
||||||
/*! Resolve instance-id prefix:names to yang statements
|
/*! Resolve instance-id prefix:names to yang statements
|
||||||
* @param[in] cplist Lisp of clixon-path
|
* @param[in] cplist Lisp of clixon-path
|
||||||
* @param[in] yt Yang statement of top symbol (can be yang-spec if top-level)
|
* @param[in] yt Yang statement of top symbol (can be yang-spec if top-level)
|
||||||
* @param[in] xt XML statement for prefix context
|
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @retval 0 Fail
|
* @retval 0 Fail error in xerr
|
||||||
* @retval 1 OK
|
* @retval 1 OK
|
||||||
* @note: The spec says: prefixes depend on the XML context in which the value occurs.
|
* @note: The spec says: prefixes depend on the XML context in which the value occurs.
|
||||||
* However, canonical prefixes/namespaces are used based on loaded yang modules.
|
* However, canonical prefixes/namespaces are used based on loaded yang modules.
|
||||||
|
|
@ -1440,7 +1439,7 @@ instance_id_resolve(clixon_path *cplist,
|
||||||
}
|
}
|
||||||
if (yang_keyword_get(yt) == Y_SPEC){
|
if (yang_keyword_get(yt) == Y_SPEC){
|
||||||
if ((yt = yang_find_module_by_prefix_yspec(yspec, cp->cp_prefix)) == NULL){
|
if ((yt = yang_find_module_by_prefix_yspec(yspec, cp->cp_prefix)) == NULL){
|
||||||
clicon_err(OE_YANG, ENOENT, "Prefix does not correspond to existing module.");
|
clicon_err(OE_YANG, ENOENT, "Prefix \"%s\" does not correspond to any existing module", cp->cp_prefix);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1857,6 +1856,7 @@ clixon_instance_id_bind(yang_stmt *yt,
|
||||||
* example.
|
* example.
|
||||||
* @param[in] yt Yang statement of top symbol (can be yang-spec if top-level)
|
* @param[in] yt Yang statement of top symbol (can be yang-spec if top-level)
|
||||||
* @param[out] cplistp Path parse-tree
|
* @param[out] cplistp Path parse-tree
|
||||||
|
* @param[out] xerr Contains error if retval=0
|
||||||
* @param[in] format Format string for xpath syntax
|
* @param[in] format Format string for xpath syntax
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @retval 0 Non-fatal failure, yang bind failures, etc,
|
* @retval 0 Non-fatal failure, yang bind failures, etc,
|
||||||
|
|
@ -1865,6 +1865,7 @@ clixon_instance_id_bind(yang_stmt *yt,
|
||||||
int
|
int
|
||||||
clixon_instance_id_parse(yang_stmt *yt,
|
clixon_instance_id_parse(yang_stmt *yt,
|
||||||
clixon_path **cplistp,
|
clixon_path **cplistp,
|
||||||
|
cxobj **xerr,
|
||||||
const char *format,
|
const char *format,
|
||||||
...)
|
...)
|
||||||
{
|
{
|
||||||
|
|
@ -1898,8 +1899,11 @@ clixon_instance_id_parse(yang_stmt *yt,
|
||||||
/* Resolve module:name to pointer to yang-stmt, fail if not successful */
|
/* Resolve module:name to pointer to yang-stmt, fail if not successful */
|
||||||
if ((ret = instance_id_resolve(cplist, yt)) < 0)
|
if ((ret = instance_id_resolve(cplist, yt)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0){
|
||||||
|
if (xerr && netconf_invalid_value_xml(xerr, "application", clicon_err_reason) < 0)
|
||||||
|
goto done;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
}
|
||||||
if (cplistp){
|
if (cplistp){
|
||||||
*cplistp = cplist;
|
*cplistp = cplist;
|
||||||
cplist = NULL;
|
cplist = NULL;
|
||||||
|
|
|
||||||
|
|
@ -159,7 +159,6 @@ plugin_module_struct_set(clicon_handle h,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Access functions */
|
/* Access functions */
|
||||||
|
|
||||||
/*! Get plugin api
|
/*! Get plugin api
|
||||||
|
|
|
||||||
|
|
@ -887,8 +887,8 @@ clicon_rpc_get(clicon_handle h,
|
||||||
* @param[in] nsc Namespace context for filter
|
* @param[in] nsc Namespace context for filter
|
||||||
* @param[in] content Clixon extension: all, config, noconfig. -1 means all
|
* @param[in] content Clixon extension: all, config, noconfig. -1 means all
|
||||||
* @param[in] depth Nr of XML levels to get, -1 is all, 0 is none
|
* @param[in] depth Nr of XML levels to get, -1 is all, 0 is none
|
||||||
* @param[in] count Collection/clixon extension
|
* @param[in] limit Collection/clixon extension
|
||||||
* @param[in] skip Collection/clixon extension
|
* @param[in] offset Collection/clixon extension
|
||||||
* @param[in] direction Collection/clixon extension
|
* @param[in] direction Collection/clixon extension
|
||||||
* @param[in] sort Collection/clixon extension
|
* @param[in] sort Collection/clixon extension
|
||||||
* @param[in] where Collection/clixon extension
|
* @param[in] where Collection/clixon extension
|
||||||
|
|
@ -909,8 +909,8 @@ clicon_rpc_get_pageable_list(clicon_handle h,
|
||||||
cvec *nsc, /* namespace context for xpath */
|
cvec *nsc, /* namespace context for xpath */
|
||||||
netconf_content content,
|
netconf_content content,
|
||||||
char *depth,
|
char *depth,
|
||||||
char *count,
|
char *limit,
|
||||||
char *skip,
|
char *offset,
|
||||||
char *direction,
|
char *direction,
|
||||||
char *sort,
|
char *sort,
|
||||||
char *where,
|
char *where,
|
||||||
|
|
@ -941,7 +941,7 @@ clicon_rpc_get_pageable_list(clicon_handle h,
|
||||||
cprintf(cb, " xmlns:%s=\"%s\"",
|
cprintf(cb, " xmlns:%s=\"%s\"",
|
||||||
NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
|
||||||
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR);
|
cprintf(cb, " %s", NETCONF_MESSAGE_ID_ATTR);
|
||||||
cprintf(cb, "><get-pageable-list xmlns=\"%s\"", NETCONF_COLLECTION_NAMESPACE);
|
cprintf(cb, "><get-pagable-list xmlns=\"%s\"", NETCONF_COLLECTION_NAMESPACE);
|
||||||
/* Clixon extension, content=all,config, or nonconfig */
|
/* Clixon extension, content=all,config, or nonconfig */
|
||||||
if ((int)content != -1)
|
if ((int)content != -1)
|
||||||
cprintf(cb, " content=\"%s\"", netconf_content_int2str(content));
|
cprintf(cb, " content=\"%s\"", netconf_content_int2str(content));
|
||||||
|
|
@ -955,17 +955,17 @@ clicon_rpc_get_pageable_list(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
cprintf(cb, ">%s</list-target>", xpath);
|
cprintf(cb, ">%s</list-target>", xpath);
|
||||||
}
|
}
|
||||||
if (count)
|
if (limit)
|
||||||
cprintf(cb, "<count>%s</count>", count);
|
cprintf(cb, "<limit>%s</limit>", limit);
|
||||||
if (skip)
|
if (offset)
|
||||||
cprintf(cb, "<skip>%s</skip>", skip);
|
cprintf(cb, "<offset>%s</offset>", offset);
|
||||||
if (direction)
|
if (direction)
|
||||||
cprintf(cb, "<direction>%s</direction>", direction);
|
cprintf(cb, "<direction>%s</direction>", direction);
|
||||||
if (sort)
|
if (sort)
|
||||||
cprintf(cb, "<sort>%s</sort>", sort);
|
cprintf(cb, "<sort>%s</sort>", sort);
|
||||||
if (where)
|
if (where)
|
||||||
cprintf(cb, "<where>%s</where>", where);
|
cprintf(cb, "<where>%s</where>", where);
|
||||||
cprintf(cb, "</get-pageable-list></rpc>");
|
cprintf(cb, "</get-pagable-list></rpc>");
|
||||||
if ((msg = clicon_msg_encode(session_id, "%s", cbuf_get(cb))) == NULL)
|
if ((msg = clicon_msg_encode(session_id, "%s", cbuf_get(cb))) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
if (clicon_rpc_msg(h, msg, &xret) < 0)
|
||||||
|
|
|
||||||
|
|
@ -1604,8 +1604,8 @@ yang_print(FILE *f,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Log/debug info about top-level (sub)modules no recursion
|
/* Log/debug info about top-level (sub)modules no recursion
|
||||||
* @param[in] f File to print to.
|
|
||||||
* @param[in] yspec Yang spec
|
* @param[in] yspec Yang spec
|
||||||
|
* @param[in] dbglevel Debug level
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
yang_spec_dump(yang_stmt *yspec,
|
yang_spec_dump(yang_stmt *yspec,
|
||||||
|
|
@ -2402,7 +2402,6 @@ ys_populate_unknown(clicon_handle h,
|
||||||
*/
|
*/
|
||||||
if (clixon_plugin_extension_all(h, yext, ys) < 0)
|
if (clixon_plugin_extension_all(h, yext, ys) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (prefix)
|
if (prefix)
|
||||||
|
|
|
||||||
|
|
@ -679,3 +679,60 @@ yang_find_module_by_name(yang_stmt *yspec,
|
||||||
return ymod;
|
return ymod;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Callback for handling RFC 7952 annotations
|
||||||
|
*
|
||||||
|
* a server indicates that it is prepared to handle that annotation according to the
|
||||||
|
* annotation's definition. That is, an annotation advertised by the
|
||||||
|
* server may be attached to an instance of a data node defined in any
|
||||||
|
* YANG module that is implemented by the server.
|
||||||
|
* Possibly add them to yang parsing, cardinality, etc?
|
||||||
|
* as described in Section 3.
|
||||||
|
* Note this is called by the module using the extension md:annotate, not by
|
||||||
|
* ietf-yang-metadata.yang
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
ietf_yang_metadata_extension_cb(clicon_handle h,
|
||||||
|
yang_stmt *yext,
|
||||||
|
yang_stmt *ys)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char *extname;
|
||||||
|
char *modname;
|
||||||
|
yang_stmt *ymod;
|
||||||
|
|
||||||
|
ymod = ys_module(yext);
|
||||||
|
modname = yang_argument_get(ymod);
|
||||||
|
extname = yang_argument_get(yext);
|
||||||
|
if (strcmp(modname, "ietf-yang-metadata") != 0 || strcmp(extname, "annotation") != 0)
|
||||||
|
goto ok;
|
||||||
|
clicon_debug(1, "%s Enabled extension:%s:%s", __FUNCTION__, modname, extname);
|
||||||
|
/* XXX Nothing yet - this should signal that xml attribute annotations are allowed
|
||||||
|
* Possibly, add an "annotation" YANG node.
|
||||||
|
*/
|
||||||
|
ok:
|
||||||
|
retval = 0;
|
||||||
|
// done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! In case ietf-yang-metadata is loaded by application, handle annotation extension
|
||||||
|
* Consider moving fn
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
yang_metadata_init(clicon_handle h)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
clixon_plugin_t *cp = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
/* Create a pseudo-plugin to create extension callback to set the ietf-yang-meta
|
||||||
|
* yang-data extension for api-root top-level restconf function.
|
||||||
|
*/
|
||||||
|
if (clixon_pseudo_plugin(h, "pseudo yang metadata", &cp) < 0)
|
||||||
|
goto done;
|
||||||
|
clixon_plugin_api_get(cp)->ca_extension = ietf_yang_metadata_extension_cb;
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,271 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# Example-module from draft-netconf-list-pagination-nc-00.txt
|
|
||||||
# Assumes variable fexample is set to name of yang file
|
|
||||||
# An extra leaf-list is added (clixon)
|
|
||||||
|
|
||||||
cat <<EOF > $fexample
|
|
||||||
module example-module {
|
|
||||||
yang-version 1.1;
|
|
||||||
namespace "http://example.com/ns/example-module";
|
|
||||||
prefix exm;
|
|
||||||
|
|
||||||
import iana-crypt-hash {
|
|
||||||
prefix ianach;
|
|
||||||
}
|
|
||||||
import ietf-inet-types {
|
|
||||||
prefix inet;
|
|
||||||
}
|
|
||||||
import ietf-yang-types {
|
|
||||||
prefix yang;
|
|
||||||
}
|
|
||||||
|
|
||||||
organization
|
|
||||||
"Example, Inc.";
|
|
||||||
contact
|
|
||||||
"support at example.com";
|
|
||||||
description
|
|
||||||
"Example Data Model Module.";
|
|
||||||
|
|
||||||
revision 2020-10-06 {
|
|
||||||
description
|
|
||||||
"Initial version.";
|
|
||||||
reference
|
|
||||||
"example.com document 1-4673.";
|
|
||||||
}
|
|
||||||
|
|
||||||
container admins {
|
|
||||||
description
|
|
||||||
"Admin Group configuration.";
|
|
||||||
list admin {
|
|
||||||
key "name";
|
|
||||||
description
|
|
||||||
"List of admins for admin group configuration.";
|
|
||||||
ordered-by system;
|
|
||||||
leaf name {
|
|
||||||
type string {
|
|
||||||
length "1 .. max";
|
|
||||||
}
|
|
||||||
description
|
|
||||||
"The name of the admin.";
|
|
||||||
}
|
|
||||||
leaf access {
|
|
||||||
type enumeration {
|
|
||||||
enum permit {
|
|
||||||
description
|
|
||||||
"Permit access privilege.";
|
|
||||||
}
|
|
||||||
enum deny {
|
|
||||||
description
|
|
||||||
"Deny access privilege.";
|
|
||||||
}
|
|
||||||
enum limited {
|
|
||||||
description
|
|
||||||
"Limited access privilege.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default "permit";
|
|
||||||
description
|
|
||||||
"The Access privilege type for this admin.";
|
|
||||||
}
|
|
||||||
leaf email-address {
|
|
||||||
type inet:email-address;
|
|
||||||
description
|
|
||||||
"Contact email of the admin.";
|
|
||||||
}
|
|
||||||
leaf password {
|
|
||||||
type ianach:crypt-hash;
|
|
||||||
description
|
|
||||||
"The password for this entry.";
|
|
||||||
}
|
|
||||||
leaf-list status {
|
|
||||||
type string;
|
|
||||||
config false;
|
|
||||||
description
|
|
||||||
"The status for this entry.";
|
|
||||||
}
|
|
||||||
container preference {
|
|
||||||
leaf-list number {
|
|
||||||
type uint8;
|
|
||||||
description
|
|
||||||
"Defines the perference numbers for the admin.";
|
|
||||||
}
|
|
||||||
description
|
|
||||||
"Preference parameters.";
|
|
||||||
}
|
|
||||||
list skill {
|
|
||||||
key "name";
|
|
||||||
description
|
|
||||||
"Represents one 'sill' resource within one
|
|
||||||
'admin' resource.";
|
|
||||||
leaf name {
|
|
||||||
type string {
|
|
||||||
length "1 .. max";
|
|
||||||
}
|
|
||||||
description
|
|
||||||
"The name of the skill.";
|
|
||||||
}
|
|
||||||
leaf rank {
|
|
||||||
type uint16;
|
|
||||||
description
|
|
||||||
"The rank identifying the rank on
|
|
||||||
the skill.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
container rulebase {
|
|
||||||
description
|
|
||||||
"Rule base configuration";
|
|
||||||
list rule {
|
|
||||||
key "name";
|
|
||||||
description
|
|
||||||
"List of rules for rulebase.";
|
|
||||||
ordered-by user;
|
|
||||||
leaf name {
|
|
||||||
type string {
|
|
||||||
length "1 .. max";
|
|
||||||
}
|
|
||||||
description
|
|
||||||
"The name of the rule.";
|
|
||||||
}
|
|
||||||
leaf match {
|
|
||||||
type string {
|
|
||||||
length "1 .. max";
|
|
||||||
}
|
|
||||||
description
|
|
||||||
"The rules in this rulebase determine what fields will be
|
|
||||||
matched upon before any action is taken on them.";
|
|
||||||
}
|
|
||||||
leaf action {
|
|
||||||
type enumeration {
|
|
||||||
enum forwarding {
|
|
||||||
description
|
|
||||||
"Specify forwarding behavior per rule entry.";
|
|
||||||
}
|
|
||||||
enum logging {
|
|
||||||
description
|
|
||||||
"Specify logging behavior per rule entry.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default "logging";
|
|
||||||
description
|
|
||||||
"Defintion of the action for this rule entry.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
container device-logs {
|
|
||||||
description
|
|
||||||
"Device log configuration";
|
|
||||||
list device-log {
|
|
||||||
description
|
|
||||||
"List of device logs.";
|
|
||||||
config false;
|
|
||||||
leaf device-id {
|
|
||||||
type string;
|
|
||||||
description
|
|
||||||
"The device id of the device log.";
|
|
||||||
}
|
|
||||||
leaf time-received {
|
|
||||||
type yang:date-and-time;
|
|
||||||
description
|
|
||||||
"The timestamp value at the time this
|
|
||||||
log was received.";
|
|
||||||
}
|
|
||||||
leaf time-generated {
|
|
||||||
type yang:date-and-time;
|
|
||||||
description
|
|
||||||
"The timestamp value at the time this
|
|
||||||
log was generated.";
|
|
||||||
}
|
|
||||||
leaf message {
|
|
||||||
type string;
|
|
||||||
description
|
|
||||||
"Message given at start of login session.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
container audit-logs {
|
|
||||||
description
|
|
||||||
"Audit log configuration";
|
|
||||||
list audit-log {
|
|
||||||
key "log-creation";
|
|
||||||
description
|
|
||||||
"List of audit logs.";
|
|
||||||
config false;
|
|
||||||
leaf source-ip {
|
|
||||||
type inet:ip-address;
|
|
||||||
description
|
|
||||||
"The IP address of the targeted object.";
|
|
||||||
}
|
|
||||||
leaf log-creation {
|
|
||||||
type yang:date-and-time;
|
|
||||||
description
|
|
||||||
"The timestamp value at the time this
|
|
||||||
log was created.";
|
|
||||||
}
|
|
||||||
leaf request {
|
|
||||||
type string;
|
|
||||||
description
|
|
||||||
"Request type of audit log.";
|
|
||||||
}
|
|
||||||
leaf outcome {
|
|
||||||
type boolean;
|
|
||||||
default "true";
|
|
||||||
description
|
|
||||||
"Indicate the audit log is retrieved sucessfully or not.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
container prefixes {
|
|
||||||
description
|
|
||||||
"Enclosing container for the list of prefixes in a policy
|
|
||||||
prefix list";
|
|
||||||
list prefix-list {
|
|
||||||
key "ip-prefix masklength-lower masklength-upper";
|
|
||||||
description
|
|
||||||
"List of prefixes in the prefix set";
|
|
||||||
leaf ip-prefix {
|
|
||||||
type inet:ip-prefix;
|
|
||||||
mandatory true;
|
|
||||||
description
|
|
||||||
"The prefix member in CIDR notation -- while the
|
|
||||||
prefix may be either IPv4 or IPv6, most
|
|
||||||
implementations require all members of the prefix set
|
|
||||||
to be the same address family. Mixing address types in
|
|
||||||
the same prefix set is likely to cause an error.";
|
|
||||||
}
|
|
||||||
leaf masklength-lower {
|
|
||||||
type uint8;
|
|
||||||
description
|
|
||||||
"Masklength range lower bound.";
|
|
||||||
}
|
|
||||||
leaf masklength-upper {
|
|
||||||
type uint8 {
|
|
||||||
range "1..128";
|
|
||||||
}
|
|
||||||
must '../masklength-upper >= ../masklength-lower' {
|
|
||||||
error-message "The upper bound should not be lessthan lower bound.";
|
|
||||||
}
|
|
||||||
description
|
|
||||||
"Masklength range upper bound.
|
|
||||||
|
|
||||||
The combination of masklength-lower and masklength-upper
|
|
||||||
define a range for the mask length, or single 'exact'
|
|
||||||
length if masklength-lower and masklenght-upper are equal.
|
|
||||||
|
|
||||||
Example: 10.3.192.0/21 through 10.3.192.0/24 would be
|
|
||||||
expressed as prefix: 10.3.192.0/21,
|
|
||||||
masklength-lower=21,
|
|
||||||
masklength-upper=24
|
|
||||||
|
|
||||||
Example: 10.3.192.0/21 (an exact match) would be
|
|
||||||
expressed as prefix: 10.3.192.0/21,
|
|
||||||
masklength-lower=21,
|
|
||||||
masklength-upper=21";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
|
|
||||||
299
test/example_social.sh
Executable file
299
test/example_social.sh
Executable file
|
|
@ -0,0 +1,299 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Example-social from draft-netconf-list-pagination-00.txt appendix A.1
|
||||||
|
# Assumes variable fexample is set to name of yang file
|
||||||
|
# Note inverted pattern is commented
|
||||||
|
|
||||||
|
cat <<EOF > $fexample
|
||||||
|
module example-social {
|
||||||
|
yang-version 1.1;
|
||||||
|
namespace "http://example.com/ns/example-social";
|
||||||
|
prefix es;
|
||||||
|
|
||||||
|
import ietf-yang-types {
|
||||||
|
prefix yang;
|
||||||
|
reference
|
||||||
|
"RFC 6991: Common YANG Data Types";
|
||||||
|
}
|
||||||
|
import ietf-inet-types {
|
||||||
|
prefix inet;
|
||||||
|
reference
|
||||||
|
"RFC 6991: Common YANG Data Types";
|
||||||
|
}
|
||||||
|
|
||||||
|
import iana-crypt-hash {
|
||||||
|
prefix ianach;
|
||||||
|
reference
|
||||||
|
"RFC 7317: A YANG Data Model for System Management";
|
||||||
|
}
|
||||||
|
|
||||||
|
organization "Example, Inc.";
|
||||||
|
contact "support@example.com";
|
||||||
|
description "Example Social Data Model.";
|
||||||
|
|
||||||
|
revision 2021-07-21 { /* clixon edit */
|
||||||
|
description
|
||||||
|
"Initial version.";
|
||||||
|
reference
|
||||||
|
"RFC XXXX: Example social module.";
|
||||||
|
}
|
||||||
|
|
||||||
|
container members {
|
||||||
|
description
|
||||||
|
"Container for list of members.";
|
||||||
|
list member {
|
||||||
|
key "member-id";
|
||||||
|
description
|
||||||
|
"List of members.";
|
||||||
|
|
||||||
|
leaf member-id {
|
||||||
|
type string {
|
||||||
|
length "1..80";
|
||||||
|
/*
|
||||||
|
pattern '.*[\n].*' {
|
||||||
|
modifier invert-match;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"The member's identifier.";
|
||||||
|
}
|
||||||
|
|
||||||
|
leaf email-address {
|
||||||
|
type inet:email-address;
|
||||||
|
mandatory true;
|
||||||
|
description
|
||||||
|
"The member's email address.";
|
||||||
|
}
|
||||||
|
leaf password {
|
||||||
|
type ianach:crypt-hash;
|
||||||
|
mandatory true;
|
||||||
|
description
|
||||||
|
"The member's hashed-password.";
|
||||||
|
}
|
||||||
|
|
||||||
|
leaf avatar {
|
||||||
|
type binary;
|
||||||
|
description
|
||||||
|
"An binary image file.";
|
||||||
|
}
|
||||||
|
|
||||||
|
leaf tagline {
|
||||||
|
type string {
|
||||||
|
length "1..80";
|
||||||
|
/*
|
||||||
|
pattern '.*[\n].*' {
|
||||||
|
modifier invert-match;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"The member's tagline.";
|
||||||
|
}
|
||||||
|
|
||||||
|
container privacy-settings {
|
||||||
|
leaf hide-network {
|
||||||
|
type boolean;
|
||||||
|
description
|
||||||
|
"Hide who you follow and who follows you.";
|
||||||
|
}
|
||||||
|
leaf post-visibility {
|
||||||
|
type enumeration {
|
||||||
|
enum public {
|
||||||
|
description
|
||||||
|
"Posts are public.";
|
||||||
|
}
|
||||||
|
enum unlisted {
|
||||||
|
description
|
||||||
|
"Posts are unlisted, though visable to all.";
|
||||||
|
}
|
||||||
|
enum followers-only {
|
||||||
|
description
|
||||||
|
"Posts only visible to followers.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default public;
|
||||||
|
description
|
||||||
|
"The post privacy setting.";
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"Preferences for the member.";
|
||||||
|
}
|
||||||
|
|
||||||
|
leaf-list following {
|
||||||
|
type leafref {
|
||||||
|
path "/members/member/member-id";
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"Other members this members is following.";
|
||||||
|
}
|
||||||
|
|
||||||
|
container posts {
|
||||||
|
description
|
||||||
|
"The member's posts.";
|
||||||
|
list post {
|
||||||
|
key timestamp;
|
||||||
|
leaf timestamp {
|
||||||
|
type yang:date-and-time;
|
||||||
|
description
|
||||||
|
"The timestamp for the member's post.";
|
||||||
|
}
|
||||||
|
leaf title {
|
||||||
|
type string {
|
||||||
|
length "1..80";
|
||||||
|
/*
|
||||||
|
pattern '.*[\n].*' {
|
||||||
|
modifier invert-match;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"A one-line title.";
|
||||||
|
}
|
||||||
|
leaf body {
|
||||||
|
type string;
|
||||||
|
mandatory true;
|
||||||
|
description
|
||||||
|
"The body of the post.";
|
||||||
|
}
|
||||||
|
description
|
||||||
|
"A list of posts.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
container favorites {
|
||||||
|
description
|
||||||
|
"The member's favorites.";
|
||||||
|
leaf-list uint8-numbers {
|
||||||
|
type uint8;
|
||||||
|
ordered-by user;
|
||||||
|
description
|
||||||
|
"The member's favorite uint8 numbers.";
|
||||||
|
}
|
||||||
|
leaf-list uint64-numbers {
|
||||||
|
type uint64;
|
||||||
|
ordered-by user;
|
||||||
|
description
|
||||||
|
"The member's favorite uint64 numbers.";
|
||||||
|
}
|
||||||
|
leaf-list int8-numbers {
|
||||||
|
type int8;
|
||||||
|
ordered-by user;
|
||||||
|
description
|
||||||
|
"The member's favorite int8 numbers.";
|
||||||
|
}
|
||||||
|
leaf-list int64-numbers {
|
||||||
|
type int64;
|
||||||
|
ordered-by user;
|
||||||
|
description
|
||||||
|
"The member's favorite uint64 numbers.";
|
||||||
|
}
|
||||||
|
leaf-list decimal64-numbers {
|
||||||
|
type decimal64 {
|
||||||
|
fraction-digits 5;
|
||||||
|
}
|
||||||
|
ordered-by user;
|
||||||
|
description
|
||||||
|
"The member's favorite decimal64 numbers.";
|
||||||
|
}
|
||||||
|
leaf-list bits {
|
||||||
|
type bits {
|
||||||
|
bit zero {
|
||||||
|
position 0;
|
||||||
|
description "zero";
|
||||||
|
}
|
||||||
|
bit one {
|
||||||
|
position 1;
|
||||||
|
description "one";
|
||||||
|
}
|
||||||
|
bit two {
|
||||||
|
position 2;
|
||||||
|
description "two";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ordered-by user;
|
||||||
|
description
|
||||||
|
"The member's favorite bits.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
container stats {
|
||||||
|
config false;
|
||||||
|
description
|
||||||
|
"Operational state members values.";
|
||||||
|
leaf joined {
|
||||||
|
type yang:date-and-time;
|
||||||
|
mandatory true;
|
||||||
|
description
|
||||||
|
"Timestamp when member joined.";
|
||||||
|
}
|
||||||
|
leaf membership-level {
|
||||||
|
type enumeration {
|
||||||
|
enum admin {
|
||||||
|
description
|
||||||
|
"Site administrator.";
|
||||||
|
}
|
||||||
|
enum standard {
|
||||||
|
description
|
||||||
|
"Standard membership level.";
|
||||||
|
}
|
||||||
|
enum pro {
|
||||||
|
description
|
||||||
|
"Professional membership level.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mandatory true;
|
||||||
|
description
|
||||||
|
"The membership level for this member.";
|
||||||
|
}
|
||||||
|
leaf last-activity {
|
||||||
|
type yang:date-and-time;
|
||||||
|
description
|
||||||
|
"Timestamp of member's last activity.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
container audit-logs {
|
||||||
|
config false;
|
||||||
|
description
|
||||||
|
"Audit log configuration";
|
||||||
|
list audit-log {
|
||||||
|
description
|
||||||
|
"List of audit logs.";
|
||||||
|
leaf timestamp {
|
||||||
|
type yang:date-and-time;
|
||||||
|
mandatory true;
|
||||||
|
description
|
||||||
|
"The timestamp for the event.";
|
||||||
|
}
|
||||||
|
leaf member-id {
|
||||||
|
type string;
|
||||||
|
mandatory true;
|
||||||
|
description
|
||||||
|
"The 'member-id' of the member.";
|
||||||
|
}
|
||||||
|
leaf source-ip {
|
||||||
|
type inet:ip-address;
|
||||||
|
mandatory true;
|
||||||
|
description
|
||||||
|
"The apparent IP address the member used.";
|
||||||
|
}
|
||||||
|
leaf request {
|
||||||
|
type string;
|
||||||
|
mandatory true;
|
||||||
|
description
|
||||||
|
"The member's request.";
|
||||||
|
}
|
||||||
|
leaf outcome {
|
||||||
|
type boolean;
|
||||||
|
mandatory true;
|
||||||
|
description
|
||||||
|
"Indicate if request was permitted.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,15 +1,21 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Restconf RFC8040 Appendix A and B "jukebox" example
|
# List pagination tests according to draft-wwlh-netconf-list-pagination-00
|
||||||
# For pagination / scaling I-D activity
|
# Backlog items:
|
||||||
|
# 1. "remaining" annotation RFC 7952
|
||||||
|
# 2. pattern '.*[\n].*' { modifier invert-match;
|
||||||
|
|
||||||
# Magic line must be first in script (see README.md)
|
# Magic line must be first in script (see README.md)
|
||||||
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||||
|
|
||||||
APPNAME=example
|
APPNAME=example
|
||||||
|
|
||||||
cfg=$dir/conf.xml
|
cfg=$dir/conf.xml
|
||||||
fexample=$dir/example-module.yang
|
fexample=$dir/example-social.yang
|
||||||
fstate=$dir/mystate.xml
|
fstate=$dir/mystate.xml
|
||||||
|
|
||||||
|
# Common example-module spec (fexample must be set)
|
||||||
|
. ./example_social.sh
|
||||||
|
|
||||||
# Define default restconfig config: RESTCONFIG
|
# Define default restconfig config: RESTCONFIG
|
||||||
RESTCONFIG=$(restconf_config none false)
|
RESTCONFIG=$(restconf_config none false)
|
||||||
|
|
||||||
|
|
@ -26,265 +32,230 @@ cat <<EOF > $cfg
|
||||||
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
||||||
<CLICON_BACKEND_PIDFILE>$dir/restconf.pidfile</CLICON_BACKEND_PIDFILE>
|
<CLICON_BACKEND_PIDFILE>$dir/restconf.pidfile</CLICON_BACKEND_PIDFILE>
|
||||||
<CLICON_XMLDB_DIR>$dir</CLICON_XMLDB_DIR>
|
<CLICON_XMLDB_DIR>$dir</CLICON_XMLDB_DIR>
|
||||||
|
<CLICON_XMLDB_FORMAT>json</CLICON_XMLDB_FORMAT>
|
||||||
<CLICON_STREAM_DISCOVERY_RFC8040>true</CLICON_STREAM_DISCOVERY_RFC8040>
|
<CLICON_STREAM_DISCOVERY_RFC8040>true</CLICON_STREAM_DISCOVERY_RFC8040>
|
||||||
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
||||||
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||||
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||||
|
<CLICON_VALIDATE_STATE_XML>true</CLICON_VALIDATE_STATE_XML>
|
||||||
$RESTCONFIG
|
$RESTCONFIG
|
||||||
</clixon-config>
|
</clixon-config>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# See draft-wwlh-netconf-list-pagination-00 A.2 (except stats and audit-log)
|
||||||
cat <<'EOF' > $dir/startup_db
|
cat <<'EOF' > $dir/startup_db
|
||||||
<config>
|
{"config":
|
||||||
<admins xmlns="http://example.com/ns/example-module">
|
{
|
||||||
<admin>
|
"example-social:members": {
|
||||||
<name>Alice</name>
|
"member": [
|
||||||
<access>permit</access>
|
{
|
||||||
<email-address>alice@example.com</email-address>
|
"member-id": "alice",
|
||||||
<password>$0$1543</password>
|
"email-address": "alice@example.com",
|
||||||
<preference>
|
"password": "$0$1543",
|
||||||
<number>1</number>
|
"avatar": "BASE64VALUE=",
|
||||||
<number>2</number>
|
"tagline": "Every day is a new day",
|
||||||
</preference>
|
"privacy-settings": {
|
||||||
<skill>
|
"hide-network": "false",
|
||||||
<name>Customer Service</name>
|
"post-visibility": "public"
|
||||||
<rank>99</rank>
|
},
|
||||||
</skill>
|
"following": ["bob", "eric", "lin"],
|
||||||
<skill>
|
"posts": {
|
||||||
<name>Problem Solving</name>
|
"post": [
|
||||||
<rank>90</rank>
|
{
|
||||||
</skill>
|
"timestamp": "2020-07-08T13:12:45Z",
|
||||||
</admin>
|
"title": "My first post",
|
||||||
<admin>
|
"body": "Hiya all!"
|
||||||
<name>Bob</name>
|
},
|
||||||
<access>limited</access>
|
{
|
||||||
<email-address>bob@example.com</email-address>
|
"timestamp": "2020-07-09T01:32:23Z",
|
||||||
<password>$0$2789</password>
|
"title": "Sleepy...",
|
||||||
<preference>
|
"body": "Catch y'all tomorrow."
|
||||||
<number>2</number>
|
}
|
||||||
<number>3</number>
|
]
|
||||||
</preference>
|
},
|
||||||
<skill>
|
"favorites": {
|
||||||
<name>Conflict Resolution</name>
|
"uint8-numbers": [17, 13, 11, 7, 5, 3],
|
||||||
<rank>93</rank>
|
"int8-numbers": [-5, -3, -1, 1, 3, 5]
|
||||||
</skill>
|
}
|
||||||
<skill>
|
},
|
||||||
<name>Management</name>
|
{
|
||||||
<rank>23</rank>
|
"member-id": "bob",
|
||||||
</skill>
|
"email-address": "bob@example.com",
|
||||||
<skill>
|
"password": "$0$1543",
|
||||||
<name>Organization</name>
|
"avatar": "BASE64VALUE=",
|
||||||
<rank>44</rank>
|
"tagline": "Here and now, like never before.",
|
||||||
</skill>
|
"posts": {
|
||||||
<skill>
|
"post": [
|
||||||
<name>Problem Solving</name>
|
{
|
||||||
<rank>98</rank>
|
"timestamp": "2020-08-14T03:32:25Z",
|
||||||
</skill>
|
"body": "Just got in."
|
||||||
</admin>
|
},
|
||||||
<admin>
|
{
|
||||||
<name>Joe</name>
|
"timestamp": "2020-08-14T03:33:55Z",
|
||||||
<access>permit</access>
|
"body": "What's new?"
|
||||||
<email-address>joe@example.com</email-address>
|
},
|
||||||
<password>$0$6523</password>
|
{
|
||||||
<preference>
|
"timestamp": "2020-08-14T03:34:30Z",
|
||||||
<number>1</number>
|
"body": "I'm bored..."
|
||||||
<number>4</number>
|
}
|
||||||
</preference>
|
]
|
||||||
<skill>
|
},
|
||||||
<name>Management</name>
|
"favorites": {
|
||||||
<rank>96</rank>
|
"decimal64-numbers": ["3.14159", "2.71828"]
|
||||||
</skill>
|
}
|
||||||
<skill>
|
},
|
||||||
<name>Collaboration</name>
|
{
|
||||||
<rank>92</rank>
|
"member-id": "eric",
|
||||||
</skill>
|
"email-address": "eric@example.com",
|
||||||
</admin>
|
"password": "$0$1543",
|
||||||
<admin>
|
"avatar": "BASE64VALUE=",
|
||||||
<name>Frank</name>
|
"tagline": "Go to bed with dreams; wake up with a purpose.",
|
||||||
<access>deny</access>
|
"following": ["alice"],
|
||||||
<email-address>frank@example.com</email-address>
|
"posts": {
|
||||||
<password>$0$4030</password>
|
"post": [
|
||||||
<preference>
|
{
|
||||||
<number>5</number>
|
"timestamp": "2020-09-17T18:02:04Z",
|
||||||
<number>9</number>
|
"title": "Son, brother, husband, father",
|
||||||
</preference>
|
"body": "What's your story?"
|
||||||
<skill>
|
}
|
||||||
<name>Organization</name>
|
]
|
||||||
<rank>90</rank>
|
},
|
||||||
</skill>
|
"favorites": {
|
||||||
<skill>
|
"bits": ["two", "one", "zero"]
|
||||||
<name>Negotiation</name>
|
}
|
||||||
<rank>80</rank>
|
},
|
||||||
</skill>
|
{
|
||||||
</admin>
|
"member-id": "lin",
|
||||||
<admin>
|
"email-address": "lin@example.com",
|
||||||
<name>Tom</name>
|
"password": "$0$1543",
|
||||||
<access>permit</access>
|
"privacy-settings": {
|
||||||
<email-address>tom@example.com</email-address>
|
"hide-network": "true",
|
||||||
<password>$0$2376</password>
|
"post-visibility": "followers-only"
|
||||||
<preference>
|
},
|
||||||
<number>2</number>
|
"following": ["joe", "eric", "alice"]
|
||||||
<number>5</number>
|
},
|
||||||
</preference>
|
{
|
||||||
<skill>
|
"member-id": "joe",
|
||||||
<name>Adaptability.</name>
|
"email-address": "joe@example.com",
|
||||||
<rank>98</rank>
|
"password": "$0$1543",
|
||||||
</skill>
|
"avatar": "BASE64VALUE=",
|
||||||
<skill>
|
"tagline": "Greatness is measured by courage and heart.",
|
||||||
<name>Active Listening</name>
|
"privacy-settings": {
|
||||||
<rank>85</rank>
|
"post-visibility": "unlisted"
|
||||||
</skill>
|
},
|
||||||
</admin>
|
"following": ["bob"],
|
||||||
</admins>
|
"posts": {
|
||||||
<rulebase xmlns="http://example.com/ns/example-module">
|
"post": [
|
||||||
<rule>
|
{
|
||||||
<name>SvrA-http</name>
|
"timestamp": "2020-10-17T18:02:04Z",
|
||||||
<match>92.0.2.0/24</match>
|
"body": "What's your status?"
|
||||||
<action>forwarding</action>
|
}
|
||||||
</rule>
|
]
|
||||||
<rule>
|
}
|
||||||
<name>SvrA-ftp</name>
|
}
|
||||||
<match>203.0.113.1/32</match>
|
]
|
||||||
<action>forwarding</action>
|
}
|
||||||
</rule>
|
}
|
||||||
<rule>
|
}
|
||||||
<name>p2p</name>
|
|
||||||
<match>p2p</match>
|
|
||||||
<action>logging</action>
|
|
||||||
</rule>
|
|
||||||
<rule>
|
|
||||||
<name>any</name>
|
|
||||||
<match>any</match>
|
|
||||||
<action>logging</action>
|
|
||||||
</rule>
|
|
||||||
<rule>
|
|
||||||
<name>SvrA-tcp</name>
|
|
||||||
<match>80</match>
|
|
||||||
<action>forwarding</action>
|
|
||||||
</rule>
|
|
||||||
</rulebase>
|
|
||||||
<prefixes xmlns="http://example.com/ns/example-module">
|
|
||||||
<prefix-list>
|
|
||||||
<ip-prefix>10.0.0.0/8</ip-prefix>
|
|
||||||
<masklength-lower>17</masklength-lower>
|
|
||||||
<masklength-upper>18</masklength-upper>
|
|
||||||
</prefix-list>
|
|
||||||
<prefix-list>
|
|
||||||
<ip-prefix>2000:1::/48</ip-prefix>
|
|
||||||
<masklength-lower>48</masklength-lower>
|
|
||||||
<masklength-upper>48</masklength-upper>
|
|
||||||
</prefix-list>
|
|
||||||
<prefix-list>
|
|
||||||
<ip-prefix>2000:2::/48</ip-prefix>
|
|
||||||
<masklength-lower>48</masklength-lower>
|
|
||||||
<masklength-upper>48</masklength-upper>
|
|
||||||
</prefix-list>
|
|
||||||
<prefix-list>
|
|
||||||
<ip-prefix>2000:3::/48</ip-prefix>
|
|
||||||
<masklength-lower>16</masklength-lower>
|
|
||||||
<masklength-upper>16</masklength-upper>
|
|
||||||
</prefix-list>
|
|
||||||
<prefix-list>
|
|
||||||
<ip-prefix>::/0</ip-prefix>
|
|
||||||
<masklength-lower>0</masklength-lower>
|
|
||||||
<masklength-upper>128</masklength-upper>
|
|
||||||
</prefix-list>
|
|
||||||
</prefixes>
|
|
||||||
</config>
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# See draft-wwlh-netconf-list-pagination-00 A.2 (only stats and audit-log)
|
||||||
cat<<EOF > $fstate
|
cat<<EOF > $fstate
|
||||||
<admins xmlns="http://example.com/ns/example-module">
|
<members xmlns="http://example.com/ns/example-social">
|
||||||
<admin>
|
<member>
|
||||||
<name>Alice</name>
|
<member-id>alice</member-id>
|
||||||
<status>Available</status>
|
<stats>
|
||||||
</admin>
|
<joined>2020-07-08T12:38:32Z</joined>
|
||||||
<admin>
|
<membership-level>admin</membership-level>
|
||||||
<name>Bob</name>
|
<last-activity>2021-04-01T02:51:11Z</last-activity>
|
||||||
<status>Busy</status>
|
</stats>
|
||||||
</admin>
|
</member>
|
||||||
<admin>
|
<member>
|
||||||
<name>Joe</name>
|
<member-id>bob</member-id>
|
||||||
<status>Do Not Disturb</status>
|
<stats>
|
||||||
</admin>
|
<joined>2020-08-14T03:30:00Z</joined>
|
||||||
<admin>
|
<membership-level>standard</membership-level>
|
||||||
<name>Frank</name>
|
<last-activity>2020-08-14T03:34:30Z</last-activity>
|
||||||
<status>Offline</status>
|
</stats>
|
||||||
</admin>
|
</member>
|
||||||
<admin>
|
<member>
|
||||||
<name>Tom</name>
|
<member-id>eric</member-id>
|
||||||
<status>Do Not Disturb</status>
|
<stats>
|
||||||
</admin>
|
<joined>2020-09-17T19:38:32Z</joined>
|
||||||
</admins>
|
<membership-level>pro</membership-level>
|
||||||
<device-logs xmlns="http://example.com/ns/example-module">
|
<last-activity>2020-09-17T18:02:04Z</last-activity>
|
||||||
<device-log>
|
</stats>
|
||||||
<device-id>Cloud-IoT-Device-A</device-id>
|
</member>
|
||||||
<time-received>2020-07-08T12:38:32Z</time-received>
|
<member>
|
||||||
<time-generated>2020-07-08T12:37:12Z</time-generated>
|
<member-id>lin</member-id>
|
||||||
<message>Upload contains 6 datapoints</message>
|
<stats>
|
||||||
</device-log>
|
<joined>2020-07-09T12:38:32Z</joined>
|
||||||
<device-log>
|
<membership-level>standard</membership-level>
|
||||||
<device-id>Cloud-IoT-Device-B</device-id>
|
<last-activity>2021-04-01T02:51:11Z</last-activity>
|
||||||
<time-received>2020-07-08T16:20:54Z</time-received>
|
</stats>
|
||||||
<time-generated>2020-07-08T16:20:14Z</time-generated>
|
</member>
|
||||||
<message>Upload successful</message>
|
<member>
|
||||||
</device-log>
|
<member-id>joe</member-id>
|
||||||
<device-log>
|
<stats>
|
||||||
<device-id>Cloud-IoT-Device-C</device-id>
|
<joined>2020-10-08T12:38:32Z</joined>
|
||||||
<time-received>2020-07-08T17:30:34Z</time-received>
|
<membership-level>pro</membership-level>
|
||||||
<time-generated>2020-07-08T17:30:12Z</time-generated>
|
<last-activity>2021-04-01T02:51:11Z</last-activity>
|
||||||
<message>Receive a configuration update</message>
|
</stats>
|
||||||
</device-log>
|
</member>
|
||||||
<device-log>
|
</members>
|
||||||
<device-id>Cloud-IoT-Device-D</device-id>
|
<audit-logs xmlns="http://example.com/ns/example-social">
|
||||||
<time-received>2020-07-08T18:40:13Z</time-received>
|
|
||||||
<time-generated>2020-07-08T18:40:00Z</time-generated>
|
|
||||||
<message>Keep-alive ping sent to server</message>
|
|
||||||
</device-log>
|
|
||||||
<device-log>
|
|
||||||
<device-id>Cloud-IoT-Device-E</device-id>
|
|
||||||
<time-received>2020-07-08T19:48:34Z</time-received>
|
|
||||||
<time-generated>2020-07-08T19:48:00Z</time-generated>
|
|
||||||
<message>Uploading data to DataPoint</message>
|
|
||||||
</device-log>
|
|
||||||
</device-logs>
|
|
||||||
<audit-logs xmlns="http://example.com/ns/example-module">
|
|
||||||
<audit-log>
|
<audit-log>
|
||||||
|
<timestamp>": "2020-10-11T06:47:59Z",</timestamp>
|
||||||
|
<member-id>alice</member-id>
|
||||||
<source-ip>192.168.0.92</source-ip>
|
<source-ip>192.168.0.92</source-ip>
|
||||||
<log-creation>2020-11-01T06:47:59Z</log-creation>
|
<request>POST /groups/group/2043</request>
|
||||||
<request>User-logged-out</request>
|
|
||||||
<outcome>true</outcome>
|
<outcome>true</outcome>
|
||||||
</audit-log>
|
</audit-log>
|
||||||
<audit-log>
|
<audit-log>
|
||||||
<source-ip>192.168.0.92</source-ip>
|
<timestamp>2020-11-01T15:22:01Z</timestamp>
|
||||||
<log-creation>2020-11-01T06:49:03Z</log-creation>
|
<member-id>bob</member-id>
|
||||||
<request>User-logged-in</request>
|
<source-ip>192.168.2.16</source-ip>
|
||||||
<outcome>true</outcome>
|
<request>POST /groups/group/123</request>
|
||||||
</audit-log>
|
|
||||||
<audit-log>
|
|
||||||
<source-ip>192.168.0.92</source-ip>
|
|
||||||
<log-creation>2020-11-01T06:51:34Z</log-creation>
|
|
||||||
<request>Patron-card-viewed</request>
|
|
||||||
<outcome>false</outcome>
|
<outcome>false</outcome>
|
||||||
</audit-log>
|
</audit-log>
|
||||||
<audit-log>
|
<audit-log>
|
||||||
<source-ip>192.168.0.92</source-ip>
|
<timestamp>2020-12-12T21:00:28Z</timestamp>
|
||||||
<log-creation>2020-11-01T06:53:01Z</log-creation>
|
<member-id>eric</member-id>
|
||||||
<request>User-logged-out</request>
|
<source-ip>192.168.254.1</source-ip>
|
||||||
|
<request>POST /groups/group/10</request>
|
||||||
<outcome>true</outcome>
|
<outcome>true</outcome>
|
||||||
</audit-log>
|
</audit-log>
|
||||||
<audit-log>
|
<audit-log>
|
||||||
|
<timestamp>2021-01-03T06:47:59Z</timestamp>
|
||||||
|
<member-id>alice</member-id>
|
||||||
<source-ip>192.168.0.92</source-ip>
|
<source-ip>192.168.0.92</source-ip>
|
||||||
<log-creation>2020-11-01T06:56:22Z</log-creation>
|
<request>POST /groups/group/333</request>
|
||||||
<request>User-logged-in</request>
|
<outcome>true</outcome>
|
||||||
<outcome>false</outcome>
|
|
||||||
</audit-log>
|
</audit-log>
|
||||||
</audit-logs>
|
<audit-log>
|
||||||
|
<timestamp>2021-01-21T10:00:00Z</timestamp>
|
||||||
|
<member-id>bob</member-id>
|
||||||
|
<source-ip>192.168.2.16</source-ip>
|
||||||
|
<request>POST /groups/group/42</request>
|
||||||
|
<outcome>true</outcome>
|
||||||
|
</audit-log>
|
||||||
|
<audit-log>
|
||||||
|
<timestamp>2020-02-07T09:06:21Z</timestamp>
|
||||||
|
<member-id>alice</member-id>
|
||||||
|
<source-ip>192.168.0.92</source-ip>
|
||||||
|
<request>POST /groups/group/1202</request>
|
||||||
|
<outcome>true</outcome>
|
||||||
|
</audit-log>
|
||||||
|
<audit-log>
|
||||||
|
<timestamp>2020-02-28T02:48:11Z</timestamp>
|
||||||
|
<member-id>bob</member-id>
|
||||||
|
<source-ip>192.168.2.16</source-ip>
|
||||||
|
<request>POST /groups/group/345</request>
|
||||||
|
<outcome>true</outcome>
|
||||||
|
</audit-log>
|
||||||
|
</audit-logs>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Common example-module spec (fexample must be set)
|
|
||||||
. ./example_module.sh
|
|
||||||
|
|
||||||
new "test params: -f $cfg -s startup -- -sS $fstate"
|
new "test params: -f $cfg -s startup -- -sS $fstate"
|
||||||
|
|
||||||
if [ $BE -ne 0 ]; then
|
if [ $BE -ne 0 ]; then
|
||||||
|
|
@ -295,7 +266,7 @@ if [ $BE -ne 0 ]; then
|
||||||
fi
|
fi
|
||||||
sudo pkill -f clixon_backend # to be sure
|
sudo pkill -f clixon_backend # to be sure
|
||||||
|
|
||||||
new "start backend -s startup -f $cfg -- -sS $mystate"
|
new "start backend -s startup -f $cfg -- -sS $fstate"
|
||||||
start_backend -s startup -f $cfg -- -sS $fstate
|
start_backend -s startup -f $cfg -- -sS $fstate
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
@ -313,18 +284,24 @@ fi
|
||||||
new "wait restconf"
|
new "wait restconf"
|
||||||
wait_restconf
|
wait_restconf
|
||||||
|
|
||||||
# draft-wwlh-netconf-list-pagination-nc-00.txt
|
new "A.3.1.1. 'limit=1' NETCONF"
|
||||||
new "C.1. 'count' Parameter NETCONF"
|
# XXX: augment GET instead, not RPC
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get-pageable-list xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-list-pagination\"><datastore xmlns:ds=\"urn:ietf:params:xml:ns:yang:ietf-datastores\">ds:running</datastore><list-target xmlns:exm=\"http://example.com/ns/example-module\">/exm:admins/exm:admin[exm:name='Bob']/exm:skill</list-target><count>2</count></get-pageable-list></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><pageable-list xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-list-pagination\"><skill xmlns=\"http://example.com/ns/example-module\"><name>Conflict Resolution</name><rank>93</rank></skill><skill xmlns=\"http://example.com/ns/example-module\"><name>Management</name><rank>23</rank></skill></pageable-list></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get-pagable-list xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-list-pagination\"><datastore xmlns:ds=\"urn:ietf:params:xml:ns:yang:ietf-datastores\">ds:running</datastore><list-target xmlns:es=\"http://example.com/ns/example-social\">/es:members/es:member[es:member-id='alice']/es:favorites/es:uint8-numbers</list-target><limit>1</limit></get-pagable-list></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><pageable-list xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-list-pagination\"><uint8-numbers xmlns=\"http://example.com/ns/example-social\" lpg:remaining=\"5\" xmlns:lpg=\"urn:ietf:params:xml:ns:yang:ietf-list-pagination\">17</uint8-numbers></pageable-list></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
#new "A.3.1.1. 'limit' Parameter RESTCONF"
|
||||||
|
#expectpart "$(curl $CURLOPTS -X GET -H "Accept: application/yang.collection+xml" $RCPROTO://localhost/restconf/data/ietf-netconf-list-pagination:get-pagable-list -d "<get-pagable-list xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-list-pagination\"><datastore xmlns:ds=\"urn:ietf:params:xml:ns:yang:ietf-datastores\">ds:running</datastore><list-target xmlns:es=\"http://example.com/ns/example-social\">/es:members/es:member[es:member-id='alice']/es:favorites/es:uint8-numbers</list-target><limit>1</limit></get-pagable-list>")" 0 "HTTP/$HVER 200" "Content-Type: application/yang-collection+xml" foo
|
||||||
|
|
||||||
|
new "A.3.1.2. 'limit=2' NETCONF"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get-pagable-list xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-list-pagination\"><datastore xmlns:ds=\"urn:ietf:params:xml:ns:yang:ietf-datastores\">ds:running</datastore><list-target xmlns:es=\"http://example.com/ns/example-social\">/es:members/es:member[es:member-id='alice']/es:favorites/es:uint8-numbers</list-target><limit>2</limit></get-pagable-list></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><pageable-list xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-list-pagination\"><uint8-numbers xmlns=\"http://example.com/ns/example-social\" lpg:remaining=\"4\" xmlns:lpg=\"urn:ietf:params:xml:ns:yang:ietf-list-pagination\">17</uint8-numbers><uint8-numbers xmlns=\"http://example.com/ns/example-social\">13</uint8-numbers></pageable-list></rpc-reply>]]>]]>$"
|
||||||
|
exit
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
new "C.2. 'skip' Parameter NETCONF"
|
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get-pageable-list xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-list-pagination\"><datastore xmlns:ds=\"urn:ietf:params:xml:ns:yang:ietf-datastores\">ds:running</datastore><list-target xmlns:exm=\"http://example.com/ns/example-module\">/exm:admins/exm:admin[exm:name='Bob']/exm:skill</list-target><count>2</count><skip>2</skip></get-pageable-list></rpc>]]>]]>" "<rpc-reply $DEFAULTNS><pageable-list xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-list-pagination\"><skill xmlns=\"http://example.com/ns/example-module\"><name>Organization</name><rank>44</rank></skill><skill xmlns=\"http://example.com/ns/example-module\"><name>Problem Solving</name><rank>98</rank></skill></pageable-list></rpc-reply>]]>]]>$"
|
|
||||||
|
|
||||||
# CLI
|
# CLI
|
||||||
# XXX This relies on a very specific clispec command: need a more generic test
|
# XXX This relies on a very specific clispec command: need a more generic test
|
||||||
new "cli show"
|
#new "cli show"
|
||||||
echo "$clixon_cli -1 -f $cfg -l o show pagination"
|
#expectpart "$($clixon_cli -1 -f $cfg -l o show pagination)" 0 "<skill xmlns=\"http://example.com/ns/example-module\">" "<name>Conflict Resolution</name>" "<rank>93</rank>" "<name>Management</name>" "<rank>23</rank>" --not-- "<name>Organization</name>" "<rank>44</rank></skill>"
|
||||||
expectpart "$($clixon_cli -1 -f $cfg -l o show pagination)" 0 "<skill xmlns=\"http://example.com/ns/example-module\">" "<name>Conflict Resolution</name>" "<rank>93</rank>" "<name>Management</name>" "<rank>23</rank>" --not-- "<name>Organization</name>" "<rank>44</rank></skill>"
|
|
||||||
|
|
||||||
# draft-wwlh-netconf-list-pagination-rc-00.txt
|
# draft-wwlh-netconf-list-pagination-rc-00.txt
|
||||||
#new "A.1. 'count' Parameter RESTCONF"
|
#new "A.1. 'count' Parameter RESTCONF"
|
||||||
|
|
|
||||||
|
|
@ -204,7 +204,10 @@ module clixon-config {
|
||||||
"Datastore format.";
|
"Datastore format.";
|
||||||
type enumeration{
|
type enumeration{
|
||||||
enum xml{
|
enum xml{
|
||||||
description "Save and load xmldb as XML";
|
description
|
||||||
|
"Save and load xmldb as XML
|
||||||
|
More specifically, such a file looks like: <config>...</config> provided
|
||||||
|
DATASTORE_TOP_SYMBOL is 'config'";
|
||||||
}
|
}
|
||||||
enum json{
|
enum json{
|
||||||
description "Save and load xmldb as JSON";
|
description "Save and load xmldb as JSON";
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,16 @@ module ietf-netconf-list-pagination {
|
||||||
namespace "urn:ietf:params:xml:ns:yang:ietf-netconf-list-pagination";
|
namespace "urn:ietf:params:xml:ns:yang:ietf-netconf-list-pagination";
|
||||||
prefix ycoll;
|
prefix ycoll;
|
||||||
|
|
||||||
|
import ietf-netconf {
|
||||||
|
prefix nc;
|
||||||
|
reference
|
||||||
|
"RFC 6241: Network Configuration Protocol (NETCONF)";
|
||||||
|
}
|
||||||
|
import ietf-netconf-with-defaults {
|
||||||
|
prefix ncwd;
|
||||||
|
reference
|
||||||
|
"RFC 6243: With-defaults Capability for NETCONF";
|
||||||
|
}
|
||||||
import ietf-yang-types {
|
import ietf-yang-types {
|
||||||
prefix yang;
|
prefix yang;
|
||||||
reference
|
reference
|
||||||
|
|
@ -20,16 +30,6 @@ module ietf-netconf-list-pagination {
|
||||||
"RFC 8342: Network Management Datastore Architecture
|
"RFC 8342: Network Management Datastore Architecture
|
||||||
(NMDA)";
|
(NMDA)";
|
||||||
}
|
}
|
||||||
import ietf-netconf {
|
|
||||||
prefix nc;
|
|
||||||
reference
|
|
||||||
"RFC 6241: Network Configuration Protocol (NETCONF)";
|
|
||||||
}
|
|
||||||
import ietf-netconf-with-defaults {
|
|
||||||
prefix ncwd;
|
|
||||||
reference
|
|
||||||
"RFC 6243: With-defaults Capability for NETCONF";
|
|
||||||
}
|
|
||||||
|
|
||||||
organization
|
organization
|
||||||
"IETF NETCONF (Network Configuration) Working Group";
|
"IETF NETCONF (Network Configuration) Working Group";
|
||||||
|
|
@ -64,7 +64,6 @@ module ietf-netconf-list-pagination {
|
||||||
|
|
||||||
This version of this YANG module is part of RFC 8526; see
|
This version of this YANG module is part of RFC 8526; see
|
||||||
the RFC itself for full legal notices.";
|
the RFC itself for full legal notices.";
|
||||||
|
|
||||||
revision 2020-10-30 {
|
revision 2020-10-30 {
|
||||||
description
|
description
|
||||||
"Initial revision.";
|
"Initial revision.";
|
||||||
|
|
@ -91,7 +90,7 @@ module ietf-netconf-list-pagination {
|
||||||
Datastore Architecture, Section 3.1.1.2";
|
Datastore Architecture, Section 3.1.1.2";
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc get-pageable-list {
|
rpc get-pagable-list {
|
||||||
description
|
description
|
||||||
"Use enhanced filtering features to retrieve data from a
|
"Use enhanced filtering features to retrieve data from a
|
||||||
specific NMDA datastore. The content returned by get-data
|
specific NMDA datastore. The content returned by get-data
|
||||||
|
|
@ -240,7 +239,7 @@ module ietf-netconf-list-pagination {
|
||||||
mandatory true;
|
mandatory true;
|
||||||
type string;
|
type string;
|
||||||
}
|
}
|
||||||
leaf count {
|
leaf limit {
|
||||||
type union {
|
type union {
|
||||||
type uint32;
|
type uint32;
|
||||||
type string {
|
type string {
|
||||||
|
|
@ -254,7 +253,7 @@ module ietf-netconf-list-pagination {
|
||||||
greater than or equal to 1, or the string 'unbounded'.
|
greater than or equal to 1, or the string 'unbounded'.
|
||||||
The string 'unbounded' is the default value.";
|
The string 'unbounded' is the default value.";
|
||||||
}
|
}
|
||||||
leaf skip {
|
leaf offset {
|
||||||
type union {
|
type union {
|
||||||
type uint32;
|
type uint32;
|
||||||
type string {
|
type string {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue