New command-line option for dumping configuration options for all clixon applications after load

Removed -s dump
This commit is contained in:
Olof hagsand 2023-08-22 12:41:36 +02:00
parent 0e81e8137b
commit c101799e74
12 changed files with 267 additions and 32 deletions

View file

@ -51,6 +51,9 @@ Developers may need to change their code
### Minor features ### Minor features
* New command-line option for dumping configuration options for all clixon applications after load
* Syntax is `-C <format>`
* Example: `clixon_backend -1C json`
* Removed sending restconf config inline using -R when CLICON_BACKEND_RESTCONF_PROCESS=true * Removed sending restconf config inline using -R when CLICON_BACKEND_RESTCONF_PROCESS=true
* Define RESTCONF_INLINE to revert * Define RESTCONF_INLINE to revert
* Clarified clixon_cli command-line: `clixon_cli [options] [commands] [-- extra-options]` * Clarified clixon_cli command-line: `clixon_cli [options] [commands] [-- extra-options]`

View file

@ -79,7 +79,7 @@
#include "backend_plugin_restconf.h" #include "backend_plugin_restconf.h"
/* Command line options to be passed to getopt(3) */ /* 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" #define BACKEND_LOGFILE "/usr/local/var/clixon_backend.log"
@ -463,6 +463,7 @@ usage(clicon_handle h,
"\t-f <file>\tClixon config file\n" "\t-f <file>\tClixon config file\n"
"\t-E <dir> \tExtra configuration file directory\n" "\t-E <dir> \tExtra configuration file directory\n"
"\t-l <s|e|o|n|f<file>> \tLog on (s)yslog, std(e)rr, std(o)ut, (n)one or (f)ile (syslog is default)\n" "\t-l <s|e|o|n|f<file>> \tLog on (s)yslog, std(e)rr, std(o)ut, (n)one or (f)ile (syslog is default)\n"
"\t-C <format>\tDump configuration options on stdout after loading. Format is xml|json|text\n"
"\t-d <dir>\tSpecify backend plugin directory (default: %s)\n" "\t-d <dir>\tSpecify backend plugin directory (default: %s)\n"
"\t-p <dir>\tAdd Yang directory path (see CLICON_YANG_DIR)\n" "\t-p <dir>\tAdd Yang directory path (see CLICON_YANG_DIR)\n"
"\t-b <dir>\tSpecify datastore directory\n" "\t-b <dir>\tSpecify datastore directory\n"
@ -489,6 +490,8 @@ usage(clicon_handle h,
exit(-1); exit(-1);
} }
/* Clixon backend application main entry point
*/
int int
main(int argc, main(int argc,
char **argv) char **argv)
@ -524,6 +527,8 @@ main(int argc,
size_t cligen_bufthreshold; size_t cligen_bufthreshold;
int dbg; int dbg;
size_t sz; 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 */ /* In the startup, logs to stderr & syslog and debug flag set later */
clicon_log_init(__PROGRAM__, LOG_INFO, logdst); clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
@ -535,7 +540,8 @@ main(int argc,
zap = 0; zap = 0;
extraxml_file = NULL; extraxml_file = NULL;
dbg = 0; dbg = 0;
config_dump = 0;
/* /*
* Command-line options for help, debug, and config-file * Command-line options for help, debug, and config-file
*/ */
@ -607,6 +613,15 @@ main(int argc,
case 'E': /* extra config dir */ case 'E': /* extra config dir */
case 'l' : case 'l' :
break; /* see above */ 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 */ case 'd': /* Plugin directory */
if (!strlen(optarg)) if (!strlen(optarg))
usage(h, argv[0]); usage(h, argv[0]);
@ -941,11 +956,6 @@ main(int argc,
goto done; goto done;
/* if status = STARTUP_INVALID, cbret contains info */ /* if status = STARTUP_INVALID, cbret contains info */
break; 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: default:
break; break;
} }
@ -978,7 +988,6 @@ main(int argc,
/* if status = STARTUP_INVALID, cbret contains info */ /* if status = STARTUP_INVALID, cbret contains info */
} }
} }
if (status != STARTUP_OK){ if (status != STARTUP_OK){
if (cbuf_len(cbret)) if (cbuf_len(cbret))
clicon_log(LOG_NOTICE, "%s: %u %s", __PROGRAM__, getpid(), cbuf_get(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 */ /* Call backend plugin_start with user -- options */
if (clixon_plugin_start_all(h) < 0) if (clixon_plugin_start_all(h) < 0)
goto done; 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 */ /* -1 option to run only once */
if (once) if (once)
goto ok; goto ok;
/* Debug dump of config options */
clicon_option_dump(h, 1);
/* Daemonize and initiate logging. Note error is initiated here to make /* Daemonize and initiate logging. Note error is initiated here to make
daemonized errors OK. Before this stage, errors are logged on stderr daemonized errors OK. Before this stage, errors are logged on stderr
also */ also */
@ -1056,7 +1074,6 @@ main(int argc,
goto done; goto done;
if (clicon_socket_set(h, ss) < 0) if (clicon_socket_set(h, ss) < 0)
goto done; goto done;
clicon_option_dump(h, 1);
/* Depending on configure setting, privileges may be dropped here after /* Depending on configure setting, privileges may be dropped here after
* initializations */ * initializations */

View file

@ -73,7 +73,7 @@
#include "cli_handle.h" #include "cli_handle.h"
/* Command line options to be passed to getopt(3) */ /* 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 /*! 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 * Just log if file does not exist or is not readable
@ -476,6 +476,8 @@ usage(clicon_handle h,
"\t-D <level> \tDebug level\n" "\t-D <level> \tDebug level\n"
"\t-f <file> \tConfig-file (mandatory)\n" "\t-f <file> \tConfig-file (mandatory)\n"
"\t-E <dir> \tExtra configuration file directory\n" "\t-E <dir> \tExtra configuration file directory\n"
"\t-l <s|e|o|n|f<file>> \tLog on (s)yslog, std(e)rr, std(o)ut, (n)one or (f)ile (stderr is default)\n"
"\t-C <format>\tDump configuration options on stdout after loading. Format is xml|json|text\n"
"\t-F <file> \tRead commands from file (default stdin)\n" "\t-F <file> \tRead commands from file (default stdin)\n"
"\t-1\t\tDo not enter interactive mode\n" "\t-1\t\tDo not enter interactive mode\n"
"\t-a UNIX|IPv4|IPv6\tInternal backend socket family\n" "\t-a UNIX|IPv4|IPv6\tInternal backend socket family\n"
@ -486,7 +488,7 @@ usage(clicon_handle h,
"\t-p <dir>\tYang directory path (see CLICON_YANG_DIR)\n" "\t-p <dir>\tYang directory path (see CLICON_YANG_DIR)\n"
"\t-G \t\tPrint auto-cli CLI syntax generated from YANG\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 \t\tDebug print dynamic CLI syntax including completions and expansions\n"
"\t-l <s|e|o|n|f<file>> \tLog on (s)yslog, std(e)rr, std(o)ut, (n)one or (f)ile (stderr is default)\n"
"\t-y <file>\tOverride yang spec file (dont include .yang suffix)\n" "\t-y <file>\tOverride yang spec file (dont include .yang suffix)\n"
"\t-c <file>\tSpecify cli spec file.\n" "\t-c <file>\tSpecify cli spec file.\n"
"\t-U <user>\tOver-ride unix user with a pseudo user for NACM.\n" "\t-U <user>\tOver-ride unix user with a pseudo user for NACM.\n"
@ -522,9 +524,12 @@ main(int argc,
size_t cligen_bufthreshold; size_t cligen_bufthreshold;
int dbg=0; int dbg=0;
int nr; int nr;
int config_dump;
enum format_enum config_dump_format = FORMAT_XML;
/* Defaults */ /* Defaults */
once = 0; once = 0;
config_dump = 0;
/* In the startup, logs to stderr & debug flag set later */ /* In the startup, logs to stderr & debug flag set later */
clicon_log_init(__PROGRAM__, LOG_INFO, logdst); clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
@ -607,6 +612,15 @@ main(int argc,
case 'E': /* extra config dir */ case 'E': /* extra config dir */
case 'l': /* Log destination */ case 'l': /* Log destination */
break; /* see above */ 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 */ case 'F': /* read commands from file */
if (freopen(optarg, "r", stdin) == NULL){ if (freopen(optarg, "r", stdin) == NULL){
fprintf(stderr, "freopen: %s\n", strerror(errno)); fprintf(stderr, "freopen: %s\n", strerror(errno));
@ -833,10 +847,6 @@ main(int argc,
if (logclisyntax) if (logclisyntax)
cli_logsyntax_set(h, logclisyntax); cli_logsyntax_set(h, logclisyntax);
clicon_option_dump(h, 1);
/* Clixon hardcodes variable tie-breaks to non-terminals (2) /* Clixon hardcodes variable tie-breaks to non-terminals (2)
* There are cases in the autocli such as: * There are cases in the autocli such as:
* (<string regexp:"r1" | <string regexp:"r2"){ ... } * (<string regexp:"r1" | <string regexp:"r2"){ ... }
@ -850,6 +860,15 @@ main(int argc,
*/ */
if (clixon_plugin_start_all(h) < 0) if (clixon_plugin_start_all(h) < 0)
goto done; goto done;
/* Explicit dump of config
* (there is also debug dump below).
*/
if (config_dump){
if (clicon_option_dump1(h, stdout, config_dump_format) < 0)
goto done;
}
/* Debug dump of config options */
clicon_option_dump(h, 1);
cligen_line_scrolling_set(cli_cligen(h), clicon_option_int(h,"CLICON_CLI_LINESCROLLING")); cligen_line_scrolling_set(cli_cligen(h), clicon_option_int(h,"CLICON_CLI_LINESCROLLING"));
/*! Start CLI history and load from file */ /*! Start CLI history and load from file */

View file

@ -70,7 +70,7 @@
#include "netconf_rpc.h" #include "netconf_rpc.h"
/* Command line options to be passed to getopt(3) */ /* Command line options to be passed to getopt(3) */
#define NETCONF_OPTS "hD:f:E:l:q01ca:u:d:p:y:U:t:eo:" #define NETCONF_OPTS "hD:f:E:l:C:q01ca:u:d:p:y:U:t:eo:"
#define NETCONF_LOGFILE "/tmp/clixon_netconf.log" #define NETCONF_LOGFILE "/tmp/clixon_netconf.log"
@ -624,6 +624,7 @@ usage(clicon_handle h,
"\t-f <file>\tConfiguration file (mandatory)\n" "\t-f <file>\tConfiguration file (mandatory)\n"
"\t-E <dir> \tExtra configuration file directory\n" "\t-E <dir> \tExtra configuration file directory\n"
"\t-l <s|e|o|n|f<file>> \tLog on (s)yslog, std(e)rr, std(o)ut, (n)one or (f)ile (syslog is default)\n" "\t-l <s|e|o|n|f<file>> \tLog on (s)yslog, std(e)rr, std(o)ut, (n)one or (f)ile (syslog is default)\n"
"\t-C <format>\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-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-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" "\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; size_t cligen_bufthreshold;
int dbg = 0; int dbg = 0;
size_t sz; size_t sz;
int config_dump = 0;
enum format_enum config_dump_format = FORMAT_XML;
/* Create handle */ /* Create handle */
if ((h = clicon_handle_init()) == NULL) if ((h = clicon_handle_init()) == NULL)
@ -728,6 +731,15 @@ main(int argc,
case 'E': /* extra config dir */ case 'E': /* extra config dir */
case 'l': /* log */ case 'l': /* log */
break; /* see above */ 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 */ case 'q': /* quiet: dont write hello */
quiet++; quiet++;
break; break;
@ -867,6 +879,15 @@ main(int argc,
if (clixon_plugin_start_all(h) < 0) if (clixon_plugin_start_all(h) < 0)
goto done; 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 /* Send hello request to backend to get session-id back
* This is done once at the beginning of the session and then this is * 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 * used by the client, even though new TCP sessions are created for
@ -890,7 +911,6 @@ main(int argc,
#endif #endif
if (clixon_event_reg_fd(0, netconf_input_cb, h, "netconf socket") < 0) if (clixon_event_reg_fd(0, netconf_input_cb, h, "netconf socket") < 0)
goto done; goto done;
clicon_option_dump(h, 1);
if (tv.tv_sec || tv.tv_usec){ if (tv.tv_sec || tv.tv_usec){
struct timeval t; struct timeval t;
gettimeofday(&t, NULL); gettimeofday(&t, NULL);
@ -900,6 +920,7 @@ main(int argc,
} }
if (clixon_event_loop(h) < 0) if (clixon_event_loop(h) < 0)
goto done; goto done;
ok:
retval = 0; retval = 0;
done: done:
if (ignore_packet_errors) if (ignore_packet_errors)

View file

@ -88,7 +88,7 @@
#include "restconf_stream.h" #include "restconf_stream.h"
/* Command line options to be passed to getopt(3) */ /* 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 /*! Convert FCGI parameters to clixon runtime data
* @param[in] h Clixon handle * @param[in] h Clixon handle
@ -269,6 +269,7 @@ usage(clicon_handle h,
"\t-f <file>\t Configuration file (mandatory)\n" "\t-f <file>\t Configuration file (mandatory)\n"
"\t-E <dir> \t Extra configuration file directory\n" "\t-E <dir> \t Extra configuration file directory\n"
"\t-l <s|e|o|n|f<file>> \tLog on (s)yslog, std(e)rr, std(o)ut, (n)one or (f)ile (syslog is default)\n" "\t-l <s|e|o|n|f<file>> \tLog on (s)yslog, std(e)rr, std(o)ut, (n)one or (f)ile (syslog is default)\n"
"\t-C <format>\tDump configuration options on stdout after loading. Format is xml|json|text\n"
"\t-p <dir>\t Yang directory path (see CLICON_YANG_DIR)\n" "\t-p <dir>\t Yang directory path (see CLICON_YANG_DIR)\n"
"\t-y <file>\t Load yang spec file (override yang main module)\n" "\t-y <file>\t Load yang spec file (override yang main module)\n"
"\t-a UNIX|IPv4|IPv6 Internal backend socket family\n" "\t-a UNIX|IPv4|IPv6 Internal backend socket family\n"
@ -283,8 +284,7 @@ usage(clicon_handle h,
exit(0); exit(0);
} }
/*! Main routine for fastcgi restconf /*! Main routine for fastcgi restconf */
*/
int int
main(int argc, main(int argc,
char **argv) char **argv)
@ -314,6 +314,8 @@ main(int argc,
char *wwwuser; char *wwwuser;
char *inline_config = NULL; char *inline_config = NULL;
size_t sz; size_t sz;
int config_dump;
enum format_enum config_dump_format = FORMAT_XML;
/* In the startup, logs to stderr & debug flag set later */ /* In the startup, logs to stderr & debug flag set later */
clicon_log_init(__PROGRAM__, LOG_INFO, logdst); clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
@ -389,6 +391,15 @@ main(int argc,
case 'E': /* extra config dir */ case 'E': /* extra config dir */
case 'l': /* log */ case 'l': /* log */
break; /* taken care of in earlier getopt above */ 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 */ case 'p' : /* yang dir path */
if (clicon_option_add(h, "CLICON_YANG_DIR", optarg) < 0) if (clicon_option_add(h, "CLICON_YANG_DIR", optarg) < 0)
goto done; goto done;
@ -528,6 +539,12 @@ main(int argc,
if (clicon_nsctx_global_set(h, nsctx_global) < 0) if (clicon_nsctx_global_set(h, nsctx_global) < 0)
goto done; 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 */ /* Dump configuration options on debug */
clicon_option_dump(h, 1); clicon_option_dump(h, 1);
@ -664,6 +681,7 @@ main(int argc,
} }
} }
} /* while */ } /* while */
ok:
retval = 0; retval = 0;
done: done:
stream_child_freeall(h); stream_child_freeall(h);

View file

@ -159,7 +159,7 @@
#endif #endif
/* Command line options to be passed to getopt(3) */ /* 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 /* If set, open outwards socket non-blocking, as opposed to blocking
* Should work both ways, but in the ninblocking case, * Should work both ways, but in the ninblocking case,
@ -1116,6 +1116,7 @@ usage(clicon_handle h,
"\t-f <file>\t Configuration file (mandatory)\n" "\t-f <file>\t Configuration file (mandatory)\n"
"\t-E <dir> \t Extra configuration file directory\n" "\t-E <dir> \t Extra configuration file directory\n"
"\t-l <s|e|o|n|f<file>> \tLog on (s)yslog, std(e)rr, std(o)ut, (n)one or (f)ile (syslog is default)\n" "\t-l <s|e|o|n|f<file>> \tLog on (s)yslog, std(e)rr, std(o)ut, (n)one or (f)ile (syslog is default)\n"
"\t-C <format>\tDump configuration options on stdout after loading and exit. Format is xml|json|text\n"
"\t-p <dir>\t Yang directory path (see CLICON_YANG_DIR)\n" "\t-p <dir>\t Yang directory path (see CLICON_YANG_DIR)\n"
"\t-y <file>\t Load yang spec file (override yang main module)\n" "\t-y <file>\t Load yang spec file (override yang main module)\n"
"\t-a UNIX|IPv4|IPv6 Internal backend socket family\n" "\t-a UNIX|IPv4|IPv6 Internal backend socket family\n"
@ -1130,6 +1131,8 @@ usage(clicon_handle h,
exit(0); exit(0);
} }
/* Clixon native restconf application main entry point
*/
int int
main(int argc, main(int argc,
char **argv) char **argv)
@ -1144,6 +1147,8 @@ main(int argc,
int ret; int ret;
cxobj *xrestconf = NULL; cxobj *xrestconf = NULL;
char *inline_config = 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 */ /* In the startup, logs to stderr & debug flag set later */
clicon_log_init(__PROGRAM__, LOG_INFO, logdst); clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
@ -1235,6 +1240,15 @@ main(int argc,
case 'E': /* extra config dir */ case 'E': /* extra config dir */
case 'l': /* log */ case 'l': /* log */
break; /* see above */ 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 */ case 'p' : /* yang dir path */
if (clicon_option_add(h, "CLICON_YANG_DIR", optarg) < 0) if (clicon_option_add(h, "CLICON_YANG_DIR", optarg) < 0)
goto done; goto done;
@ -1283,6 +1297,12 @@ main(int argc,
/* Init restconf auth-type */ /* Init restconf auth-type */
restconf_auth_type_set(h, CLIXON_AUTH_NONE); 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 */ /* Dump configuration options on debug */
clicon_option_dump(h, 1); clicon_option_dump(h, 1);
@ -1326,6 +1346,7 @@ main(int argc,
/* Main event loop */ /* Main event loop */
if (clixon_event_loop(h) < 0) if (clixon_event_loop(h) < 0)
goto done; goto done;
ok:
retval = 0; retval = 0;
done: done:
clicon_debug(1, "restconf_main_openssl done"); clicon_debug(1, "restconf_main_openssl done");

View file

@ -68,7 +68,6 @@ enum startup_mode_t{
SM_RUNNING, /* Commit running db configuration into running state */ SM_RUNNING, /* Commit running db configuration into running state */
SM_STARTUP, /* Commit startup 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_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) */ /*! See clixon-config.yang type priv_mode (privileges mode) */
@ -106,9 +105,12 @@ enum regexp_mode{
* Prototypes * Prototypes
*/ */
/* Print registry on file. For debugging. */ /* Debug dump config options */
int clicon_option_dump(clicon_handle h, int dblevel); 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 */ /* Add a clicon options overriding file setting */
int clicon_option_add(clicon_handle h, const char *name, char *value); int clicon_option_add(clicon_handle h, const char *name, char *value);

View file

@ -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 */ 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{ enum format_enum{
FORMAT_XML, FORMAT_XML,
FORMAT_JSON, FORMAT_JSON,

View file

@ -71,6 +71,9 @@
#include "clixon_log.h" #include "clixon_log.h"
#include "clixon_yang.h" #include "clixon_yang.h"
#include "clixon_xml.h" #include "clixon_xml.h"
#include "clixon_json.h"
#include "clixon_text_syntax.h"
#include "clixon_proto.h"
#include "clixon_options.h" #include "clixon_options.h"
#include "clixon_data.h" #include "clixon_data.h"
#include "clixon_xpath_ctx.h" #include "clixon_xpath_ctx.h"
@ -90,7 +93,6 @@ static const map_str2int startup_mode_map[] = {
{"running", SM_RUNNING}, {"running", SM_RUNNING},
{"startup", SM_STARTUP}, {"startup", SM_STARTUP},
{"running-startup", SM_RUNNING_STARTUP}, {"running-startup", SM_RUNNING_STARTUP},
{"dump-xml", SM_DUMP_XML},
{NULL, -1} {NULL, -1}
}; };
@ -129,13 +131,16 @@ static const map_str2int yang_regexp_map[] = {
{NULL, -1} {NULL, -1}
}; };
/*! Print registry on file. For debugging.
/*! Debug dump config options
* *
* @param[in] h Clicon handle * @param[in] h Clicon handle
* @param[in] dbglevel Debug level * @param[in] dbglevel Debug level
* @retval 0 OK * @retval 0 OK
* @retval -1 Error * @retval -1 Error
* @note CLICON_FEATURE, CLICON_YANG_DIR and CLICON_SNMP_MIB are treated specially since they are lists * @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 int
clicon_option_dump(clicon_handle h, clicon_option_dump(clicon_handle h,
@ -191,6 +196,47 @@ clicon_option_dump(clicon_handle h,
return retval; 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 /*! Open and parse single config file
* *
* @param[in] filename * @param[in] filename

View file

@ -87,6 +87,9 @@ struct formatvec{
int fv_int; int fv_int;
}; };
/*! Translate between int and string of tree formats
* @see eum format_enum
*/
static struct formatvec _FORMATS[] = { static struct formatvec _FORMATS[] = {
{"xml", FORMAT_XML}, {"xml", FORMAT_XML},
{"text", FORMAT_TEXT}, {"text", FORMAT_TEXT},

View file

@ -37,6 +37,7 @@ cat <<EOF > $cfg
</clixon-config> </clixon-config>
EOF EOF
new "Start without configdir as baseline"
cat <<EOF > $cfile1 cat <<EOF > $cfile1
<clixon-config xmlns="http://clicon.org/config"> <clixon-config xmlns="http://clicon.org/config">
<CLICON_MODULE_SET_ID>2</CLICON_MODULE_SET_ID> <CLICON_MODULE_SET_ID>2</CLICON_MODULE_SET_ID>
@ -44,9 +45,9 @@ cat <<EOF > $cfile1
</clixon-config> </clixon-config>
EOF 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"' 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 <<EOF > $cfg cat <<EOF > $cfg
<clixon-config xmlns="http://clicon.org/config"> <clixon-config xmlns="http://clicon.org/config">
<CLICON_CONFIGDIR>$dir/dontexist</CLICON_CONFIGDIR> <CLICON_CONFIGDIR>$dir/dontexist</CLICON_CONFIGDIR>
@ -62,9 +63,9 @@ cat <<EOF > $cfg
</clixon-config> </clixon-config>
EOF 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" 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 rm -f $cfile1
cat <<EOF > $cfg cat <<EOF > $cfg
<clixon-config xmlns="http://clicon.org/config"> <clixon-config xmlns="http://clicon.org/config">
@ -81,9 +82,9 @@ cat <<EOF > $cfg
</clixon-config> </clixon-config>
EOF 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"' 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 <<EOF > $cfg cat <<EOF > $cfg
<clixon-config xmlns="http://clicon.org/config"> <clixon-config xmlns="http://clicon.org/config">
<CLICON_CONFIGDIR>$cdir</CLICON_CONFIGDIR> <CLICON_CONFIGDIR>$cdir</CLICON_CONFIGDIR>
@ -99,9 +100,9 @@ cat <<EOF > $cfg
</clixon-config> </clixon-config>
EOF 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"' 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 <<EOF > $cfile1 cat <<EOF > $cfile1
<clixon-config xmlns="http://clicon.org/config"> <clixon-config xmlns="http://clicon.org/config">
<CLICON_MODULE_SET_ID>2</CLICON_MODULE_SET_ID> <CLICON_MODULE_SET_ID>2</CLICON_MODULE_SET_ID>
@ -112,9 +113,9 @@ cat <<EOF > $cfile1
</clixon-config> </clixon-config>
EOF 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"' 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 <<EOF > $cfile2 cat <<EOF > $cfile2
<clixon-config xmlns="http://clicon.org/config"> <clixon-config xmlns="http://clicon.org/config">
<CLICON_MODULE_SET_ID>3</CLICON_MODULE_SET_ID> <CLICON_MODULE_SET_ID>3</CLICON_MODULE_SET_ID>
@ -122,7 +123,6 @@ cat <<EOF > $cfile2
</clixon-config> </clixon-config>
EOF 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"' 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" new "Start with 2 extra configfiles + command-line"

83
test/test_config_dump.sh Executable file
View file

@ -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 <<EOF > $cfg
<clixon-config xmlns="http://clicon.org/config">
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
<CLICON_CONFIGDIR>$cfdir</CLICON_CONFIGDIR>
<CLICON_YANG_DIR>${YANG_INSTALLDIR}</CLICON_YANG_DIR>
<CLICON_YANG_MAIN_DIR>$dir</CLICON_YANG_MAIN_DIR>
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
<CLICON_CLISPEC_DIR>$dir</CLICON_CLISPEC_DIR>
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
<CLICON_XMLDB_DIR>$dir</CLICON_XMLDB_DIR>
<CLICON_MODULE_SET_ID>0</CLICON_MODULE_SET_ID>
<CLICON_FEATURE>orig</CLICON_FEATURE>
<autocli>
<module-default>false</module-default>
<list-keyword-default>kw-nokey</list-keyword-default>
</autocli>
</clixon-config>
EOF
cat <<EOF > $cfdir/extra
<clixon-config xmlns="http://clicon.org/config">
<CLICON_FEATURE>extradir</CLICON_FEATURE>
</clixon-config>
EOF
cat <<EOF > $dir/ex.cli
# Clixon example specification
CLICON_MODE="base";
EOF
cat <<EOF > $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 '^<clixon-config xmlns="http://clicon.org/config">' "<CLICON_YANG_MAIN_DIR>$dir</CLICON_YANG_MAIN_DIR>" "<CLICON_MODULE_SET_ID>0</CLICON_MODULE_SET_ID>" "<autocli>" "<list-keyword-default>kw-nokey</list-keyword-default>" "<CLICON_FEATURE>orig</CLICON_FEATURE>" "<CLICON_FEATURE>cmdline</CLICON_FEATURE>" "<CLICON_FEATURE>extradir</CLICON_FEATURE>" --not-- "<CLICON_MODULE_SET_ID>42</CLICON_MODULE_SET_ID>"
new "backend xml"
expectpart "$(sudo $clixon_backend -1 -f $cfg -s none -C xml -o CLICON_MODULE_SET=42 -o CLICON_FEATURE="cmdline")" 0 '^<clixon-config xmlns="http://clicon.org/config">' "<CLICON_YANG_MAIN_DIR>$dir</CLICON_YANG_MAIN_DIR>" "<CLICON_MODULE_SET_ID>0</CLICON_MODULE_SET_ID>" "<autocli>" "<list-keyword-default>kw-nokey</list-keyword-default>" "<CLICON_FEATURE>orig</CLICON_FEATURE>" "<CLICON_FEATURE>cmdline</CLICON_FEATURE>" "<CLICON_FEATURE>extradir</CLICON_FEATURE>" --not-- "<CLICON_MODULE_SET_ID>42</CLICON_MODULE_SET_ID>"
new "netconf xml"
expectpart "$($clixon_netconf -q -f $cfg -C xml -o CLICON_MODULE_SET=42 -o CLICON_FEATURE="cmdline")" 0 '^<clixon-config xmlns="http://clicon.org/config">' "<CLICON_YANG_MAIN_DIR>$dir</CLICON_YANG_MAIN_DIR>" "<CLICON_MODULE_SET_ID>0</CLICON_MODULE_SET_ID>" "<autocli>" "<list-keyword-default>kw-nokey</list-keyword-default>" "<CLICON_FEATURE>orig</CLICON_FEATURE>" "<CLICON_FEATURE>cmdline</CLICON_FEATURE>" "<CLICON_FEATURE>extradir</CLICON_FEATURE>" --not-- "<CLICON_MODULE_SET_ID>42</CLICON_MODULE_SET_ID>"
new "restconf xml"
expectpart "$(sudo $clixon_restconf -f $cfg -C xml -o CLICON_MODULE_SET=42 -o CLICON_FEATURE="cmdline")" 0 '^<clixon-config xmlns="http://clicon.org/config">' "<CLICON_YANG_MAIN_DIR>$dir</CLICON_YANG_MAIN_DIR>" "<CLICON_MODULE_SET_ID>0</CLICON_MODULE_SET_ID>" "<autocli>" "<list-keyword-default>kw-nokey</list-keyword-default>" "<CLICON_FEATURE>orig</CLICON_FEATURE>" "<CLICON_FEATURE>cmdline</CLICON_FEATURE>" "<CLICON_FEATURE>extradir</CLICON_FEATURE>" --not-- "<CLICON_MODULE_SET_ID>42</CLICON_MODULE_SET_ID>"
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