From c101799e747ca2ff5ec1ddf02e3d9d17b9b26968 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Tue, 22 Aug 2023 12:41:36 +0200 Subject: [PATCH] New command-line option for dumping configuration options for all clixon applications after load Removed -s dump --- CHANGELOG.md | 3 + apps/backend/backend_main.c | 35 ++++++-- apps/cli/cli_main.c | 31 +++++-- apps/netconf/netconf_main.c | 25 +++++- apps/restconf/restconf_main_fcgi.c | 24 +++++- apps/restconf/restconf_main_native.c | 23 ++++- lib/clixon/clixon_options.h | 6 +- lib/clixon/clixon_xml.h | 4 +- lib/src/clixon_options.c | 50 ++++++++++- lib/src/clixon_proto.c | 3 + .../{test_configdir.sh => test_config_dir.sh} | 12 +-- test/test_config_dump.sh | 83 +++++++++++++++++++ 12 files changed, 267 insertions(+), 32 deletions(-) rename test/{test_configdir.sh => test_config_dir.sh} (100%) create mode 100755 test/test_config_dump.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index a7ecdfcb..90476e8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,9 @@ Developers may need to change their code ### Minor features +* New command-line option for dumping configuration options for all clixon applications after load + * Syntax is `-C ` + * Example: `clixon_backend -1C json` * Removed sending restconf config inline using -R when CLICON_BACKEND_RESTCONF_PROCESS=true * Define RESTCONF_INLINE to revert * Clarified clixon_cli command-line: `clixon_cli [options] [commands] [-- extra-options]` diff --git a/apps/backend/backend_main.c b/apps/backend/backend_main.c index 7b144c3b..971c9f7c 100644 --- a/apps/backend/backend_main.c +++ b/apps/backend/backend_main.c @@ -79,7 +79,7 @@ #include "backend_plugin_restconf.h" /* Command line options to be passed to getopt(3) */ -#define BACKEND_OPTS "hD:f:E:l:d:p:b:Fza:u:P:1qs:c:U:g:y:o:" +#define BACKEND_OPTS "hD:f:E:l:C:d:p:b:Fza:u:P:1qs:c:U:g:y:o:" #define BACKEND_LOGFILE "/usr/local/var/clixon_backend.log" @@ -463,6 +463,7 @@ usage(clicon_handle h, "\t-f \tClixon config file\n" "\t-E \tExtra configuration file directory\n" "\t-l > \tLog on (s)yslog, std(e)rr, std(o)ut, (n)one or (f)ile (syslog is default)\n" + "\t-C \tDump configuration options on stdout after loading. Format is xml|json|text\n" "\t-d \tSpecify backend plugin directory (default: %s)\n" "\t-p \tAdd Yang directory path (see CLICON_YANG_DIR)\n" "\t-b \tSpecify datastore directory\n" @@ -489,6 +490,8 @@ usage(clicon_handle h, exit(-1); } +/* Clixon backend application main entry point + */ int main(int argc, char **argv) @@ -524,6 +527,8 @@ main(int argc, size_t cligen_bufthreshold; int dbg; size_t sz; + int config_dump; + enum format_enum config_dump_format = FORMAT_XML; /* In the startup, logs to stderr & syslog and debug flag set later */ clicon_log_init(__PROGRAM__, LOG_INFO, logdst); @@ -535,7 +540,8 @@ main(int argc, zap = 0; extraxml_file = NULL; dbg = 0; - + config_dump = 0; + /* * Command-line options for help, debug, and config-file */ @@ -607,6 +613,15 @@ main(int argc, case 'E': /* extra config dir */ case 'l' : break; /* see above */ + case 'C': /* Explicitly dump configuration */ + if (!strlen(optarg)) + usage(h, argv[0]); + if ((config_dump_format = format_str2int(optarg)) < 0){ + fprintf(stderr, "Unrecognized dump format: %s(expected: xml|json|text)\n", argv[0]); + usage(h, argv[0]); + } + config_dump++; + break; case 'd': /* Plugin directory */ if (!strlen(optarg)) usage(h, argv[0]); @@ -941,11 +956,6 @@ main(int argc, goto done; /* if status = STARTUP_INVALID, cbret contains info */ break; - case SM_DUMP_XML: - /* dump the tree */ - cxobj *xc = clicon_conf_xml(h); - ret = clixon_xml2file(stdout, xc, 0, 1, "", &fprintf, 0, 1); - goto ok; default: break; } @@ -978,7 +988,6 @@ main(int argc, /* if status = STARTUP_INVALID, cbret contains info */ } } - if (status != STARTUP_OK){ if (cbuf_len(cbret)) clicon_log(LOG_NOTICE, "%s: %u %s", __PROGRAM__, getpid(), cbuf_get(cbret)); @@ -1005,10 +1014,19 @@ main(int argc, /* Call backend plugin_start with user -- options */ if (clixon_plugin_start_all(h) < 0) goto done; + /* Explicit dump of config (also debug dump below). */ + if (config_dump){ + if (clicon_option_dump1(h, stdout, config_dump_format) < 0) + goto done; + } + /* -1 option to run only once */ if (once) goto ok; + /* Debug dump of config options */ + clicon_option_dump(h, 1); + /* Daemonize and initiate logging. Note error is initiated here to make daemonized errors OK. Before this stage, errors are logged on stderr also */ @@ -1056,7 +1074,6 @@ main(int argc, goto done; if (clicon_socket_set(h, ss) < 0) goto done; - clicon_option_dump(h, 1); /* Depending on configure setting, privileges may be dropped here after * initializations */ diff --git a/apps/cli/cli_main.c b/apps/cli/cli_main.c index ac230ceb..56f875cf 100644 --- a/apps/cli/cli_main.c +++ b/apps/cli/cli_main.c @@ -73,7 +73,7 @@ #include "cli_handle.h" /* Command line options to be passed to getopt(3) */ -#define CLI_OPTS "+hD:f:E:l:F:1a:u:d:m:qp:GLy:c:U:o:" +#define CLI_OPTS "+hD:f:E:l:C:F:1a:u:d:m:qp:GLy:c:U:o:" /*! Check if there is a CLI history file and if so dump the CLI histiry to it * Just log if file does not exist or is not readable @@ -476,6 +476,8 @@ usage(clicon_handle h, "\t-D \tDebug level\n" "\t-f \tConfig-file (mandatory)\n" "\t-E \tExtra configuration file directory\n" + "\t-l > \tLog on (s)yslog, std(e)rr, std(o)ut, (n)one or (f)ile (stderr is default)\n" + "\t-C \tDump configuration options on stdout after loading. Format is xml|json|text\n" "\t-F \tRead commands from file (default stdin)\n" "\t-1\t\tDo not enter interactive mode\n" "\t-a UNIX|IPv4|IPv6\tInternal backend socket family\n" @@ -486,7 +488,7 @@ usage(clicon_handle h, "\t-p \tYang directory path (see CLICON_YANG_DIR)\n" "\t-G \t\tPrint auto-cli CLI syntax generated from YANG\n" "\t-L \t\tDebug print dynamic CLI syntax including completions and expansions\n" - "\t-l > \tLog on (s)yslog, std(e)rr, std(o)ut, (n)one or (f)ile (stderr is default)\n" + "\t-y \tOverride yang spec file (dont include .yang suffix)\n" "\t-c \tSpecify cli spec file.\n" "\t-U \tOver-ride unix user with a pseudo user for NACM.\n" @@ -522,9 +524,12 @@ main(int argc, size_t cligen_bufthreshold; int dbg=0; int nr; + int config_dump; + enum format_enum config_dump_format = FORMAT_XML; /* Defaults */ once = 0; + config_dump = 0; /* In the startup, logs to stderr & debug flag set later */ clicon_log_init(__PROGRAM__, LOG_INFO, logdst); @@ -607,6 +612,15 @@ main(int argc, case 'E': /* extra config dir */ case 'l': /* Log destination */ break; /* see above */ + case 'C': /* Explicitly dump configuration */ + if (!strlen(optarg)) + usage(h, argv[0]); + if ((config_dump_format = format_str2int(optarg)) < 0){ + fprintf(stderr, "Unrecognized dump format: %s(expected: xml|json|text)\n", argv[0]); + usage(h, argv[0]); + } + config_dump++; + break; case 'F': /* read commands from file */ if (freopen(optarg, "r", stdin) == NULL){ fprintf(stderr, "freopen: %s\n", strerror(errno)); @@ -833,10 +847,6 @@ main(int argc, if (logclisyntax) cli_logsyntax_set(h, logclisyntax); - clicon_option_dump(h, 1); - - - /* Clixon hardcodes variable tie-breaks to non-terminals (2) * There are cases in the autocli such as: * (\tConfiguration file (mandatory)\n" "\t-E \tExtra configuration file directory\n" "\t-l > \tLog on (s)yslog, std(e)rr, std(o)ut, (n)one or (f)ile (syslog is default)\n" + "\t-C \tDump configuration options on stdout after loading and exit. Format is xml|json|text\n" "\t-q\t\tServer does not send hello message on startup\n" "\t-0 \t\tSet netconf base capability to 0, server does not expect hello, force EOM framing\n" "\t-1 \t\tSet netconf base capability to 1, server does not expect hello, force chunked framing\n" @@ -663,6 +664,8 @@ main(int argc, size_t cligen_bufthreshold; int dbg = 0; size_t sz; + int config_dump = 0; + enum format_enum config_dump_format = FORMAT_XML; /* Create handle */ if ((h = clicon_handle_init()) == NULL) @@ -728,6 +731,15 @@ main(int argc, case 'E': /* extra config dir */ case 'l': /* log */ break; /* see above */ + case 'C': /* Explicitly dump configuration */ + if (!strlen(optarg)) + usage(h, argv[0]); + if ((config_dump_format = format_str2int(optarg)) < 0){ + fprintf(stderr, "Unrecognized dump format: %s(expected: xml|json|text)\n", argv[0]); + usage(h, argv[0]); + } + config_dump++; + break; case 'q': /* quiet: dont write hello */ quiet++; break; @@ -867,6 +879,15 @@ main(int argc, if (clixon_plugin_start_all(h) < 0) goto done; + /* Explicit dump of config (also debug dump below). */ + if (config_dump){ + if (clicon_option_dump1(h, stdout, config_dump_format) < 0) + goto done; + goto ok; + } + /* Debug dump of config options */ + clicon_option_dump(h, 1); + /* Send hello request to backend to get session-id back * This is done once at the beginning of the session and then this is * used by the client, even though new TCP sessions are created for @@ -890,7 +911,6 @@ main(int argc, #endif if (clixon_event_reg_fd(0, netconf_input_cb, h, "netconf socket") < 0) goto done; - clicon_option_dump(h, 1); if (tv.tv_sec || tv.tv_usec){ struct timeval t; gettimeofday(&t, NULL); @@ -900,6 +920,7 @@ main(int argc, } if (clixon_event_loop(h) < 0) goto done; + ok: retval = 0; done: if (ignore_packet_errors) diff --git a/apps/restconf/restconf_main_fcgi.c b/apps/restconf/restconf_main_fcgi.c index 58e7df03..97058c86 100644 --- a/apps/restconf/restconf_main_fcgi.c +++ b/apps/restconf/restconf_main_fcgi.c @@ -88,7 +88,7 @@ #include "restconf_stream.h" /* Command line options to be passed to getopt(3) */ -#define RESTCONF_OPTS "hD:f:E:l:p:d:y:a:u:rW:R:o:" +#define RESTCONF_OPTS "hD:f:E:l:C:p:d:y:a:u:rW:R:o:" /*! Convert FCGI parameters to clixon runtime data * @param[in] h Clixon handle @@ -269,6 +269,7 @@ usage(clicon_handle h, "\t-f \t Configuration file (mandatory)\n" "\t-E \t Extra configuration file directory\n" "\t-l > \tLog on (s)yslog, std(e)rr, std(o)ut, (n)one or (f)ile (syslog is default)\n" + "\t-C \tDump configuration options on stdout after loading. Format is xml|json|text\n" "\t-p \t Yang directory path (see CLICON_YANG_DIR)\n" "\t-y \t Load yang spec file (override yang main module)\n" "\t-a UNIX|IPv4|IPv6 Internal backend socket family\n" @@ -283,8 +284,7 @@ usage(clicon_handle h, exit(0); } -/*! Main routine for fastcgi restconf - */ +/*! Main routine for fastcgi restconf */ int main(int argc, char **argv) @@ -314,6 +314,8 @@ main(int argc, char *wwwuser; char *inline_config = NULL; size_t sz; + int config_dump; + enum format_enum config_dump_format = FORMAT_XML; /* In the startup, logs to stderr & debug flag set later */ clicon_log_init(__PROGRAM__, LOG_INFO, logdst); @@ -389,6 +391,15 @@ main(int argc, case 'E': /* extra config dir */ case 'l': /* log */ break; /* taken care of in earlier getopt above */ + case 'C': /* Explicitly dump configuration */ + if (!strlen(optarg)) + usage(h, argv[0]); + if ((config_dump_format = format_str2int(optarg)) < 0){ + fprintf(stderr, "Unrecognized dump format: %s(expected: xml|json|text)\n", argv[0]); + usage(h, argv[0]); + } + config_dump++; + break; case 'p' : /* yang dir path */ if (clicon_option_add(h, "CLICON_YANG_DIR", optarg) < 0) goto done; @@ -528,6 +539,12 @@ main(int argc, if (clicon_nsctx_global_set(h, nsctx_global) < 0) goto done; + /* Explicit dump of config (also debug dump below). */ + if (config_dump){ + if (clicon_option_dump1(h, stdout, config_dump_format) < 0) + goto done; + goto ok; + } /* Dump configuration options on debug */ clicon_option_dump(h, 1); @@ -664,6 +681,7 @@ main(int argc, } } } /* while */ + ok: retval = 0; done: stream_child_freeall(h); diff --git a/apps/restconf/restconf_main_native.c b/apps/restconf/restconf_main_native.c index e92b029a..c4f71c0a 100644 --- a/apps/restconf/restconf_main_native.c +++ b/apps/restconf/restconf_main_native.c @@ -159,7 +159,7 @@ #endif /* Command line options to be passed to getopt(3) */ -#define RESTCONF_OPTS "hD:f:E:l:p:y:a:u:rW:R:o:" +#define RESTCONF_OPTS "hD:f:E:l:C:p:y:a:u:rW:R:o:" /* If set, open outwards socket non-blocking, as opposed to blocking * Should work both ways, but in the ninblocking case, @@ -1116,6 +1116,7 @@ usage(clicon_handle h, "\t-f \t Configuration file (mandatory)\n" "\t-E \t Extra configuration file directory\n" "\t-l > \tLog on (s)yslog, std(e)rr, std(o)ut, (n)one or (f)ile (syslog is default)\n" + "\t-C \tDump configuration options on stdout after loading and exit. Format is xml|json|text\n" "\t-p \t Yang directory path (see CLICON_YANG_DIR)\n" "\t-y \t Load yang spec file (override yang main module)\n" "\t-a UNIX|IPv4|IPv6 Internal backend socket family\n" @@ -1130,6 +1131,8 @@ usage(clicon_handle h, exit(0); } +/* Clixon native restconf application main entry point + */ int main(int argc, char **argv) @@ -1144,6 +1147,8 @@ main(int argc, int ret; cxobj *xrestconf = NULL; char *inline_config = NULL; + int config_dump = 0; + enum format_enum config_dump_format = FORMAT_XML; /* In the startup, logs to stderr & debug flag set later */ clicon_log_init(__PROGRAM__, LOG_INFO, logdst); @@ -1235,6 +1240,15 @@ main(int argc, case 'E': /* extra config dir */ case 'l': /* log */ break; /* see above */ + case 'C': /* Explicitly dump configuration */ + if (!strlen(optarg)) + usage(h, argv[0]); + if ((config_dump_format = format_str2int(optarg)) < 0){ + fprintf(stderr, "Unrecognized dump format: %s(expected: xml|json|text)\n", argv[0]); + usage(h, argv[0]); + } + config_dump++; + break; case 'p' : /* yang dir path */ if (clicon_option_add(h, "CLICON_YANG_DIR", optarg) < 0) goto done; @@ -1283,6 +1297,12 @@ main(int argc, /* Init restconf auth-type */ restconf_auth_type_set(h, CLIXON_AUTH_NONE); + /* Explicit dump of config (also debug dump below). */ + if (config_dump){ + if (clicon_option_dump1(h, stdout, config_dump_format) < 0) + goto done; + goto ok; + } /* Dump configuration options on debug */ clicon_option_dump(h, 1); @@ -1326,6 +1346,7 @@ main(int argc, /* Main event loop */ if (clixon_event_loop(h) < 0) goto done; + ok: retval = 0; done: clicon_debug(1, "restconf_main_openssl done"); diff --git a/lib/clixon/clixon_options.h b/lib/clixon/clixon_options.h index 59428cf7..f2aab440 100644 --- a/lib/clixon/clixon_options.h +++ b/lib/clixon/clixon_options.h @@ -68,7 +68,6 @@ enum startup_mode_t{ SM_RUNNING, /* Commit running db configuration into running state */ SM_STARTUP, /* Commit startup configuration into running state */ SM_RUNNING_STARTUP, /* First try running db, if it is empty try startup db */ - SM_DUMP_XML /* Dump XML configuration to stdout and exit */ }; /*! See clixon-config.yang type priv_mode (privileges mode) */ @@ -106,9 +105,12 @@ enum regexp_mode{ * Prototypes */ -/* Print registry on file. For debugging. */ +/* Debug dump config options */ int clicon_option_dump(clicon_handle h, int dblevel); +/*! Dump config options on stdio using output format */ +int clicon_option_dump1(clicon_handle h, FILE *f, int format); + /* Add a clicon options overriding file setting */ int clicon_option_add(clicon_handle h, const char *name, char *value); diff --git a/lib/clixon/clixon_xml.h b/lib/clixon/clixon_xml.h index f2a7e3f5..726b5c77 100644 --- a/lib/clixon/clixon_xml.h +++ b/lib/clixon/clixon_xml.h @@ -178,7 +178,9 @@ typedef int (xml_applyfn_t)(cxobj *x, void *arg); typedef struct clixon_xml_vec clixon_xvec; /* struct defined in clicon_xml_vec.c */ -/* Alternative formats */ +/* Alternative tree formats, + * @see format_int2str, format_str2int + */ enum format_enum{ FORMAT_XML, FORMAT_JSON, diff --git a/lib/src/clixon_options.c b/lib/src/clixon_options.c index 3e92c210..8c68a738 100644 --- a/lib/src/clixon_options.c +++ b/lib/src/clixon_options.c @@ -71,6 +71,9 @@ #include "clixon_log.h" #include "clixon_yang.h" #include "clixon_xml.h" +#include "clixon_json.h" +#include "clixon_text_syntax.h" +#include "clixon_proto.h" #include "clixon_options.h" #include "clixon_data.h" #include "clixon_xpath_ctx.h" @@ -90,7 +93,6 @@ static const map_str2int startup_mode_map[] = { {"running", SM_RUNNING}, {"startup", SM_STARTUP}, {"running-startup", SM_RUNNING_STARTUP}, - {"dump-xml", SM_DUMP_XML}, {NULL, -1} }; @@ -129,13 +131,16 @@ static const map_str2int yang_regexp_map[] = { {NULL, -1} }; -/*! Print registry on file. For debugging. + +/*! Debug dump config options * * @param[in] h Clicon handle * @param[in] dbglevel Debug level * @retval 0 OK * @retval -1 Error * @note CLICON_FEATURE, CLICON_YANG_DIR and CLICON_SNMP_MIB are treated specially since they are lists + * @note sub-config structs not shown: eg autocli/restconf + * @see clicon_option_dump1 different formats */ int clicon_option_dump(clicon_handle h, @@ -191,6 +196,47 @@ clicon_option_dump(clicon_handle h, return retval; } +/*! Dump config options on stdio using output format + * + * @param[in] h Clicon handle + * @param[in] f Output file + * @param[in] format Dump output format + * @retval 0 OK + * @retval -1 Error + * @see clicon_option_dump for debug log + */ +int +clicon_option_dump1(clicon_handle h, + FILE *f, + int format) +{ + int retval = -1; + cxobj *xc; + + xc = clicon_conf_xml(h); + switch (format){ + case FORMAT_XML: + if (clixon_xml2file(f, xc, 0, 1, "", cligen_output, 0, 0) < 0) + goto done; + break; + case FORMAT_JSON: + if (clixon_json2file(f, xc, 1, cligen_output, 0, 0) < 0) + goto done; + break; + case FORMAT_TEXT: + if (clixon_txt2file(f, xc, 0, cligen_output, 0, 0) < 0) + goto done; + break; + default: + clicon_err(OE_XML, EINVAL, "%s not supported", format_int2str(format)); + goto done; + break; + } + retval = 0; + done: + return retval; +} + /*! Open and parse single config file * * @param[in] filename diff --git a/lib/src/clixon_proto.c b/lib/src/clixon_proto.c index 7e194c81..630a6be8 100644 --- a/lib/src/clixon_proto.c +++ b/lib/src/clixon_proto.c @@ -87,6 +87,9 @@ struct formatvec{ int fv_int; }; +/*! Translate between int and string of tree formats + * @see eum format_enum + */ static struct formatvec _FORMATS[] = { {"xml", FORMAT_XML}, {"text", FORMAT_TEXT}, diff --git a/test/test_configdir.sh b/test/test_config_dir.sh similarity index 100% rename from test/test_configdir.sh rename to test/test_config_dir.sh index 3b604c95..88b89685 100755 --- a/test/test_configdir.sh +++ b/test/test_config_dir.sh @@ -37,6 +37,7 @@ cat < $cfg EOF +new "Start without configdir as baseline" cat < $cfile1 2 @@ -44,9 +45,9 @@ cat < $cfile1 EOF -new "Start without configdir as baseline" expectpart "$($clixon_cli -1 -f $cfg show options)" 0 'CLICON_MODULE_SET_ID: "1"' 'CLICON_FEATURE: "test1"' --not-- 'CLICON_FEATURE: "test2"' +new "Start with wrong configdir" cat < $cfg $dir/dontexist @@ -62,9 +63,9 @@ cat < $cfg EOF -new "Start with wrong configdir" expectpart "$($clixon_cli -1 -f $cfg -l o show options)" 255 "UNIX error: CLICON_CONFIGDIR:" "opendir: No such file or directory" +new "Start with wrong configdir -E override" rm -f $cfile1 cat < $cfg @@ -81,9 +82,9 @@ cat < $cfg EOF -new "Start with wrong configdir -E override" expectpart "$($clixon_cli -1 -f $cfg -E $cdir show options)" 0 'CLICON_MODULE_SET_ID: "1"' 'CLICON_FEATURE: "test1"' --not-- 'CLICON_FEATURE: "test2"' +new "Start with empty configdir" cat < $cfg $cdir @@ -99,9 +100,9 @@ cat < $cfg EOF -new "Start with empty configdir" expectpart "$($clixon_cli -1 -f $cfg -l o show options)" 0 'CLICON_MODULE_SET_ID: "1"' 'CLICON_FEATURE: "test1"' --not-- 'CLICON_FEATURE: "test2"' +new "Start with 1 extra configfile" cat < $cfile1 2 @@ -112,9 +113,9 @@ cat < $cfile1 EOF -new "Start with 1 extra configfile" expectpart "$($clixon_cli -1 -f $cfg -l o show options)" 0 'CLICON_MODULE_SET_ID: "2"' 'CLICON_FEATURE: "test1"' 'CLICON_FEATURE: "test2"' +new "Start with 2 extra configfiles" cat < $cfile2 3 @@ -122,7 +123,6 @@ cat < $cfile2 EOF -new "Start with 2 extra configfiles" expectpart "$($clixon_cli -1 -f $cfg -l o show options)" 0 'CLICON_MODULE_SET_ID: "3"' 'CLICON_FEATURE: "test1"' 'CLICON_FEATURE: "test2"' 'CLICON_FEATURE: "test3"' new "Start with 2 extra configfiles + command-line" diff --git a/test/test_config_dump.sh b/test/test_config_dump.sh new file mode 100755 index 00000000..4a838a62 --- /dev/null +++ b/test/test_config_dump.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash +# Test -C config dump +# Check config file value, overwrite with -o, overwrite with -E configdir +# Format xml/json/text +# cli, backend, netconf, restconf + +# Magic line must be first in script (see README.md) +s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi + +APPNAME=example + + +cfg=$dir/conf_yang.xml +cfdir=$dir/conf.d +test -d $cfdir || mkdir $cfdir +fyang=$dir/example.yang + +cat < $cfg + + $cfg + $cfdir + ${YANG_INSTALLDIR} + $dir + /usr/local/lib/$APPNAME/backend + $dir + /usr/local/lib/$APPNAME/cli + /usr/local/var/$APPNAME/$APPNAME.sock + /usr/local/var/$APPNAME/$APPNAME.pidfile + $dir + 0 + orig + + false + kw-nokey + + +EOF + +cat < $cfdir/extra + + extradir + +EOF + +cat < $dir/ex.cli +# Clixon example specification +CLICON_MODE="base"; +EOF + +cat < $fyang +module example { + namespace "urn:example:clixon"; + prefix ex; + container table{ + } +} +EOF + +# Extra cmdline opts, first is overwritten, second appended +CMDOPTS='-o CLICON_MODULE_SET=42 -o CLICON_FEATURE="cmdline"' + +new "cli xml" +expectpart "$($clixon_cli -1 -f $cfg -C xml -o CLICON_MODULE_SET=42 -o CLICON_FEATURE="cmdline")" 0 '^' "$dir" "0" "" "kw-nokey" "orig" "cmdline" "extradir" --not-- "42" + +new "backend xml" +expectpart "$(sudo $clixon_backend -1 -f $cfg -s none -C xml -o CLICON_MODULE_SET=42 -o CLICON_FEATURE="cmdline")" 0 '^' "$dir" "0" "" "kw-nokey" "orig" "cmdline" "extradir" --not-- "42" + +new "netconf xml" +expectpart "$($clixon_netconf -q -f $cfg -C xml -o CLICON_MODULE_SET=42 -o CLICON_FEATURE="cmdline")" 0 '^' "$dir" "0" "" "kw-nokey" "orig" "cmdline" "extradir" --not-- "42" + +new "restconf xml" +expectpart "$(sudo $clixon_restconf -f $cfg -C xml -o CLICON_MODULE_SET=42 -o CLICON_FEATURE="cmdline")" 0 '^' "$dir" "0" "" "kw-nokey" "orig" "cmdline" "extradir" --not-- "42" + +new "cli json" +expectpart "$($clixon_cli -1 -f $cfg -C json -o CLICON_MODULE_SET=42 -o CLICON_FEATURE="cmdline")" 0 '"clixon-config:clixon-config": {' '"CLICON_YANG_MAIN_DIR": "/var/tmp/./test_config_dump.sh",' + +new "cli text" +expectpart "$($clixon_cli -1 -f $cfg -C text -o CLICON_MODULE_SET=42 -o CLICON_FEATURE="cmdline")" 0 '^clixon-config:clixon-config {' 'list-keyword-default kw-nokey;' 'CLICON_FEATURE \[' 'extradir' 'orig' 'cmdline' + +rm -rf $dir + +new "endtest" +endtest