New clixon-lib@2023-11-01.yang revision with ignore-compare extension

This commit is contained in:
Olof hagsand 2023-10-25 18:09:40 +02:00
parent 62348fc9c7
commit e7313fc9a2
10 changed files with 121 additions and 35 deletions

View file

@ -52,7 +52,14 @@ Developers may need to change their code
* clicon_debug() -> clixon_debug() * clicon_debug() -> clixon_debug()
* clicon_debug_init() -> clixon_debug_init() * clicon_debug_init() -> clixon_debug_init()
* clicon_debug_get() -> clixon_debug_get() * clicon_debug_get() -> clixon_debug_get()
* clicon_debug_xml() -> clixon_debug_xml()
* There are backward compatible macros during a transition period
### Minor features
* New `clixon-lib@2023-11-01.yang` revision
* Added ignore-compare extension
### Corrected Bugs ### Corrected Bugs
* Fixed: [Does clixon cli support autocompletion for leafrefs pointed to another module?](https://github.com/clicon/clixon/issues/455) * Fixed: [Does clixon cli support autocompletion for leafrefs pointed to another module?](https://github.com/clicon/clixon/issues/455)

View file

@ -316,4 +316,9 @@ cxobj *xml_child_index_each(cxobj *xparent, char *name, cxobj *xprev, enum cx
#endif #endif
/* 6.4 backward compatability */
#if 1
#define clicon_debug_xml clixon_debug_xml
#endif
#endif /* _CLIXON_XML_H */ #endif /* _CLIXON_XML_H */

View file

@ -476,6 +476,7 @@ xml_tree_equal(cxobj *x0,
char *b1; char *b1;
cxobj *x0c = NULL; /* x0 child */ cxobj *x0c = NULL; /* x0 child */
cxobj *x1c = NULL; /* x1 child */ cxobj *x1c = NULL; /* x1 child */
int extflag = 0;
/* Traverse x0 and x1 in lock-step */ /* Traverse x0 and x1 in lock-step */
x0c = x1c = NULL; x0c = x1c = NULL;
@ -485,11 +486,30 @@ xml_tree_equal(cxobj *x0,
if (x0c == NULL && x1c == NULL) if (x0c == NULL && x1c == NULL)
goto ok; goto ok;
else if (x0c == NULL){ else if (x0c == NULL){
/* If cl:gnore-compare extension, return equal */
if ((yc1 = xml_spec(x1c)) != NULL){
if (yang_extension_value(yc1, "ignore-compare", CLIXON_LIB_NS, &extflag, NULL) < 0)
goto done;
if (extflag)
goto ok;
}
goto done; goto done;
} }
else if (x1c == NULL){ else if (x1c == NULL){
if ((yc0 = xml_spec(x0c)) != NULL){
if (yang_extension_value(yc0, "ignore-compare", CLIXON_LIB_NS, &extflag, NULL) < 0)
goto done;
if (extflag)
goto ok;
}
goto done; goto done;
} }
if ((yc0 = xml_spec(x0c)) != NULL){
if (yang_extension_value(yc0, "ignore-compare", CLIXON_LIB_NS, &extflag, NULL) < 0)
goto done;
if (extflag)
goto ok;
}
/* Both x0c and x1c exists, check if they are yang-equal. */ /* Both x0c and x1c exists, check if they are yang-equal. */
eq = xml_cmp(x0c, x1c, 0, 0, NULL); eq = xml_cmp(x0c, x1c, 0, 0, NULL);
if (eq < 0){ if (eq < 0){

View file

@ -3798,7 +3798,7 @@ yang_anydata_add(yang_stmt *yp,
* @param[in] name Name of the extension * @param[in] name Name of the extension
* @param[in] ns The namespace of the module where the extension is defined * @param[in] ns The namespace of the module where the extension is defined
* @param[out] exist The extension exists. * @param[out] exist The extension exists.
* @param[out] value clispec operator (hide/none) - direct pointer into yang, dont free * @param[out] value Extension value if any
* @retval 0 OK: Look in exist and value for return value * @retval 0 OK: Look in exist and value for return value
* @retval -1 Error * @retval -1 Error
* This is for extensions with an argument * This is for extensions with an argument

View file

@ -838,7 +838,7 @@ yang_metadata_init(clicon_handle h)
* This function is used where a yang-lib module-set is available to populate * This function is used where a yang-lib module-set is available to populate
* an XML mount-point. * an XML mount-point.
* @param[in] h Clixon handle * @param[in] h Clixon handle
* @param[in] yanglib XML tree on the form <yang-lib>... * @param[in] xyanglib XML tree on the form <yang-lib>...
* @param[in] yspec Will be populated with YANGs, is consumed * @param[in] yspec Will be populated with YANGs, is consumed
* @retval 1 OK * @retval 1 OK
* @retval 0 Parse error * @retval 0 Parse error
@ -848,7 +848,7 @@ yang_metadata_init(clicon_handle h)
*/ */
int int
yang_lib2yspec(clicon_handle h, yang_lib2yspec(clicon_handle h,
cxobj *yanglib, cxobj *xyanglib,
yang_stmt *yspec) yang_stmt *yspec)
{ {
int retval = -1; int retval = -1;
@ -863,7 +863,7 @@ yang_lib2yspec(clicon_handle h,
yang_stmt *yrev; yang_stmt *yrev;
int modmin = 0; int modmin = 0;
if (xpath_vec(yanglib, nsc, "module-set/module", &vec, &veclen) < 0) if (xpath_vec(xyanglib, nsc, "module-set/module", &vec, &veclen) < 0)
goto done; goto done;
for (i=0; i<veclen; i++){ for (i=0; i<veclen; i++){
xi = vec[i]; xi = vec[i];

View file

@ -1129,9 +1129,9 @@ yang_parse_module(clicon_handle h,
if (revision) if (revision)
cprintf(cb, "@%s", revision); cprintf(cb, "@%s", revision);
if (origname) if (origname)
clicon_err(OE_YANG, ENOENT, "No yang files found matching \"%s\" in the list of CLICON_YANG_DIRs when loading %s.yang", cbuf_get(cb), origname); clicon_err(OE_YANG, ENOENT, "Yang \"%s\" not found in the list of CLICON_YANG_DIRs when loading %s.yang", cbuf_get(cb), origname);
else else
clicon_err(OE_YANG, ENOENT, "No yang files found matching \"%s\" in the list of CLICON_YANG_DIRs", cbuf_get(cb)); clicon_err(OE_YANG, ENOENT, "Yang \"%s\" not found in the list of CLICON_YANG_DIRs", cbuf_get(cb));
goto done; goto done;
} }
filename = cbuf_get(fbuf); filename = cbuf_get(fbuf);

View file

@ -76,7 +76,7 @@ DATASTORE_TOP="config"
# clixon yang revisions occuring in tests (see eg yang/clixon/Makefile.in) # clixon yang revisions occuring in tests (see eg yang/clixon/Makefile.in)
CLIXON_AUTOCLI_REV="2023-09-01" CLIXON_AUTOCLI_REV="2023-09-01"
CLIXON_LIB_REV="2023-05-01" CLIXON_LIB_REV="2023-11-01"
CLIXON_CONFIG_REV="2023-05-01" CLIXON_CONFIG_REV="2023-05-01"
CLIXON_RESTCONF_REV="2022-08-01" CLIXON_RESTCONF_REV="2022-08-01"
CLIXON_EXAMPLE_REV="2022-11-01" CLIXON_EXAMPLE_REV="2022-11-01"

View file

@ -120,14 +120,15 @@ EOF
expectxml="<upgraded xmlns=\"urn:example:a\"/>" expectxml="<upgraded xmlns=\"urn:example:a\"/>"
fi fi
elif $modstate; then elif $modstate; then
expectxml="<error-message>Internal error: No yang files found matching \"A@2016-01-01\" in the list of CLICON_YANG_DIRs</error-message>" # expectxml="<error-message>Internal error: No yang files found matching \"A@2016-01-01\" in the list of CLICON_YANG_DIRs</error-message>"
expectxml="<error-message>Internal error: Yang \"A@2016-01-01\" not found in the list of CLICON_YANG_DIRs</error-message>"
fi fi
else # xml false else # xml false
xmltag="wrong" xmltag="wrong"
expectxml="<error-message>Failed to find YANG spec of XML node: $xmltag with parent: config in namespace: urn:example:a</error-message>" expectxml="<error-message>Failed to find YANG spec of XML node: $xmltag with parent: config in namespace: urn:example:a</error-message>"
if ! $oldyang; then if ! $oldyang; then
if $modstate; then if $modstate; then
expectxml="<error-message>Internal error: No yang files found matching \"A@2016-01-01\" in the list of CLICON_YANG_DIRs</error-message>" expectxml="<error-message>Internal error: Yang \"A@2016-01-01\" not found in the list of CLICON_YANG_DIRs</error-message>"
fi fi
fi fi
fi fi

View file

@ -43,7 +43,7 @@ YANG_INSTALLDIR = @YANG_INSTALLDIR@
# Note: mirror these to test/config.sh.in # Note: mirror these to test/config.sh.in
YANGSPECS = clixon-config@2023-05-01.yang # 6.3 YANGSPECS = clixon-config@2023-05-01.yang # 6.3
YANGSPECS += clixon-lib@2023-05-01.yang # 6.3 YANGSPECS += clixon-lib@2023-11-01.yang # 6.5
YANGSPECS += clixon-rfc5277@2008-07-01.yang YANGSPECS += clixon-rfc5277@2008-07-01.yang
YANGSPECS += clixon-xml-changelog@2019-03-21.yang YANGSPECS += clixon-xml-changelog@2019-03-21.yang
YANGSPECS += clixon-restconf@2022-08-01.yang # 5.9 YANGSPECS += clixon-restconf@2022-08-01.yang # 5.9

View file

@ -5,10 +5,10 @@ module clixon-lib {
import ietf-yang-types { import ietf-yang-types {
prefix yang; prefix yang;
} }
import ietf-netconf-monitoring { import ietf-netconf-monitoring {
prefix ncm; prefix ncm;
} }
import ietf-yang-metadata { import ietf-yang-metadata {
prefix "md"; prefix "md";
} }
@ -21,7 +21,7 @@ module clixon-lib {
description description
"***** BEGIN LICENSE BLOCK ***** "***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2019 Olof Hagsand Copyright (C) 2009-2019 Olof Hagsand
Copyright (C) 2020-2021 Olof Hagsand and Rubicon Communications, LLC(Netgate) Copyright (C) 2020-2022 Olof Hagsand and Rubicon Communications, LLC(Netgate)
This file is part of CLIXON This file is part of CLIXON
@ -68,6 +68,18 @@ module clixon-lib {
- objectexisted - objectexisted
"; ";
revision 2023-11-01 {
description
"Added ignore-compare extension
Removed obsolete extension autocli-op
Released in 6.5.0";
}
revision 2023-05-01 {
description
"Restructured and extended stats rpc to schema mountpoints
Moved datastore-format typedef from clixon-config
";
}
revision 2023-03-01 { revision 2023-03-01 {
description description
"Added creator meta-object"; "Added creator meta-object";
@ -138,6 +150,27 @@ module clixon-lib {
description description
"Common operations that can be performed on a service"; "Common operations that can be performed on a service";
} }
typedef datastore_format{
description
"Datastore format (only xml and json implemented in actual data.";
type enumeration{
enum 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{
description "Save and load xmldb as JSON";
}
enum text{
description "'Curly' C-like text format";
}
enum cli{
description "CLI format";
}
}
}
identity snmp { identity snmp {
description description
"SNMP"; "SNMP";
@ -160,20 +193,12 @@ module clixon-lib {
"A CLI session"; "A CLI session";
base ncm:transport; base ncm:transport;
} }
extension autocli-op { extension ignore-compare {
description description
"Takes an argument an operation defing how to modify the clispec at "The object should be ignored when comparing device configs for equality.
this point in the YANG tree for the automated generated CLI. One example is auto-created objects by the server, such as uid.
Note that this extension is only used in clixon_cli. Another example is a plain-text password is changed to an encrypted by the server.";
Operations is expected to be extended, but the following operations are defined:
- hide This command is active but not shown by ? or TAB (meaning, it hides the auto-completion of commands)
- hide-database This command hides the database
- hide-database-auto-completion This command hides the database and the auto completion (meaning, this command acts as both commands above)
Obsolete: use clixon-autocli:hide and clixon-autocli:hide-show instead";
argument cliop;
status obsolete;
} }
md:annotation creator { md:annotation creator {
type string; type string;
description description
@ -182,7 +207,7 @@ module clixon-lib {
create the same object. When such a service is deleted (or changed) one needs to keep create the same object. When such a service is deleted (or changed) one needs to keep
track of which service created what. track of which service created what.
Limitations: only objects that are actually added or deleted. Limitations: only objects that are actually added or deleted.
A sub-object wil not be noted"; A sub-object will not be noted";
} }
rpc debug { rpc debug {
description "Set debug level of backend."; description "Set debug level of backend.";
@ -195,8 +220,15 @@ module clixon-lib {
rpc ping { rpc ping {
description "Check aliveness of backend daemon."; description "Check aliveness of backend daemon.";
} }
rpc stats { rpc stats { /* Could be moved to state */
description "Clixon XML statistics."; description "Clixon yang and datastore statistics.";
input {
leaf modules {
description "If enabled include per-module statistics";
type boolean;
mandatory false;
}
}
output { output {
container global{ container global{
description description
@ -216,7 +248,8 @@ module clixon-lib {
type uint64; type uint64;
} }
} }
list datastore{ container datastores{
list datastore{
description "Per datastore statistics for cxobj"; description "Per datastore statistics for cxobj";
key "name"; key "name";
leaf name{ leaf name{
@ -232,9 +265,11 @@ module clixon-lib {
description "Size in bytes of internal datastore cache of datastore tree."; description "Size in bytes of internal datastore cache of datastore tree.";
type uint64; type uint64;
} }
}
} }
list module{ container module-sets{
description "Per YANG module statistics"; list module-set{
description "Statistics per group of module, eg top-level and mount-points";
key "name"; key "name";
leaf name{ leaf name{
description "Name of YANG module."; description "Name of YANG module.";
@ -242,14 +277,33 @@ module clixon-lib {
} }
leaf nr{ leaf nr{
description description
"Number of YANG objects. That is number of residing YANG objects"; "Total number of YANG objects in set";
type uint64; type uint64;
} }
leaf size{ leaf size{
description description
"Size in bytes of internal YANG object representation."; "Total size in bytes of internal YANG object representation for module set";
type uint64; type uint64;
} }
list module{
description "Statistics per module (if modules set in input)";
key "name";
leaf name{
description "Name of YANG module.";
type string;
}
leaf nr{
description
"Number of YANG objects. That is number of residing YANG objects";
type uint64;
}
leaf size{
description
"Size in bytes of internal YANG object representation.";
type uint64;
}
}
}
} }
} }
} }
@ -262,7 +316,6 @@ module clixon-lib {
} }
} }
} }
rpc process-control { rpc process-control {
description description
"Control a specific process or daemon: start/stop, etc. "Control a specific process or daemon: start/stop, etc.