[provide support for load config of cli format along with json and xml format as save config is supported for all 3 formats](https://github.com/clicon/clixon/issues/320)
This commit is contained in:
parent
3d648bc08f
commit
1a9def2f6e
4 changed files with 102 additions and 2 deletions
|
|
@ -64,6 +64,7 @@ Users may have to change how they access the system
|
||||||
|
|
||||||
### Minor features
|
### Minor features
|
||||||
|
|
||||||
|
* [provide support for load config of cli format along with json and xml format as save config is supported for all 3 formats](https://github.com/clicon/clixon/issues/320)
|
||||||
* [prevent clixon-restconf@2021-05-20.yang module from loading](https://github.com/clicon/clixon/issues/318)
|
* [prevent clixon-restconf@2021-05-20.yang module from loading](https://github.com/clicon/clixon/issues/318)
|
||||||
* Instead of always loading it, load it to datastore YANGs only if `CLICON_BACKEND_RESTCONF_PROCESS` is `true`
|
* Instead of always loading it, load it to datastore YANGs only if `CLICON_BACKEND_RESTCONF_PROCESS` is `true`
|
||||||
* YANG unique: added single descendant node ids as special case
|
* YANG unique: added single descendant node ids as special case
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@
|
||||||
#include <clixon/clixon.h>
|
#include <clixon/clixon.h>
|
||||||
|
|
||||||
#include "clixon_cli_api.h"
|
#include "clixon_cli_api.h"
|
||||||
|
#include "cli_plugin.h"
|
||||||
#include "cli_common.h"
|
#include "cli_common.h"
|
||||||
|
|
||||||
/*! Register log notification stream
|
/*! Register log notification stream
|
||||||
|
|
@ -867,6 +868,36 @@ load_config_file(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case FORMAT_CLI:
|
||||||
|
{
|
||||||
|
char *mode = cli_syntax_mode(h);
|
||||||
|
cligen_result result; /* match result */
|
||||||
|
int evalresult = 0; /* if result == 1, calback result */
|
||||||
|
char *lineptr = NULL;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
while(!cligen_exiting(cli_cligen(h))) {
|
||||||
|
lineptr = NULL; n = 0;
|
||||||
|
if (getline(&lineptr, &n, fp) < 0){
|
||||||
|
if (errno){
|
||||||
|
clicon_err(OE_UNIX, errno, "getline");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
goto ok; /* eof, skip backend rpc since this is done by cli code */
|
||||||
|
}
|
||||||
|
if (clicon_parse(h, lineptr, &mode, &result, &evalresult) < 0)
|
||||||
|
goto done;
|
||||||
|
if (result != 1) /* Not unique match */
|
||||||
|
goto done;
|
||||||
|
if (evalresult < 0)
|
||||||
|
goto done;
|
||||||
|
if (lineptr){
|
||||||
|
free(lineptr);
|
||||||
|
lineptr = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
clicon_err(OE_PLUGIN, 0, "format: %s not implemented", formatstr);
|
clicon_err(OE_PLUGIN, 0, "format: %s not implemented", formatstr);
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -888,6 +919,7 @@ load_config_file(clicon_handle h,
|
||||||
cbuf_get(cbxml)) < 0)
|
cbuf_get(cbxml)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
cbuf_free(cbxml);
|
cbuf_free(cbxml);
|
||||||
|
ok:
|
||||||
ret = 0;
|
ret = 0;
|
||||||
done:
|
done:
|
||||||
if (xerr)
|
if (xerr)
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ show("Show a particular state of the system"){
|
||||||
}
|
}
|
||||||
configuration("Show configuration"), cli_auto_show("datamodel", "candidate", "text", true, false);{
|
configuration("Show configuration"), cli_auto_show("datamodel", "candidate", "text", true, false);{
|
||||||
xml("Show configuration as XML"), cli_auto_show("datamodel", "candidate", "xml", true, false);
|
xml("Show configuration as XML"), cli_auto_show("datamodel", "candidate", "xml", true, false);
|
||||||
cli("Show configuration as CLI commands"), cli_auto_show("datamodel", "candidate", "cli", true, false, "set ");
|
oad cli("Show configuration as CLI commands"), cli_auto_show("datamodel", "candidate", "cli", true, false, "set ");
|
||||||
netconf("Show configuration as netconf edit-config operation"), cli_auto_show("datamodel", "candidate", "netconf", true, false);
|
netconf("Show configuration as netconf edit-config operation"), cli_auto_show("datamodel", "candidate", "netconf", true, false);
|
||||||
text("Show configuration as text"), cli_auto_show("datamodel", "candidate", "text", true, false);
|
text("Show configuration as text"), cli_auto_show("datamodel", "candidate", "text", true, false);
|
||||||
json("Show configuration as JSON"), cli_auto_show("datamodel", "candidate", "json", true, false);
|
json("Show configuration as JSON"), cli_auto_show("datamodel", "candidate", "json", true, false);
|
||||||
|
|
@ -105,10 +105,12 @@ save("Save candidate configuration to XML file") <filename:string>("Filename (lo
|
||||||
}
|
}
|
||||||
load("Load configuration from XML file") <filename:string>("Filename (local filename)"),load_config_file("filename", "replace");{
|
load("Load configuration from XML file") <filename:string>("Filename (local filename)"),load_config_file("filename", "replace");{
|
||||||
replace("Replace candidate with file contents"), load_config_file("filename", "replace");{
|
replace("Replace candidate with file contents"), load_config_file("filename", "replace");{
|
||||||
|
cli("Replace candidate with file containing CLI commands"), load_config_file("","filename", "replace", "cli");
|
||||||
xml("Replace candidate with file containing XML"), load_config_file("","filename", "replace", "xml");
|
xml("Replace candidate with file containing XML"), load_config_file("","filename", "replace", "xml");
|
||||||
json("Replace candidate with file containing JSON"), load_config_file("","filename", "replace", "json");
|
json("Replace candidate with file containing JSON"), load_config_file("","filename", "replace", "json");
|
||||||
}
|
}
|
||||||
merge("Merge file with existent candidate"), load_config_file("filename", "merge");{
|
merge("Merge file with existent candidate"), load_config_file("filename", "merge");{
|
||||||
|
cli("Merge candidate with file containing CLI commands"), load_config_file("","filename", "merge", "cli");
|
||||||
xml("Merge candidate with file containing XML"), load_config_file("","filename", "merge", "xml");
|
xml("Merge candidate with file containing XML"), load_config_file("","filename", "merge", "xml");
|
||||||
json("Merge candidate with file containing JSON"), load_config_file("","filename", "merge", "json");
|
json("Merge candidate with file containing JSON"), load_config_file("","filename", "merge", "json");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,12 @@ APPNAME=example
|
||||||
# include err() and new() functions and creates $dir
|
# include err() and new() functions and creates $dir
|
||||||
|
|
||||||
cfg=$dir/conf_yang.xml
|
cfg=$dir/conf_yang.xml
|
||||||
|
clidir=$dir/cli
|
||||||
|
if [ -d $clidir ]; then
|
||||||
|
rm -rf $clidir/*
|
||||||
|
else
|
||||||
|
mkdir $clidir
|
||||||
|
fi
|
||||||
|
|
||||||
# Use yang in example
|
# Use yang in example
|
||||||
|
|
||||||
|
|
@ -27,13 +33,62 @@ cat <<EOF > $cfg
|
||||||
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
||||||
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
||||||
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||||
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
<CLICON_CLISPEC_DIR>$clidir</CLICON_CLISPEC_DIR>
|
||||||
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||||
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||||
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||||
</clixon-config>
|
</clixon-config>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
cat <<EOF > $clidir/ex.cli
|
||||||
|
# Clixon example specification
|
||||||
|
CLICON_MODE="example";
|
||||||
|
CLICON_PROMPT="%U@%H %W> ";
|
||||||
|
CLICON_PLUGIN="example_cli";
|
||||||
|
|
||||||
|
set @datamodel, cli_auto_set();
|
||||||
|
delete("Delete a configuration item") {
|
||||||
|
@datamodel, cli_auto_del();
|
||||||
|
all("Delete whole candidate configuration"), delete_all("candidate");
|
||||||
|
}
|
||||||
|
validate("Validate changes"), cli_validate();
|
||||||
|
commit("Commit the changes"), cli_commit();
|
||||||
|
quit("Quit"), cli_quit();
|
||||||
|
shell("System command") <source:rest>, cli_start_shell();
|
||||||
|
copy("Copy and create a new object"){
|
||||||
|
interface("Copy interface"){
|
||||||
|
(<name:string>|<name:string expand_dbvar("candidate","/ietf-interfaces:interfaces/interface=%s/name")>("name of interface to copy from")) to("Copy to interface") <toname:string>("Name of interface to copy to"), cli_copy_config("candidate","//interface[%s='%s']","urn:ietf:params:xml:ns:yang:ietf-interfaces","name","name","toname");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
discard("Discard edits (rollback 0)"), discard_changes();
|
||||||
|
|
||||||
|
|
||||||
|
debug("Debugging parts of the system"){
|
||||||
|
cli("Set cli debug") <level:int32>("Set debug level (0..n)"), cli_debug_cli();
|
||||||
|
}
|
||||||
|
show("Show a particular state of the system"){
|
||||||
|
xpath("Show configuration") <xpath:string>("XPATH expression") <ns:string>("Namespace"), show_conf_xpath("candidate");
|
||||||
|
compare("Compare candidate and running databases"), compare_dbs((int32)0);{
|
||||||
|
xml("Show comparison in xml"), compare_dbs((int32)0);
|
||||||
|
text("Show comparison in text"), compare_dbs((int32)1);
|
||||||
|
}
|
||||||
|
configuration("Show configuration"), cli_auto_show("datamodel", "candidate", "text", true, false);{
|
||||||
|
cli("Show configuration as CLI commands"), cli_auto_show("datamodel", "candidate", "cli", true, false, "set ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
save("Save candidate configuration to XML file") <filename:string>("Filename (local filename)"), save_config_file("candidate","filename", "xml");
|
||||||
|
load("Load configuration from XML file") <filename:string>("Filename (local filename)"),load_config_file("filename", "replace");
|
||||||
|
|
||||||
|
rpc("example rpc") <a:string>("routing instance"), example_client_rpc("");
|
||||||
|
|
||||||
|
# Special cli bug with choice+dbexpand, part1 set db symbol
|
||||||
|
choicebug {
|
||||||
|
<name:string choice:foobar>;
|
||||||
|
<name:string expand_dbvar("candidate","/clixon-example:table/parameter/name")>;
|
||||||
|
}
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
new "test params: -f $cfg"
|
new "test params: -f $cfg"
|
||||||
if [ $BE -ne 0 ]; then
|
if [ $BE -ne 0 ]; then
|
||||||
new "kill old backend"
|
new "kill old backend"
|
||||||
|
|
@ -132,6 +187,16 @@ new "cli rpc"
|
||||||
# We dont know which message-id the cli app uses
|
# We dont know which message-id the cli app uses
|
||||||
expectpart "$($clixon_cli -1 -f $cfg -l o rpc ipv4)" 0 "<rpc-reply $DEFAULTONLY message-id=" "><x xmlns=\"urn:example:clixon\">ipv4</x><y xmlns=\"urn:example:clixon\">42</y></rpc-reply>"
|
expectpart "$($clixon_cli -1 -f $cfg -l o rpc ipv4)" 0 "<rpc-reply $DEFAULTONLY message-id=" "><x xmlns=\"urn:example:clixon\">ipv4</x><y xmlns=\"urn:example:clixon\">42</y></rpc-reply>"
|
||||||
|
|
||||||
|
new "cli bug with choice+dbexpand, part1 set db symbol"
|
||||||
|
expectpart "$($clixon_cli -1 -f $cfg set table parameter foobar)" 0 "^$"
|
||||||
|
|
||||||
|
# Here can be error: ambiguous
|
||||||
|
new "cli bug with choice+dbexpand: part2, make same choice"
|
||||||
|
expectpart "$($clixon_cli -1 -f $cfg choicebug foobar)" 0 "^$"
|
||||||
|
|
||||||
|
new "cli discard"
|
||||||
|
expectpart "$($clixon_cli -1 -f $cfg discard)" 0 "^$"
|
||||||
|
|
||||||
if [ $BE -ne 0 ]; then
|
if [ $BE -ne 0 ]; then
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
# Check if premature kill
|
# Check if premature kill
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue