diff --git a/CHANGELOG.md b/CHANGELOG.md
index 81dc1a13..6688382b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -82,6 +82,7 @@ Developers may need to change their code
### Corrected Bugs
+* [cl:autocli-op hide has no effect in yang submodule](https://github.com/clicon/clixon/issues/282)
* [Doxygen - Typo in Input #275](https://github.com/clicon/clixon/issues/275)
## 5.3.0
@@ -105,7 +106,7 @@ The 5.3 release has pagination support, Linkref changes in validation and auto-c
* Updated state callback signature containing parameters for pagination
* See API changes below
* Work-in-progress
- * Enable remaining attriute with LIST_PAGINATION_REMAINING compile-time option
+ * Enable remaining attribute with LIST_PAGINATION_REMAINING compile-time option
* sort/direction/where etc not supported
* For documentation: [User manual pagination](https://clixon-docs.readthedocs.io/en/latest/misc.html#pagination)
* YANG Leafref feature update
diff --git a/apps/cli/cli_auto.c b/apps/cli/cli_auto.c
index c51b6f79..5e4e4f6d 100644
--- a/apps/cli/cli_auto.c
+++ b/apps/cli/cli_auto.c
@@ -353,7 +353,7 @@ cli_xml2cli(cxobj *xn,
yang_keyword_get(ys) == Y_LEAF_LIST){
if (prepend)
(*fn)(stdout, "%s", prepend);
- if (gt == GT_ALL || gt == GT_VARS || gt == GT_HIDE)
+ if (gt == GT_ALL || gt == GT_VARS || gt == GT_HIDE || gt == GT_OC_COMPRESS)
(*fn)(stdout, "%s ", xml_name(xn));
if ((body = xml_body(xn)) != NULL){
if (index(body, ' '))
diff --git a/apps/cli/cli_generate.c b/apps/cli/cli_generate.c
index ac6527df..2f042ead 100644
--- a/apps/cli/cli_generate.c
+++ b/apps/cli/cli_generate.c
@@ -764,7 +764,7 @@ yang2cli_leaf(clicon_handle h,
/* Look for autocli-op defined in clixon-lib.yang */
if (yang_extension_value(ys, "autocli-op", CLIXON_LIB_NS, NULL, &opext) < 0)
goto done;
- if (gt == GT_VARS|| gt == GT_ALL || gt == GT_HIDE){
+ if (gt == GT_VARS || gt == GT_ALL || gt == GT_HIDE || gt == GT_OC_COMPRESS){
cprintf(cb, "%s", yang_argument_get(ys));
yang2cli_helptext(cb, helptext);
cprintf(cb, " ");
@@ -833,13 +833,27 @@ yang2cli_container(clicon_handle h,
char *helptext = NULL;
char *s;
int hide = 0;
+ int hide_oc = 0;
+ int exist = 0;
char *opext = NULL;
+ yang_stmt *ymod = NULL;
+
+
+ if (ys_real_module(ys, &ymod) < 0)
+ goto done;
+ if (yang_extension_value(ymod, "openconfig-version", "http://openconfig.net/yang/openconfig-ext", &exist, NULL) < 0)
+ goto done;
+ if (exist) {
+ if (strcmp(yang_argument_get(ys), "config") == 0){
+ hide_oc = 1;
+ }
+ }
/* If non-presence container && HIDE mode && only child is
* a list, then skip container keyword
* See also xml2cli
*/
- if ((hide = yang_container_cli_hide(ys, gt)) == 0){
+ if ((hide = yang_container_cli_hide(ys, gt)) == 0 && hide_oc == 0){
cprintf(cb, "%*s%s", level*3, "", yang_argument_get(ys));
if ((yd = yang_find(ys, Y_DESCRIPTION, NULL)) != NULL){
if ((helptext = strdup(yang_argument_get(yd))) == NULL){
@@ -868,10 +882,10 @@ yang2cli_container(clicon_handle h,
yc = NULL;
while ((yc = yn_each(ys, yc)) != NULL)
if (yang2cli_stmt(h, yc, gt, level+1, state, show_tree, cb) < 0)
- goto done;
- if (hide == 0)
- cprintf(cb, "%*s}\n", level*3, "");
- retval = 0;
+ goto done;
+ if (hide == 0 && hide_oc == 0)
+ cprintf(cb, "%*s}\n", level*3, "");
+ retval = 0;
done:
if (helptext)
free(helptext);
@@ -956,7 +970,7 @@ yang2cli_list(clicon_handle h,
cprintf(cb, "{\n");
}
if (yang2cli_leaf(h, yleaf,
- (gt==GT_VARS||gt==GT_HIDE)?GT_NONE:gt, level+1,
+ (gt==GT_VARS||gt==GT_HIDE||gt==GT_OC_COMPRESS)?GT_NONE:gt, level+1,
last_key, show_tree, 1,
cb) < 0)
goto done;
diff --git a/apps/cli/cli_main.c b/apps/cli/cli_main.c
index 0264490e..f085d539 100644
--- a/apps/cli/cli_main.c
+++ b/apps/cli/cli_main.c
@@ -620,7 +620,7 @@ main(int argc,
Should be 0 but default is 1 since all legacy apps use 1
Test legacy before shifting default to 0
*/
- cv_exclude_keys(clicon_cli_varonly(h));
+ cligen_exclude_keys_set(cli_cligen(h), clicon_cli_varonly(h));
/* Initialize plugin module by creating a handle holding plugin and callback lists */
if (clixon_plugin_module_init(h) < 0)
diff --git a/apps/cli/cli_plugin.c b/apps/cli/cli_plugin.c
index 77b60cbe..f83a99e6 100644
--- a/apps/cli/cli_plugin.c
+++ b/apps/cli/cli_plugin.c
@@ -525,34 +525,50 @@ cli_handler_err(FILE *f)
/*! Variant of eval for context checking
* @see cligen_eval
*/
-int
-cligen_clixon_eval(cligen_handle h,
+static int
+clixon_cligen_eval(cligen_handle h,
cg_obj *co,
cvec *cvv)
{
struct cg_callback *cc;
- int retval = 0;
+ int retval = -1;
cvec *argv;
- plugin_context_t *pc = NULL;
+ cvec *cvv1 = NULL; /* Modified */
+ plugin_context_t *pc = NULL; /* Clixon-specific */
+
+ /* Save matched object for plugin use */
if (h)
cligen_co_match_set(h, co);
+ /* Make a copy of var argument for modifications */
+ if ((cvv1 = cvec_dup(cvv)) == NULL)
+ goto done;
+ /* Make modifications to cvv */
+ if (cligen_expand_first_get(h) &&
+ cvec_expand_first(cvv1) < 0)
+ goto done;
+ if (cligen_exclude_keys_get(h) &&
+ cvec_exclude_keys(cvv1) < 0)
+ goto done;
+ /* Traverse callbacks */
for (cc = co->co_callbacks; cc; cc=cc->cc_next){
/* Vector cvec argument to callback */
if (cc->cc_fn_vec){
argv = cc->cc_cvec ? cvec_dup(cc->cc_cvec) : NULL;
cligen_fn_str_set(h, cc->cc_fn_str);
- if ((pc = plugin_context_get()) == NULL)
+ /* Clixon-specific */
+ if ((pc = plugin_context_get()) == NULL)
break;
if ((retval = (*cc->cc_fn_vec)(
cligen_userhandle(h)?cligen_userhandle(h):h,
- cvv,
+ cvv1,
argv)) < 0){
if (argv != NULL)
cvec_free(argv);
cligen_fn_str_set(h, NULL);
- break;
+ goto done;
}
+ /* Clixon-specific */
if (plugin_context_check(pc, "CLIgen", cc->cc_fn_str) < 0)
break;
if (pc){
@@ -564,8 +580,12 @@ cligen_clixon_eval(cligen_handle h,
cligen_fn_str_set(h, NULL);
}
}
- if (pc)
+ retval = 0;
+ done:
+ if (pc) /* Clixon-specific */
free(pc);
+ if (cvv1)
+ cvec_free(cvv1);
return retval;
}
@@ -589,7 +609,7 @@ clicon_eval(clicon_handle h,
if (!cligen_exiting(cli_cligen(h))) {
clicon_err_reset();
- if ((retval = cligen_clixon_eval(cli_cligen(h), match_obj, cvv)) < 0) {
+ if ((retval = clixon_cligen_eval(cli_cligen(h), match_obj, cvv)) < 0) {
#if 0 /* This is removed since we get two error messages on failure.
But maybe only sometime?
Both a real log when clicon_err is called, and the here again.
@@ -631,7 +651,7 @@ clicon_parse(clicon_handle h,
cli_syntax_t *stx = NULL;
cli_syntaxmode_t *csm;
parse_tree *pt; /* Orig */
- cg_obj *match_obj;
+ cg_obj *match_obj = NULL;
cvec *cvv = NULL;
FILE *f;
char *reason = NULL;
@@ -663,12 +683,15 @@ clicon_parse(clicon_handle h,
fprintf(stderr, "No such parse-tree registered: %s\n", modename);
goto done;
}
- if ((cvv = cvec_new(0)) == NULL){
- clicon_err(OE_UNIX, errno, "cvec_new");
+#if 0 // switch after 5.4
+ if (cliread_parse2(cli_cligen(h), cmd, pt, &match_obj, &cvv, result, &reason) < 0)
+ goto done;
+#else
+ if ((cvv = cvec_new(0)) == NULL)
goto done;;
- }
if (cliread_parse(cli_cligen(h), cmd, pt, &match_obj, cvv, result, &reason) < 0)
goto done;
+#endif
/* Debug command and result code */
clicon_debug(1, "%s result:%d command: \"%s\"", __FUNCTION__, *result, cmd);
if (*result != CG_MATCH)
@@ -708,6 +731,8 @@ done:
free(reason);
if (cvv)
cvec_free(cvv);
+ if (match_obj)
+ co_free(match_obj, 0);
return retval;
}
diff --git a/lib/clixon/clixon_options.h b/lib/clixon/clixon_options.h
index 72073f09..ddec1eb8 100644
--- a/lib/clixon/clixon_options.h
+++ b/lib/clixon/clixon_options.h
@@ -77,6 +77,7 @@ enum genmodel_type{
GT_VARS, /* Keywords on non-key variables */
GT_ALL, /* Keywords on all variables */
GT_HIDE, /* Keywords on all variables and hide container around lists */
+ GT_OC_COMPRESS, /* OpenConfig */
};
typedef enum genmodel_type genmodel_type;
diff --git a/lib/src/clixon_json_parse.y b/lib/src/clixon_json_parse.y
index 019942c4..947cf538 100644
--- a/lib/src/clixon_json_parse.y
+++ b/lib/src/clixon_json_parse.y
@@ -223,12 +223,27 @@ json_current_clone(clixon_json_yacc *jy)
clicon_debug(2, "%s", __FUNCTION__);
if (jy->jy_current == NULL){
- return -1;
+ return -1;
}
xn = jy->jy_current;
json_current_pop(jy);
- if (jy->jy_current)
- json_current_new(jy, xml_name(xn));
+
+ if (jy->jy_current) {
+ char* name = xml_name(xn);
+ char* prefix = xml_prefix(xn);
+ char* maybe_prefixed_name = NULL;
+
+ if (prefix) {
+ char* name_parts[] = {prefix, name};
+ maybe_prefixed_name = clicon_strjoin(2, name_parts, ":");
+ } else {
+ maybe_prefixed_name = strdup(name);
+ }
+ json_current_new(jy, maybe_prefixed_name);
+
+ if (maybe_prefixed_name)
+ free(maybe_prefixed_name);
+ }
return 0;
}
diff --git a/lib/src/clixon_options.c b/lib/src/clixon_options.c
index aa2bcc3b..886781a8 100644
--- a/lib/src/clixon_options.c
+++ b/lib/src/clixon_options.c
@@ -89,6 +89,7 @@ static const map_str2int cli_genmodel_map[] = {
{"VARS", GT_VARS},
{"ALL", GT_ALL},
{"HIDE", GT_HIDE},
+ {"OC_COMPRESS", GT_OC_COMPRESS},
{NULL, -1}
};
diff --git a/lib/src/clixon_sig.c b/lib/src/clixon_sig.c
index 611a27a8..80f305b7 100644
--- a/lib/src/clixon_sig.c
+++ b/lib/src/clixon_sig.c
@@ -156,7 +156,7 @@ clixon_signal_restore(sigset_t *sigset,
int retval = -1;
int i;
- if (sigprocmask(0, sigset, NULL) < 0){
+ if (sigprocmask(SIG_SETMASK, sigset, NULL) < 0){
clicon_err(OE_UNIX, errno, "sigprocmask");
goto done;
}
diff --git a/lib/src/clixon_xml.c b/lib/src/clixon_xml.c
index 750bbab2..a3c32725 100644
--- a/lib/src/clixon_xml.c
+++ b/lib/src/clixon_xml.c
@@ -581,10 +581,11 @@ xml_parent(cxobj *xn)
return xn->x_up;
}
-/*! Set parent of xnode, parent is copied.
+/*! Set parent of xml node.
* @param[in] xn xml node
* @param[in] parent pointer to new parent xml node
* @retval 0 OK
+ * @see xml_child_rm remove child from parent
*/
int
xml_parent_set(cxobj *xn,
@@ -1986,8 +1987,6 @@ xml_copy(cxobj *x0,
return retval;
}
-
-
/*! Create and return a copy of xml tree.
*
* @code
diff --git a/lib/src/clixon_xml_map.c b/lib/src/clixon_xml_map.c
index aaf2c233..9abbf774 100644
--- a/lib/src/clixon_xml_map.c
+++ b/lib/src/clixon_xml_map.c
@@ -286,7 +286,7 @@ xml2cli_recurse(FILE *f,
/* If presence container, then print as leaf (but continue to children) */
if (prepend)
(*fn)(f, "%s", prepend);
- if (gt == GT_ALL || gt == GT_VARS || gt == GT_HIDE)
+ if (gt == GT_ALL || gt == GT_VARS || gt == GT_HIDE || gt == GT_OC_COMPRESS)
(*fn)(f, "%s ", xml_name(x));
if ((body = xml_body(x)) != NULL){
if (index(body, ' '))
diff --git a/lib/src/clixon_yang.c b/lib/src/clixon_yang.c
index d4e70dea..c9a8b0a0 100644
--- a/lib/src/clixon_yang.c
+++ b/lib/src/clixon_yang.c
@@ -2355,6 +2355,14 @@ ys_populate_unique(clicon_handle h,
* RFC 7950 Sec 7.19:
* If no "argument" statement is present, the keyword expects no argument when
* it is used.
+ * Note there is some complexity in different yang modules with unknown-statements.
+ * y0) The location of the extension definition. E.g. extension autocli-op
+ * y1) The location of the unknown-statement (ys). This is for example: cl:autocli-op hide.
+ * Lookup of "cl" is lexically scoped in this context (to find (y0)).
+ * y2) The unknown statement may be used by uses/grouping of (y1). But "cl" is declared
+ * in y1 context. This is fixed by setting ys_mymodule to y1 which is then used in
+ * lookups such as in yang_extension_value().
+ * @see yang_extension_value Called on expanded YANG, eg in context of (y2)
*/
static int
ys_populate_unknown(clicon_handle h,
@@ -2376,6 +2384,8 @@ ys_populate_unknown(clicon_handle h,
clicon_err(OE_YANG, ENOENT, "Extension \"%s:%s\", module not found", prefix, id);
goto done;
}
+ /* To find right binding eg after grouping/uses */
+ ys->ys_mymodule = ys_module(ys);
if ((yext = yang_find(ymod, Y_EXTENSION, id)) == NULL){
clicon_err(OE_YANG, ENOENT, "Extension \"%s:%s\" not found", prefix, id);
goto done;
@@ -3255,7 +3265,7 @@ yang_container_cli_hide(yang_stmt *ys,
keyw = yang_keyword_get(ys);
/* HIDE mode */
- if (gt != GT_HIDE)
+ if (gt != GT_HIDE && gt != GT_OC_COMPRESS)
return 0;
/* A container */
if (yang_keyword_get(ys) != Y_CONTAINER)
@@ -3572,6 +3582,7 @@ yang_anydata_add(yang_stmt *yp,
* // use extension value
* }
* @endcode
+ * @see ys_populate_unknown Called when parsing YANGo
*/
int
yang_extension_value(yang_stmt *ys,
diff --git a/lib/src/clixon_yang_internal.h b/lib/src/clixon_yang_internal.h
index 06a73d4c..4fb3a489 100644
--- a/lib/src/clixon_yang_internal.h
+++ b/lib/src/clixon_yang_internal.h
@@ -71,9 +71,13 @@ struct yang_stmt{
char *ys_argument; /* String / argument depending on keyword */
uint16_t ys_flags; /* Flags according to YANG_FLAG_MARK and others */
- yang_stmt *ys_mymodule; /* Shortcut to "my" module. Augmented
- nodes can belong to other
- modules than the ancestor module */
+ yang_stmt *ys_mymodule; /* Shortcut to "my" module. Used by:
+ 1) Augmented nodes "belong" to the module where the
+ augment is declared, which may be differnt from
+ the direct ancestor module
+ 2) Unknown nodes "belong" to where the extension is
+ declared
+ */
cg_var *ys_cv; /* cligen variable. See ys_populate()
Following stmts have cv:s:
leaf: for default value
diff --git a/test/test_augment.sh b/test/test_augment.sh
index 06ef088c..d910cbc6 100755
--- a/test/test_augment.sh
+++ b/test/test_augment.sh
@@ -185,6 +185,18 @@ module example-augment {
type string;
}
}
+ /* augment a list */
+ augment "/if:interfaces" {
+ list ports{
+ key id;
+ leaf id {
+ type int32;
+ }
+ leaf str {
+ type string;
+ }
+ }
+ }
}
EOF
@@ -291,6 +303,30 @@ expectpart "$(curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/ietf-inte
new "restconf GET augment multi-namespace cross level 2"
expectpart "$(curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces/interface=e1/example-augment:ospf/reference-bandwidth)" 0 "HTTP/$HVER 200" '{"example-augment:reference-bandwidth":23}'
+new "delete interfaces"
+expectpart "$(curl $CURLOPTS -X DELETE $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces)" 0 "HTTP/$HVER 204"
+
+# augmented lists
+XML="22nisse44kalle"
+new "netconf PUT augmented list"
+expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLOmerge$XML]]>]]>" "^]]>]]>$"
+
+new "netconf commit"
+expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "^]]>]]>$"
+
+new "netconf get config"
+expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO]]>]]>" "$XML]]>]]>"
+
+JSON='{"ietf-interfaces:interfaces":{"example-augment:ports":[{"id":22,"str":"foo"},{"id":44,"str":"bar"}]}}'
+
+new "restconf PUT augmented list"
+expectpart "$(curl $CURLOPTS -X PUT -H 'Content-Type: application/yang-data+json' $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces -d "$JSON")" 0 "HTTP/$HVER 204"
+
+# Escaped [] why?
+JSON1='{"ietf-interfaces:interfaces":{"example-augment:ports":\[{"id":22,"str":"foo"},{"id":44,"str":"bar"}\]}}'
+new "restconf GET augmented list"
+expectpart "$(curl $CURLOPTS -X GET -H 'Accept: application/yang-data+json' $RCPROTO://localhost/restconf/data/ietf-interfaces:interfaces)" 0 "HTTP/$HVER 200" "$JSON1"
+
if [ $RC -ne 0 ]; then
new "Kill restconf daemon"
stop_restconf
diff --git a/test/test_cli_auto_extension.sh b/test/test_cli_auto_extension.sh
index 15878398..1cccbbd3 100755
--- a/test/test_cli_auto_extension.sh
+++ b/test/test_cli_auto_extension.sh
@@ -136,7 +136,6 @@ wait_backend
function testparam()
{
-
# Try hidden parameter list
new "query table parameter hidden"
expectpart "$(echo "set table ?" | $clixon_cli -f $cfg 2>&1)" 0 "set table" "" --not-- "parameter"
@@ -282,6 +281,60 @@ EOF
new "Test hidden parameter in table/param/value augment"
testvalue
+# Example using imported module where clixon-lib is NOT declared in main module
+# see discussion in ys_populate_unknown (y1 vs y2) and
+# https://github.com/clicon/clixon/issues/282
+cat < $fyang
+module example {
+ yang-version 1.1;
+ namespace "urn:example:clixon";
+ prefix ex;
+ import example-augment{
+ prefix aug;
+ }
+
+ container table{
+ list parameter{
+ key name;
+ leaf name{
+ type string;
+ }
+ uses aug:pg;
+ }
+ }
+}
+EOF
+
+# Use this as grouping (not annotate)
+cat < $fyang2
+module example-augment {
+ namespace "urn:example:augment";
+ prefix aug;
+ import clixon-lib{
+ prefix cl;
+ }
+ grouping pg {
+ cl:autocli-op hide; /* This is the extension */
+ leaf value{
+ description "a value";
+ type string;
+ }
+ list index{
+ key i;
+ leaf i{
+ type string;
+ }
+ leaf iv{
+ type string;
+ }
+ }
+ }
+}
+EOF
+
+new "Test hidden parameter in imported module"
+testparam
+
new "Kill backend"
# Check if premature kill
pid=$(pgrep -u root -f clixon_backend)
diff --git a/test/test_cli_auto_genmodel.sh b/test/test_cli_auto_genmodel.sh
index 566e2c04..6adb22f1 100755
--- a/test/test_cli_auto_genmodel.sh
+++ b/test/test_cli_auto_genmodel.sh
@@ -1,6 +1,7 @@
+
#!/usr/bin/env bash
# Tests for using the auto cli.
-# In particular setting a config, displaying as cli commands and reconfigure it
+# In particular setting a config, displaying as cli commands and reconfigure it
# Tests:
# Make a config in CLI. Show output as CLI, save it and ensure it is the same
# Try the different GENMODEL settings
@@ -15,6 +16,7 @@ APPNAME=example
cfg=$dir/conf_yang.xml
fyang=$dir/$APPNAME.yang
+fyang2=$dir/${APPNAME}2.yang
fstate=$dir/state.xml
clidir=$dir/cli
if [ -d $clidir ]; then
@@ -25,12 +27,19 @@ fi
# Use yang in example
+if [ ! -d "$OPENCONFIG" ]; then
+# err "Hmm Openconfig dir does not seem to exist, try git clone https://github.com/openconfig/public?"
+ echo "...skipped: OPENCONFIG not set"
+ if [ "$s" = $0 ]; then exit 0; else return 0; fi
+fi
+
cat < $cfg
$cfg
/usr/local/share/clixon
$dir_tmp
- $fyang
+ $OPENCONFIG/
+ $dir
/usr/local/lib/$APPNAME/backend
$clidir
/usr/local/lib/$APPNAME/cli
@@ -49,6 +58,9 @@ cat < $fyang
module $APPNAME {
namespace "urn:example:clixon";
prefix ex;
+ import openconfig-extensions { prefix oc-ext; }
+ /* Set openconfig version to "fake" an openconfig YANG */
+ oc-ext:openconfig-version;
container table{
list parameter{
key name;
@@ -69,6 +81,85 @@ module $APPNAME {
}
}
}
+ container interfaces {
+ list interface {
+ key name;
+ leaf name {
+ type string;
+ }
+ container config {
+ leaf enabled {
+ type boolean;
+ default false;
+ description "Whether the interface is enabled or not.";
+ }
+ }
+ container state {
+ config false;
+ leaf oper-status {
+ type enumeration {
+ enum UP {
+ value 1;
+ description "Ready to pass packets.";
+ }
+ enum DOWN {
+ value 2;
+ description "The interface does not pass any packets.";
+ }
+ }
+ }
+ }
+ leaf enabled {
+ type boolean;
+ default false;
+ description "Whether the interface is enabled or not.";
+ }
+ }
+ }
+}
+EOF
+
+# For openconfig but NO openconfig extension
+cat < $fyang2
+module ${APPNAME}2 {
+ namespace "urn:example:clixon2";
+ prefix ex2;
+ import openconfig-extensions { prefix oc-ext; }
+ container interfaces2 {
+ list interface {
+ key name;
+ leaf name {
+ type string;
+ }
+ container config {
+ leaf enabled {
+ type boolean;
+ default false;
+ description "Whether the interface is enabled or not.";
+ }
+ }
+ container state {
+ config false;
+ leaf oper-status {
+ type enumeration {
+ enum UP {
+ value 1;
+ description "Ready to pass packets.";
+ }
+ enum DOWN {
+ value 2;
+ description "The interface does not pass any packets.";
+ }
+ }
+ }
+ }
+ leaf enabled {
+ type boolean;
+ default false;
+ description "Whether the interface is enabled or not.";
+ }
+ }
+ }
}
EOF
@@ -127,6 +218,9 @@ function testrun()
elif [ $mode = HIDE ]; then
table=
name=
+ elif [ $mode = OC_COMPRESS ]; then
+ table=
+ name=
else
table=" table"
name=
@@ -159,7 +253,7 @@ SAVED=$($clixon_cli -1 -o CLICON_CLI_GENMODEL_TYPE=$mode -f $cfg show config)
new "delete a x"
expectpart "$($clixon_cli -1 -o CLICON_CLI_GENMODEL_TYPE=$mode -f $cfg delete$table parameter$name a value x)" 0 ""
- new "show match a & b xml"
+ new "show match a & b xml"
expectpart "$($clixon_cli -1 -o CLICON_CLI_GENMODEL_TYPE=$mode -f $cfg show xml)" 0 "" "" "a" "" "" "b" "z" "" "
" --not-- "x"
new "delete a"
@@ -190,6 +284,9 @@ testrun HIDE
new "keywords=ALL"
testrun ALL
+new "keywords=OC_COMPRESS"
+testrun OC_COMPRESS
+
new "keywords=VARS"
testrun VARS
@@ -201,11 +298,20 @@ new "commit"
expectpart "$($clixon_cli -1 -f $cfg commit)" 0 ""
new "show state"
-expectpart "$($clixon_cli -1 -f $cfg show state)" 0 "exstate sender x" "table parameter a" "table parameter a value x"
+expectpart "$($clixon_cli -1 -f $cfg show state)" 0 "exstate sender x" "table parameter a" "table parameter a value x"
new "show state exstate"
expectpart "$($clixon_cli -1 -f $cfg show state exstate)" 0 "state sender x" --not-- "table parameter a" "table parameter a value x"
+#---- openconfig path compression
+
+new "Openconfig: check no config path"
+expectpart "$($clixon_cli -1 -f $cfg set interfaces interface e config enabled true 2>&1)" 255 "Unknown command"
+
+# negative test
+new "Openconfig: check exist config path"
+expectpart "$($clixon_cli -1 -f $cfg set interfaces2 interface e config enabled true 2>&1)" 0 "^$"
+
new "Kill backend"
# Check if premature kill
pid=$(pgrep -u root -f clixon_backend)
diff --git a/yang/clixon/clixon-config@2021-07-11.yang b/yang/clixon/clixon-config@2021-07-11.yang
index 50bad2cc..1364455a 100644
--- a/yang/clixon/clixon-config@2021-07-11.yang
+++ b/yang/clixon/clixon-config@2021-07-11.yang
@@ -1,3 +1,4 @@
+
module clixon-config {
yang-version 1.1;
namespace "http://clicon.org/config";
@@ -247,6 +248,9 @@ module clixon-config {
enum HIDE{
description "Keywords on non-key variables and hide container around lists: a y ";
}
+ enum OC_COMPRESS{
+ description "See: https://github.com/openconfig/ygot/blob/master/docs/design.md#openconfig-path-compression";
+ }
}
}
typedef nacm_mode{