diff --git a/CHANGELOG.md b/CHANGELOG.md index f16acb75..b81b5a2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,7 @@ Developers may need to change their code ### Corrected Busg +* Fixed: [YANG 'when' does not work in multiple grouping](https://github.com/clicon/clixon/issues/572) * Fixed: [Error when changing choice/case with different structure](https://github.com/clicon/clixon/issues/568) * Fixed: [Clixon handle if-feature incorrectly](https://github.com/clicon/clixon/issues/555) * Fixed: [Clixon fails to load yang with extension](https://github.com/clicon/clixon/issues/554) diff --git a/apps/snmp/snmp_main.c b/apps/snmp/snmp_main.c index b3fc45c3..5fe6bdb0 100644 --- a/apps/snmp/snmp_main.c +++ b/apps/snmp/snmp_main.c @@ -363,11 +363,9 @@ main(int argc, enum format_enum config_dump_format = FORMAT_XML; int print_version = 0; int32_t d; -#if 1 char *buf = NULL; size_t bufsize = 0; - int err; -#endif + int ret; /* Create handle */ if ((h = clixon_handle_init()) == NULL) @@ -379,35 +377,24 @@ main(int argc, goto done; /* Set username to clixon handle. Use in all communication to backend */ -#if 1 - { - bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); - if (bufsize == -1){ - bufsize = 16384; - } - if ((buf = malloc(bufsize)) == NULL){ - clixon_err(OE_UNIX, errno, "malloc"); - goto done; - } - err = getpwuid_r(getuid(), &pw, buf, bufsize, &pwresult); - if (pwresult == NULL) { - if (err == 0) - clixon_err(OE_UNIX, errno, "getpwuid_r"); - else - clixon_err(OE_UNIX, err, "getpwuid_r"); - goto done; - } + bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (bufsize == -1){ + bufsize = 16384; + } + if ((buf = malloc(bufsize)) == NULL){ + clixon_err(OE_UNIX, errno, "malloc"); + goto done; + } + ret = getpwuid_r(getuid(), &pw, buf, bufsize, &pwresult); + if (pwresult == NULL) { + if (ret == 0) + clixon_err(OE_UNIX, errno, "getpwuid_r"); + else + clixon_err(OE_UNIX, ret, "getpwuid_r"); + goto done; } if (clicon_username_set(h, pw.pw_name) < 0) goto done; -#else - if ((pw = getpwuid(getuid())) == NULL){ - clixon_err(OE_UNIX, errno, "getpwuid"); - goto done; - } - if (clicon_username_set(h, pw->pw_name) < 0) - goto done; -#endif while ((c = getopt(argc, argv, SNMP_OPTS)) != -1) switch (c) { case 'h' : /* help */ @@ -625,10 +612,8 @@ main(int argc, ok: retval = 0; done: -#if 1 if (buf) free(buf); -#endif clixon_log_init(h, __PROGRAM__, LOG_INFO, 0); /* Log on syslog no stderr */ clixon_log(h, LOG_NOTICE, "%s: %u Terminated", __PROGRAM__, getpid()); snmp_terminate(h); diff --git a/lib/clixon/clixon_yang.h b/lib/clixon/clixon_yang.h index 4a254e36..5fb5ce5f 100644 --- a/lib/clixon/clixon_yang.h +++ b/lib/clixon/clixon_yang.h @@ -93,7 +93,7 @@ #define YANG_FLAG_SPEC_MOUNT 0x400 /* Top-level spec is mounted by other top-level tree */ #define YANG_FLAG_WHEN 0x800 /* Use external map to access when-info for - * augment/grouping */ + * augment/grouping. Only orig object */ #define YANG_FLAG_MYMODULE 0x1000 /* Use external map to access my-module for * UNKNOWNS and augment/grouping */ #define YANG_FLAG_REFINE 0x2000 /* In derived trees from grouping and augments, this node diff --git a/lib/src/clixon_map.c b/lib/src/clixon_map.c index 93824638..05e22015 100644 --- a/lib/src/clixon_map.c +++ b/lib/src/clixon_map.c @@ -195,7 +195,7 @@ clixon_ptr2ptr(map_ptr2ptr *mptab, return 0; } -/*! Add pointer pairto mptab map +/*! Add pointer pair to mptab map * * @param[in] mptab Ptr to ptr map * @param[in] ptr0 Input pointer diff --git a/lib/src/clixon_yang.c b/lib/src/clixon_yang.c index 90c515f9..6957e2d6 100644 --- a/lib/src/clixon_yang.c +++ b/lib/src/clixon_yang.c @@ -518,14 +518,17 @@ yang_when_get(clixon_handle h, yang_stmt *ys) { map_ptr2ptr *mp = _yang_when_map; + yang_stmt *ys2; if (mp == NULL){ clixon_log(h, LOG_WARNING, "when_map not defined, yang_init() not called?"); return NULL; } else { - if (yang_flag_get(ys, YANG_FLAG_WHEN) != 0x0 && mp != NULL) - return clixon_ptr2ptr(mp, ys); + if ((ys2 = yang_orig_get(ys)) == NULL) + ys2 = ys; + if (yang_flag_get(ys2, YANG_FLAG_WHEN) != 0x0 && mp != NULL) + return clixon_ptr2ptr(mp, ys2); } return NULL; } @@ -544,6 +547,7 @@ yang_when_set(clixon_handle h, yang_stmt *ywhen) { int retval = -1; + yang_stmt *ys2; map_ptr2ptr *mp = _yang_when_map; if (mp == NULL){ @@ -551,13 +555,16 @@ yang_when_set(clixon_handle h, goto done; } else { - if (clixon_ptr2ptr(mp, ys) != NULL) { - clixon_err(OE_YANG, 0, "when pointer already set"); - goto done; + if ((ys2 = yang_orig_get(ys)) == NULL) + ys2 = ys; + if (clixon_ptr2ptr(mp, ys2) == NULL) { + assert(yang_flag_set(ys2, YANG_FLAG_WHEN)==0); // XXX + if (clixon_ptr2ptr_add(&_yang_when_map, ys2, ywhen) < 0) + goto done; + yang_flag_set(ys2, YANG_FLAG_WHEN); } - if (clixon_ptr2ptr_add(&_yang_when_map, ys, ywhen) < 0) - goto done; - yang_flag_set(ys, YANG_FLAG_WHEN); + else + assert(yang_flag_set(ys2, YANG_FLAG_WHEN) == 0); // XXX } retval = 0; done: @@ -2453,6 +2460,7 @@ yang_mounts_print(FILE *f, } /* Log/debug info about top-level (sub)modules no recursion + * * @param[in] yspec Yang spec * @param[in] dbglevel Debug level */ @@ -2537,6 +2545,7 @@ yang_print_cbuf(cbuf *cb, else cprintf(cb, " %s", arg); } + // cprintf(cb, " %p ", yn); For debugging object ptr if (yang_len_get(yn)){ cprintf(cb, " {"); if (pretty) diff --git a/test/test_grouping_multi.sh b/test/test_grouping_multi.sh index 7c11d763..9ef4b5c9 100755 --- a/test/test_grouping_multi.sh +++ b/test/test_grouping_multi.sh @@ -42,7 +42,7 @@ create @datamodel, cli_auto_create(); commit("Commit the changes"), cli_commit(); validate("Validate changes"), cli_validate(); delete("Delete a configuration item") { - @datamodel, cli_auto_del(); + @datamodel, cli_auto_del(); all("Delete whole candidate configuration"), delete_all("candidate"); } show("Show a particular state of the system"){ @@ -52,36 +52,55 @@ EOF # Yang specs must be here first for backend. But then the specs are changed but just for CLI # Annotate original Yang spec example directly -# First annotate /table/parameter +# First annotate /table/parameter # Had a problem with unknown in grouping -> test uses uses/grouping cat < $fyang module example { - namespace "urn:example:clixon"; - prefix ex; - grouping L3-top { - leaf L3{ - type string; - } - } - grouping L2-top { - container L2 { - uses L3-top { - when 'false'; - } - } - } - container L1x { - /* Does not work */ - uses L2-top; - } - container L1y { - /* Works */ - container L2 { - uses L3-top { - when 'false'; - } - } - } + namespace "urn:example:clixon"; + prefix ex; + grouping L0-group { + leaf L0{ + type string; + } + } + grouping L1-group { + list L1 { + key x; + leaf x { + type uint32; + } + uses L0-group { + when 'x=42'; +// when 'false'; + } + } + } + container L2x { + description "Two-level"; + list L1 { + key x; + leaf x { + type uint32; + } + uses L0-group { + when 'x=42'; +// when 'false'; + } + } + } + container L2y { + description "Three levels"; + uses L1-group; + } + grouping L2-group { + container L2 { + uses L1-group; + } + } + container L3 { + description "Four levels"; + uses L2-group; + } } EOF @@ -99,6 +118,35 @@ fi new "wait backend" wait_backend +new "CLI: L2 17, expect fail" +expectpart "$($clixon_cli -f $cfg -1 set L2x L1 17 L0 x 2>&1)" 255 "Node 'L0' tagged with 'when' condition 'x=42' in module 'example'" + +new "CLI: L2 42, expect ok" +expectpart "$($clixon_cli -f $cfg -1 set L2x L1 42 L0 x 2>&1)" 0 "" + +new "NETCONF: L2x, expect fail" +expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "17x" "" "applicationunknown-elementL0errorNode 'L0' tagged with 'when' condition 'x=42' in module 'example' evaluates to false in edit-config operation (see RFC 7950 Sec 8.3.2)" + +new "NETCONF: L2x, expect ok" +expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "42x" "" "" + +new "NETCONF validate, expect ok" +expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "" "" "" + +new "L2y grouping, expect fail" +expectpart "$($clixon_cli -f $cfg -1 set L2y L1 17 L0 x 2>&1)" 255 "Node 'L0' tagged with 'when' condition 'x=42' in module 'example'" + +new "L2y grouping, expect ok" +expectpart "$($clixon_cli -f $cfg -1 set L2y L1 42 L0 x 2>&1)" 0 "" + +new "NETCONF: L2y, expect fail" +expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "17x" "" "applicationunknown-elementL0errorNode 'L0' tagged with 'when' condition 'x=42' in module 'example' evaluates to false in edit-config operation (see RFC 7950 Sec 8.3.2)" + +new "NETCONF: L2y, expect ok" +expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "42x" "" "" + +new "L3, expect fail" +expectpart "$($clixon_cli -f $cfg -1 set L3 L2 L1 17 L0 x 2>&1)" 255 "" if [ $BE -ne 0 ]; then new "Kill backend" @@ -110,7 +158,7 @@ if [ $BE -ne 0 ]; then # kill backend stop_backend -f $cfg fi - + rm -rf $dir new "endtest"