* Pagination according to new draft

* count/skip -> limit/offset
* ietf-yang-metadata RFC 7952 support, placeholder parsing and extension
This commit is contained in:
Olof hagsand 2021-07-27 21:36:47 +02:00
parent 77bacc93bb
commit 0c7f2043f3
26 changed files with 751 additions and 620 deletions

View file

@ -1256,9 +1256,9 @@ _json_parse(char *str,
/* RFC 7951 Section 4: A namespace-qualified member name MUST be used for all
* members of a top-level JSON object
*/
if (yspec && xml_prefix(x) == NULL
/* && yb != YB_MODULE_NEXT XXX Dont know what this is for */
){
if (yspec && xml_prefix(x) == NULL &&
/* XXX: For top-level config file: */
(yb != YB_NONE || strcmp(xml_name(x),DATASTORE_TOP_SYMBOL)!=0)){
if ((cberr = cbuf_new()) == NULL){
clicon_err(OE_UNIX, errno, "cbuf_new");
goto done;

View file

@ -50,6 +50,7 @@
#include <limits.h>
#include <stdint.h>
#include <syslog.h>
#include <sys/param.h>
/* cligen */
#include <cligen/cligen.h>
@ -72,6 +73,8 @@
#include "clixon_xpath.h"
#include "clixon_yang_module.h"
#include "clixon_yang_parse_lib.h"
#include "clixon_plugin.h"
#include "clixon_netconf_lib.h"
/*! 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;
}
/*! Load generic yang specs, ie ietf netconf yang module and set enabled features
* @param[in] h Clixon handle
* @retval 0 OK
@ -1494,8 +1498,8 @@ netconf_module_features(clicon_handle h)
int
netconf_module_load(clicon_handle h)
{
int retval = -1;
yang_stmt *yspec;
int retval = -1;
yang_stmt *yspec;
yspec = clicon_dbspec_yang(h);
/* Load yang spec */
@ -1530,6 +1534,15 @@ netconf_module_load(clicon_handle h)
/* Load netconf list pagination */
if (yang_spec_parse_module(h, "ietf-netconf-list-pagination", NULL, yspec)< 0)
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
retval = 0;
done:

View file

@ -1403,9 +1403,8 @@ api_path_resolve(clixon_path *cplist,
/*! Resolve instance-id prefix:names to yang statements
* @param[in] cplist Lisp of clixon-path
* @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 0 Fail
* @retval 0 Fail error in xerr
* @retval 1 OK
* @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.
@ -1440,7 +1439,7 @@ instance_id_resolve(clixon_path *cplist,
}
if (yang_keyword_get(yt) == Y_SPEC){
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;
}
}
@ -1857,6 +1856,7 @@ clixon_instance_id_bind(yang_stmt *yt,
* example.
* @param[in] yt Yang statement of top symbol (can be yang-spec if top-level)
* @param[out] cplistp Path parse-tree
* @param[out] xerr Contains error if retval=0
* @param[in] format Format string for xpath syntax
* @retval -1 Error
* @retval 0 Non-fatal failure, yang bind failures, etc,
@ -1865,6 +1865,7 @@ clixon_instance_id_bind(yang_stmt *yt,
int
clixon_instance_id_parse(yang_stmt *yt,
clixon_path **cplistp,
cxobj **xerr,
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 */
if ((ret = instance_id_resolve(cplist, yt)) < 0)
goto done;
if (ret == 0)
if (ret == 0){
if (xerr && netconf_invalid_value_xml(xerr, "application", clicon_err_reason) < 0)
goto done;
goto fail;
}
if (cplistp){
*cplistp = cplist;
cplist = NULL;

View file

@ -159,7 +159,6 @@ plugin_module_struct_set(clicon_handle h,
return 0;
}
/* Access functions */
/*! Get plugin api

View file

@ -887,8 +887,8 @@ clicon_rpc_get(clicon_handle h,
* @param[in] nsc Namespace context for filter
* @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] count Collection/clixon extension
* @param[in] skip Collection/clixon extension
* @param[in] limit Collection/clixon extension
* @param[in] offset Collection/clixon extension
* @param[in] direction Collection/clixon extension
* @param[in] sort 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 */
netconf_content content,
char *depth,
char *count,
char *skip,
char *limit,
char *offset,
char *direction,
char *sort,
char *where,
@ -941,7 +941,7 @@ clicon_rpc_get_pageable_list(clicon_handle h,
cprintf(cb, " xmlns:%s=\"%s\"",
NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
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 */
if ((int)content != -1)
cprintf(cb, " content=\"%s\"", netconf_content_int2str(content));
@ -955,17 +955,17 @@ clicon_rpc_get_pageable_list(clicon_handle h,
goto done;
cprintf(cb, ">%s</list-target>", xpath);
}
if (count)
cprintf(cb, "<count>%s</count>", count);
if (skip)
cprintf(cb, "<skip>%s</skip>", skip);
if (limit)
cprintf(cb, "<limit>%s</limit>", limit);
if (offset)
cprintf(cb, "<offset>%s</offset>", offset);
if (direction)
cprintf(cb, "<direction>%s</direction>", direction);
if (sort)
cprintf(cb, "<sort>%s</sort>", sort);
if (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)
goto done;
if (clicon_rpc_msg(h, msg, &xret) < 0)

View file

@ -736,7 +736,7 @@ xpath_first_localonly(cxobj *xcur,
* If result is not nodeset, return empty nodeset
* @param[in] xcur xml-tree where to search
* @param[in] nsc External XML namespace context, or NULL
* @param[in] xpformat Format string for XPATH syntax
* @param[in] xpformat Format string for XPATH syntax
* @param[out] vec vector of xml-trees. Vector must be free():d after use
* @param[out] veclen returns length of vector in return value
* @retval 0 OK

View file

@ -1604,8 +1604,8 @@ yang_print(FILE *f,
}
/* Log/debug info about top-level (sub)modules no recursion
* @param[in] f File to print to.
* @param[in] yspec Yang spec
* @param[in] dbglevel Debug level
*/
int
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)
goto done;
retval = 0;
done:
if (prefix)

View file

@ -679,3 +679,60 @@ yang_find_module_by_name(yang_stmt *yspec,
return ymod;
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;
}