Fixed: [Duplicate config files in configdir causes merge problems -> set ? = NULL](https://github.com/clicon/clixon/issues/510)

Made file-dir match more exact, eg .cli not ?cli
Added -1 as any arg to xml_rm_children()
This commit is contained in:
Olof hagsand 2024-04-11 12:02:08 +02:00
parent e55e05353f
commit 344786a971
12 changed files with 76 additions and 28 deletions

View file

@ -24,6 +24,10 @@ Expected: June 2024
* New `clixon-lib@2024-04-01.yang` revision * New `clixon-lib@2024-04-01.yang` revision
- Added: Default format - Added: Default format
### Corrected Bugs
* Fixed: [Duplicate config files in configdir causes merge problems -> set ? = NULL](https://github.com/clicon/clixon/issues/510)
## 7.0.1 ## 7.0.1
3 April 2024 3 April 2024

View file

@ -413,7 +413,7 @@ clispec_load(clixon_handle h)
/* Load all clispec .cli files in directory */ /* Load all clispec .cli files in directory */
if (clispec_dir){ if (clispec_dir){
/* Get directory list of files */ /* Get directory list of files */
if ((ndp = clicon_file_dirent(clispec_dir, &dp, "(.cli)$", S_IFREG)) < 0) if ((ndp = clicon_file_dirent(clispec_dir, &dp, "\\.cli$", S_IFREG)) < 0)
goto done; goto done;
/* Load the syntax parse trees into cli_syntax stx structure */ /* Load the syntax parse trees into cli_syntax stx structure */
for (i = 0; i < ndp; i++) { for (i = 0; i < ndp; i++) {

View file

@ -43,5 +43,5 @@ CLICON_MODE="|example_pipe"; # Must start with |
json("JSON"), pipe_showas_fn("json"); json("JSON"), pipe_showas_fn("json");
text("Text curly braces"), pipe_showas_fn("text"); text("Text curly braces"), pipe_showas_fn("text");
} }
save("Save configuration to file") <filename:string>("Filename (local filename)"), pipe_save_file("filename"); save("Save to file") <filename:string>("Local filename"), pipe_save_file("filename");
} }

View file

@ -39,7 +39,6 @@
#ifndef _CLIXON_FILE_H_ #ifndef _CLIXON_FILE_H_
#define _CLIXON_FILE_H_ #define _CLIXON_FILE_H_
int clicon_file_dirent(const char *dir, struct dirent **ent, int clicon_file_dirent(const char *dir, struct dirent **ent,
const char *regexp, mode_t type); const char *regexp, mode_t type);
int clicon_files_recursive(const char *dir, const char *regexp, cvec *cvv); int clicon_files_recursive(const char *dir, const char *regexp, cvec *cvv);

View file

@ -177,7 +177,7 @@ clicon_files_recursive(const char *dir,
* @code * @code
* char *dir = "/root/fs"; * char *dir = "/root/fs";
* struct dirent *dp; * struct dirent *dp;
* if ((ndp = clicon_file_dirent(dir, &dp, "(.so)$", S_IFREG)) < 0) * if ((ndp = clicon_file_dirent(dir, &dp, "\\.so$", S_IFREG)) < 0)
* return -1; * return -1;
* for (i = 0; i < ndp; i++) * for (i = 0; i < ndp; i++)
* do something with dp[i].d_name; * do something with dp[i].d_name;

View file

@ -295,6 +295,12 @@ parse_configfile_one(clixon_handle h,
} }
/*! Merge XML sub config file into main config-file /*! Merge XML sub config file into main config-file
*
* @param[in] h Clixon handle
* @param[in] xt Existing target XML
* @param[in] xe Source XML (merge this to xt)
* @retval 0 OK
* @retval -1 Error
*/ */
static int static int
merge_control_xml(clixon_handle h, merge_control_xml(clixon_handle h,
@ -307,6 +313,7 @@ merge_control_xml(clixon_handle h,
cxobj *xec; cxobj *xec;
cxobj *xtc; cxobj *xtc;
cxobj *x; cxobj *x;
// int ret;
/* One could have used xml_merge, but there are several special conditions */ /* One could have used xml_merge, but there are several special conditions */
xec = NULL; xec = NULL;
@ -315,7 +322,9 @@ merge_control_xml(clixon_handle h,
continue; continue;
if ((body = xml_body(xec)) == NULL){ if ((body = xml_body(xec)) == NULL){
if ((xtc = xml_find_type(xt, NULL, name, CX_ELMNT)) != NULL){ if ((xtc = xml_find_type(xt, NULL, name, CX_ELMNT)) != NULL){
if (merge_control_xml(h, xtc, xec) < 0) if (xml_rm_children(xtc, -1) < 0)
goto done;
if (xml_copy(xec, xtc) < 0)
goto done; goto done;
} }
else{ else{
@ -332,25 +341,31 @@ merge_control_xml(clixon_handle h,
continue; continue;
} }
/* List options for configure options that are lists or leaf-lists: append to main */ /* List options for configure options that are lists or leaf-lists: append to main */
if (strcmp(name,"CLICON_FEATURE")==0 || if (strcmp(name,"CLICON_FEATURE") == 0 ||
strcmp(name,"CLICON_YANG_DIR")==0 || strcmp(name,"CLICON_YANG_DIR") == 0 ||
strcmp(name,"CLICON_SNMP_MIB")==0){ strcmp(name,"CLICON_SNMP_MIB") == 0){
if ((x = xml_dup(xec)) == NULL) if ((x = xml_dup(xec)) == NULL)
goto done; goto done;
if (xml_addsub(xt, x) < 0) if (xml_addsub(xt, x) < 0)
goto done; goto done;
continue; continue;
} }
/* Overwrite: remove existing in master if any */ /* Replace existing */
if ((x = xml_find_type(xt, NULL, name, CX_ELMNT)) != NULL) xtc = xml_find_type(xt, NULL, name, CX_ELMNT);
xml_purge(x); if (xtc != NULL){
if (xml_rm_children(xtc, -1) < 0)
goto done;
if (xml_copy(xec, xtc) < 0)
goto done;
}
else {
/* Copy and add to master */ /* Copy and add to master */
if ((x = xml_dup(xec)) == NULL) if ((x = xml_dup(xec)) == NULL)
goto done; goto done;
if (xml_addsub(xt, x) < 0) if (xml_addsub(xt, x) < 0)
goto done; goto done;
} }
}
retval = 0; retval = 0;
done: done:
return retval; return retval;
@ -423,7 +438,7 @@ parse_configfile(clixon_handle h,
goto done; goto done;
} }
closedir(dirp); closedir(dirp);
if((ndp = clicon_file_dirent(extraconfdir, &dp, NULL, S_IFREG)) < 0) /* Read dir */ if((ndp = clicon_file_dirent(extraconfdir, &dp, "\\.xml$", S_IFREG)) < 0) /* Read dir */
goto done; goto done;
/* Loop through files */ /* Loop through files */
for (i = 0; i < ndp; i++){ for (i = 0; i < ndp; i++){
@ -489,7 +504,7 @@ parse_configfile(clixon_handle h,
strlen(body)+1) == NULL) strlen(body)+1) == NULL)
goto done; goto done;
} }
xml_sort(xt); xml_sort_recurse(xt);
retval = 0; retval = 0;
*xconfig = xt; *xconfig = xt;
xt = NULL; xt = NULL;

View file

@ -424,7 +424,7 @@ clixon_plugins_load(clixon_handle h,
goto done; goto done;
} }
/* Get plugin objects names from plugin directory */ /* Get plugin objects names from plugin directory */
if((ndp = clicon_file_dirent(dir, &dp, regexp?regexp:"(.so)$", S_IFREG)) < 0) if((ndp = clicon_file_dirent(dir, &dp, regexp?regexp:"\\.so$", S_IFREG)) < 0)
goto done; goto done;
/* Load all plugins */ /* Load all plugins */
for (i = 0; i < ndp; i++) { for (i = 0; i < ndp; i++) {

View file

@ -1575,7 +1575,7 @@ xml_rm_children(cxobj *xp,
return 0; return 0;
for (i=0; i<xml_child_nr(xp);){ for (i=0; i<xml_child_nr(xp);){
xc = xml_child_i(xp, i); xc = xml_child_i(xp, i);
if (xml_type(xc) != type){ if (type != -1 && xml_type(xc) != type){
i++; i++;
continue; continue;
} }

View file

@ -1682,7 +1682,7 @@ yang_spec_load_dir(clixon_handle h,
* a@2000-01-01.yang, * a@2000-01-01.yang,
* a@2111-11-11.yang * a@2111-11-11.yang
*/ */
if((ndp = clicon_file_dirent(dir, &dp, "(.yang)$", S_IFREG)) < 0) if((ndp = clicon_file_dirent(dir, &dp, "\\.yang$", S_IFREG)) < 0)
goto done; goto done;
if (ndp == 0) if (ndp == 0)
goto ok; goto ok;

View file

@ -19,10 +19,13 @@ APPNAME=example
cfg=$dir/conf_yang.xml cfg=$dir/conf_yang.xml
cdir=$dir/conf.d cdir=$dir/conf.d
cfile1=$cdir/00a.xml cfile1=$cdir/01a.xml
cfile2=$cdir/01a.xml cfile2=$cdir/02a.xml
cfile3=$cdir/03a.xml
cfile4=$cdir/04a.xxxml
test -d $cdir || mkdir $cdir rm -rf $cdir
mkdir $cdir
cat <<EOF > $cfg cat <<EOF > $cfg
<clixon-config xmlns="http://clicon.org/config"> <clixon-config xmlns="http://clicon.org/config">
@ -39,6 +42,8 @@ EOF
# dummy # dummy
touch $dir/spec.cli touch $dir/spec.cli
new "test params: -f $cfg"
new "Start without configdir as baseline" 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">
@ -139,6 +144,29 @@ expectpart "$($clixon_cli -1 -f $cfg -C xml)" 0 "<CLICON_MODULE_SET_ID>3</CLICON
new "Start with 2 extra configfiles + command-line -C xml" new "Start with 2 extra configfiles + command-line -C xml"
expectpart "$($clixon_cli -1 -f $cfg -o CLICON_MODULE_SET_ID=4 -o CLICON_FEATURE=test4 -C xml)" 0 "<CLICON_MODULE_SET_ID>4</CLICON_MODULE_SET_ID>" "<CLICON_FEATURE>test1</CLICON_FEATURE>" "<CLICON_FEATURE>test2</CLICON_FEATURE>" "<CLICON_FEATURE>test3</CLICON_FEATURE>" "<CLICON_FEATURE>test4</CLICON_FEATURE>" expectpart "$($clixon_cli -1 -f $cfg -o CLICON_MODULE_SET_ID=4 -o CLICON_FEATURE=test4 -C xml)" 0 "<CLICON_MODULE_SET_ID>4</CLICON_MODULE_SET_ID>" "<CLICON_FEATURE>test1</CLICON_FEATURE>" "<CLICON_FEATURE>test2</CLICON_FEATURE>" "<CLICON_FEATURE>test3</CLICON_FEATURE>" "<CLICON_FEATURE>test4</CLICON_FEATURE>"
# Ensure two sub-dirs (eg <restconf>) only last is present
cat <<EOF > $cfile3
<clixon-config xmlns="http://clicon.org/config">
<restconf>
<server-cert-path>nisse</server-cert-path>
</restconf>
</clixon-config>
EOF
new "Last <restconf> replaces first"
expectpart "$($clixon_cli -1 -f $cfg -C xml)" 0 "<restconf>" "<server-cert-path>nisse</server-cert-path>" --not-- "<server-cert-path>bar</server-cert-path>"
# Ensure file without .xml suffix is not read
cat <<EOF > $cfile4
<clixon-config xmlns="http://clicon.org/config">
<restconf>
<server-cert-path>laban</server-cert-path>
</restconf>
</clixon-config>
EOF
new "File without .xml is not read"
expectpart "$($clixon_cli -1 -f $cfg -C xml)" 0 "<restconf>" "<server-cert-path>nisse</server-cert-path>" --not-- "<server-cert-path>laban</server-cert-path>"
rm -rf $dir rm -rf $dir
new "endtest" new "endtest"

View file

@ -35,7 +35,7 @@ cat <<EOF > $cfg
</clixon-config> </clixon-config>
EOF EOF
cat <<EOF > $cfdir/extra cat <<EOF > $cfdir/extra.xml
<clixon-config xmlns="http://clicon.org/config"> <clixon-config xmlns="http://clicon.org/config">
<CLICON_FEATURE>extradir</CLICON_FEATURE> <CLICON_FEATURE>extradir</CLICON_FEATURE>
</clixon-config> </clixon-config>
@ -55,6 +55,7 @@ module example {
} }
EOF EOF
new "test params: -f $cfg"
if [ $BE -ne 0 ]; then if [ $BE -ne 0 ]; then
# kill old backend (if any) # kill old backend (if any)
new "kill old backend" new "kill old backend"
@ -64,7 +65,6 @@ if [ $BE -ne 0 ]; then
fi fi
fi fi
# Extra cmdline opts, first is overwritten, second appended # Extra cmdline opts, first is overwritten, second appended
CMDOPTS='-o CLICON_MODULE_SET=42 -o CLICON_FEATURE="cmdline"' CMDOPTS='-o CLICON_MODULE_SET=42 -o CLICON_FEATURE="cmdline"'

View file

@ -469,7 +469,9 @@ module clixon-config {
AFTER the main config file (CLICON_CONFIGFILE) in the following way: AFTER the main config file (CLICON_CONFIGFILE) in the following way:
- leaf values are overwritten - leaf values are overwritten
- leaf-list values are appended - leaf-list values are appended
The files in this directory will be loaded alphabetically. The files in this directory are loaded alphabetically.
Only files ending with .xml are read
Sub-structures, eg <autocli> are replaced with the latest (alphabetically)
If the dir is given but does not exist will result in an error. If the dir is given but does not exist will result in an error.
You can override file setting with -E <dir> command-line option. You can override file setting with -E <dir> command-line option.
Note that due to bootstraping this value is only meaningful in the main config file"; Note that due to bootstraping this value is only meaningful in the main config file";