* Created two sub-files (clixon_validate.c and clixon_api_path.c) from large lib/src/clixon_xml_map.c source file.

This commit is contained in:
Olof hagsand 2020-01-01 11:12:54 +01:00
parent 50420cb262
commit c1903916f9
14 changed files with 2511 additions and 2138 deletions

View file

@ -4,10 +4,11 @@
### Minor changes ### Minor changes
* C-API: Added `xpath_first_localonly()` as an xpath function that skips prefix and namespace checks. * C-API: Added `xpath_first_localonly()` as an xpath function that skips prefix and namespace checks.
* Added experimental code for optizing XPath search using binary search. * Added experimental code for optimizing XPath search using binary search.
* Enable with XPATH_LIST_OPTIMIZE in include/clixon_custom.h * Enable with XPATH_LIST_OPTIMIZE in include/clixon_custom.h
* Optimizes xpaths on the form: `a[b=c]` on sorted, yangified config lists. * Optimizes xpaths on the form: `a[b=c]` on sorted, yangified config lists.
* Removed most assert.h includes * Removed most assert.h includes
* Created two sub-files (clixon_validate.c and clixon_api_path.c) from large lib/src/clixon_xml_map.c source file.
* Added "canonical" global namespace context: `nsctx_global` * Added "canonical" global namespace context: `nsctx_global`
* This is a normalized XML prefix:namespace pair vector computed from all loaded Yang modules. Useful when writing XML and XPATH expressions in callbacks. * This is a normalized XML prefix:namespace pair vector computed from all loaded Yang modules. Useful when writing XML and XPATH expressions in callbacks.
* Get it with `clicon_nsctx_global_get(h)` * Get it with `clicon_nsctx_global_get(h)`

View file

@ -82,7 +82,9 @@
#include <clixon/clixon_options.h> #include <clixon/clixon_options.h>
#include <clixon/clixon_data.h> #include <clixon/clixon_data.h>
#include <clixon/clixon_regex.h> #include <clixon/clixon_regex.h>
#include <clixon/clixon_api_path.h>
#include <clixon/clixon_xml_map.h> #include <clixon/clixon_xml_map.h>
#include <clixon/clixon_validate.h>
#include <clixon/clixon_datastore.h> #include <clixon/clixon_datastore.h>
#include <clixon/clixon_xpath_ctx.h> #include <clixon/clixon_xpath_ctx.h>
#include <clixon/clixon_xpath_optimize.h> #include <clixon/clixon_xpath_optimize.h>

View file

@ -0,0 +1,64 @@
/*
*
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2019 Olof Hagsand and Benny Holmgren
This file is part of CLIXON.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 3 or later (the "GPL"),
in which case the provisions of the GPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of the GPL, and not to allow others to
use your version of this file under the terms of Apache License version 2,
indicate your decision by deleting the provisions above and replace them with
the notice and other provisions required by the GPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the Apache License version 2 or the GPL.
***** END LICENSE BLOCK *****
*
* "api-path" is "URI-encoded path expression" definition in RFC8040 3.5.3
* BNF:
* <api-path> := <root> ("/" (<api-identifier> | <list-instance>))*
* <root> := <string>
* <api-identifier> := [<module-name> ":"] <identifier>
* <module-name> := <identifier>
* <list-instance> := <api-identifier> "=" key-value *("," key-value)
* <key-value> := <string>
* <string> := <an unquoted string>
* <identifier> := (<ALPHA> | "_") (<ALPHA> | <DIGIT> | "_" | "-" | ".")
*/
#ifndef _CLIXON_API_PATH_H_
#define _CLIXON_API_PATH_H_
/*
* Prototypes
*/
int xml_yang_root(cxobj *x, cxobj **xr);
int yang2api_path_fmt(yang_stmt *ys, int inclkey, char **api_path_fmt);
int api_path_fmt2api_path(char *api_path_fmt, cvec *cvv, char **api_path);
int api_path_fmt2xpath(char *api_path_fmt, cvec *cvv, char **xpath);
int api_path2xpath_cvv(cvec *api_path, int offset, yang_stmt *yspec, cbuf *xpath, cvec **nsc, cxobj **xerr);
int api_path2xpath(char *api_path, yang_stmt *yspec, char **xpath, cvec **nsc);
int api_path2xml(char *api_path, yang_stmt *yspec, cxobj *xtop,
yang_class nodeclass, int strict,
cxobj **xpathp, yang_stmt **ypathp, cxobj **xerr);
int xml2api_path_1(cxobj *x, cbuf *cb);
#endif /* _CLIXON_API_PATH_H_ */

View file

@ -0,0 +1,50 @@
/*
*
***** BEGIN LICENSE BLOCK *****
Copyright (C) 2009-2019 Olof Hagsand and Benny Holmgren
This file is part of CLIXON.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Alternatively, the contents of this file may be used under the terms of
the GNU General Public License Version 3 or later (the "GPL"),
in which case the provisions of the GPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of the GPL, and not to allow others to
use your version of this file under the terms of Apache License version 2,
indicate your decision by deleting the provisions above and replace them with
the notice and other provisions required by the GPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the Apache License version 2 or the GPL.
***** END LICENSE BLOCK *****
*
* XML code
*/
#ifndef _CLIXON_VALIDATE_H_
#define _CLIXON_VALIDATE_H_
/*
* Prototypes
*/
int xml_yang_validate_rpc(clicon_handle h, cxobj *xrpc, cxobj **xret);
int xml_yang_validate_add(clicon_handle h, cxobj *xt, cxobj **xret);
int xml_yang_validate_list_key_only(clicon_handle h, cxobj *xt, cxobj **xret);
int xml_yang_validate_all(clicon_handle h, cxobj *xt, cxobj **xret);
int xml_yang_validate_all_top(clicon_handle h, cxobj *xt, cxobj **xret);
#endif /* _CLIXON_VALIDATE_H_ */

View file

@ -32,7 +32,7 @@
***** END LICENSE BLOCK ***** ***** END LICENSE BLOCK *****
* *
* XML code * Translation / mapping code between formats
*/ */
#ifndef _CLIXON_XML_MAP_H_ #ifndef _CLIXON_XML_MAP_H_
@ -47,22 +47,13 @@ typedef enum yang_class yang_class;
int isxmlns(cxobj *x); int isxmlns(cxobj *x);
int xml2txt(FILE *f, cxobj *x, int level); int xml2txt(FILE *f, cxobj *x, int level);
int xml2cli(FILE *f, cxobj *x, char *prepend, enum genmodel_type gt); int xml2cli(FILE *f, cxobj *x, char *prepend, enum genmodel_type gt);
int xml_yang_root(cxobj *x, cxobj **xr);
int xmlns_assign(cxobj *x); int xmlns_assign(cxobj *x);
int xml_yang_validate_rpc(clicon_handle h, cxobj *xrpc, cxobj **xret);
int xml_yang_validate_list_key_only(clicon_handle h, cxobj *xt, cxobj **xret);
int xml_yang_validate_add(clicon_handle h, cxobj *xt, cxobj **xret);
int xml_yang_validate_all(clicon_handle h, cxobj *xt, cxobj **xret);
int xml_yang_validate_all_top(clicon_handle h, cxobj *xt, cxobj **xret);
int xml2cvec(cxobj *xt, yang_stmt *ys, cvec **cvv0); int xml2cvec(cxobj *xt, yang_stmt *ys, cvec **cvv0);
int cvec2xml_1(cvec *cvv, char *toptag, cxobj *xp, cxobj **xt0); int cvec2xml_1(cvec *cvv, char *toptag, cxobj *xp, cxobj **xt0);
int xml_diff(yang_stmt *yspec, cxobj *x0, cxobj *x1, int xml_diff(yang_stmt *yspec, cxobj *x0, cxobj *x1,
cxobj ***first, size_t *firstlen, cxobj ***first, size_t *firstlen,
cxobj ***second, size_t *secondlen, cxobj ***second, size_t *secondlen,
cxobj ***changed_x0, cxobj ***changed_x1, size_t *changedlen); cxobj ***changed_x0, cxobj ***changed_x1, size_t *changedlen);
int yang2api_path_fmt(yang_stmt *ys, int inclkey, char **api_path_fmt);
int api_path_fmt2api_path(char *api_path_fmt, cvec *cvv, char **api_path);
int api_path_fmt2xpath(char *api_path_fmt, cvec *cvv, char **xpath);
int xml_tree_prune_flagged_sub(cxobj *xt, int flag, int test, int *upmark); int xml_tree_prune_flagged_sub(cxobj *xt, int flag, int test, int *upmark);
int xml_tree_prune_flagged(cxobj *xt, int flag, int test); int xml_tree_prune_flagged(cxobj *xt, int flag, int test);
int xml_default(cxobj *x, void *arg); int xml_default(cxobj *x, void *arg);
@ -70,14 +61,7 @@ int xml_sanity(cxobj *x, void *arg);
int xml_non_config_data(cxobj *xt, void *arg); int xml_non_config_data(cxobj *xt, void *arg);
int xml_spec_populate_rpc(clicon_handle h, cxobj *x, yang_stmt *yspec); int xml_spec_populate_rpc(clicon_handle h, cxobj *x, yang_stmt *yspec);
int xml_spec_populate(cxobj *x, void *arg); int xml_spec_populate(cxobj *x, void *arg);
int api_path2xpath_cvv(cvec *api_path, int offset, yang_stmt *yspec, cbuf *xpath, cvec **nsc, cxobj **xerr);
int api_path2xpath(char *api_path, yang_stmt *yspec, char **xpath, cvec **nsc);
int api_path2xml(char *api_path, yang_stmt *yspec, cxobj *xtop,
yang_class nodeclass, int strict,
cxobj **xpathp, yang_stmt **ypathp, cxobj **xerr);
int xml2xpath(cxobj *x, char **xpath); int xml2xpath(cxobj *x, char **xpath);
int xml2api_path_1(cxobj *x, cbuf *cb);
int check_namespaces(cxobj *x0, cxobj *x1, cxobj *x1p); int check_namespaces(cxobj *x0, cxobj *x1, cxobj *x1p);
int xml_merge(cxobj *x0, cxobj *x1, yang_stmt *yspec, char **reason); int xml_merge(cxobj *x0, cxobj *x1, yang_stmt *yspec, char **reason);
int yang_enum_int_value(cxobj *node, int32_t *val); int yang_enum_int_value(cxobj *node, int32_t *val);

View file

@ -67,10 +67,11 @@ CPPFLAGS = @CPPFLAGS@
INCLUDES = -I. @INCLUDES@ -I$(top_srcdir)/lib/clixon -I$(top_srcdir)/include -I$(top_srcdir) INCLUDES = -I. @INCLUDES@ -I$(top_srcdir)/lib/clixon -I$(top_srcdir)/include -I$(top_srcdir)
SRC = clixon_sig.c clixon_uid.c clixon_log.c clixon_err.c clixon_event.c \ SRC = clixon_sig.c clixon_uid.c clixon_log.c clixon_err.c clixon_event.c \
clixon_string.c clixon_regex.c clixon_handle.c \ clixon_string.c clixon_regex.c clixon_handle.c clixon_file.c \
clixon_xml.c clixon_xml_sort.c clixon_xml_map.c clixon_file.c \ clixon_xml.c clixon_xml_sort.c clixon_xml_map.c \
clixon_json.c clixon_yang.c clixon_yang_type.c clixon_yang_module.c \ clixon_json.c clixon_yang.c clixon_yang_type.c clixon_yang_module.c \
clixon_yang_cardinality.c clixon_xml_changelog.c clixon_xml_nsctx.c \ clixon_yang_cardinality.c clixon_xml_changelog.c clixon_xml_nsctx.c \
clixon_api_path.c clixon_validate.c \
clixon_hash.c clixon_options.c clixon_data.c clixon_plugin.c \ clixon_hash.c clixon_options.c clixon_data.c clixon_plugin.c \
clixon_proto.c clixon_proto_client.c \ clixon_proto.c clixon_proto_client.c \
clixon_xpath.c clixon_xpath_ctx.c clixon_xpath_eval.c clixon_xpath_optimize.c \ clixon_xpath.c clixon_xpath_ctx.c clixon_xpath_eval.c clixon_xpath_optimize.c \

1064
lib/src/clixon_api_path.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -59,7 +59,7 @@
/* cligen */ /* cligen */
#include <cligen/cligen.h> #include <cligen/cligen.h>
/* clicon */ /* clixon */
#include "clixon_err.h" #include "clixon_err.h"
#include "clixon_string.h" #include "clixon_string.h"
#include "clixon_queue.h" #include "clixon_queue.h"
@ -74,6 +74,7 @@
#include "clixon_xpath.h" #include "clixon_xpath.h"
#include "clixon_netconf_lib.h" #include "clixon_netconf_lib.h"
#include "clixon_xml_nsctx.h" #include "clixon_xml_nsctx.h"
#include "clixon_validate.h"
#include "clixon_xml_map.h" #include "clixon_xml_map.h"
/*! Clixon configuration namespace /*! Clixon configuration namespace

1197
lib/src/clixon_validate.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -69,6 +69,7 @@
#include "clixon_netconf_lib.h" #include "clixon_netconf_lib.h"
#include "clixon_xml_nsctx.h" #include "clixon_xml_nsctx.h"
#include "clixon_xml_map.h" #include "clixon_xml_map.h"
#include "clixon_validate.h"
#include "clixon_xml_changelog.h" #include "clixon_xml_changelog.h"
#include "clixon_xpath_ctx.h" #include "clixon_xpath_ctx.h"
#include "clixon_xpath.h" #include "clixon_xpath.h"

File diff suppressed because it is too large Load diff

View file

@ -64,7 +64,6 @@
#include "clixon_yang.h" #include "clixon_yang.h"
#include "clixon_xml.h" #include "clixon_xml.h"
#include "clixon_xml_sort.h" #include "clixon_xml_sort.h"
#include "clixon_xml_nsctx.h"
#include "clixon_xpath_ctx.h" #include "clixon_xpath_ctx.h"
#include "clixon_xpath.h" #include "clixon_xpath.h"
#include "clixon_xpath_optimize.h" #include "clixon_xpath_optimize.h"

View file

@ -39,7 +39,6 @@
#ifndef _CLIXON_YANG_INTERNAL_H_ #ifndef _CLIXON_YANG_INTERNAL_H_
#define _CLIXON_YANG_INTERNAL_H_ #define _CLIXON_YANG_INTERNAL_H_
/* /*
* Clixon-specific cligen variable (cv) flags * Clixon-specific cligen variable (cv) flags
* CLIgen flags defined are in the range 0x01 -0x0f * CLIgen flags defined are in the range 0x01 -0x0f
@ -48,7 +47,6 @@
*/ */
#define V_UNSET 0x10 /* Used by XML code to denote a value is not default */ #define V_UNSET 0x10 /* Used by XML code to denote a value is not default */
#define YANG_FLAG_MARK 0x01 /* Marker for dynamic algorithms, eg expand */ #define YANG_FLAG_MARK 0x01 /* Marker for dynamic algorithms, eg expand */
/*! Yang type cache. Yang type statements can cache all typedef info here /*! Yang type cache. Yang type statements can cache all typedef info here

124
test/test_cli_apipath.sh Executable file
View file

@ -0,0 +1,124 @@
#!/usr/bin/env bash
# Tests for manually adding keys to cli set/merge/del callbacks including error handling
# Note only completed commands, not interactive expand/completion
# 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
# include err() and new() functions and creates $dir
cfg=$dir/conf_yang.xml
fyang=$dir/$APPNAME.yang
clidir=$dir/cli
if [ -d $clidir ]; then
rm -rf $clidir/*
else
mkdir $clidir
fi
# Use yang in example
cat <<EOF > $cfg
<clixon-config xmlns="http://clicon.org/config">
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
<CLICON_YANG_DIR>$dir</CLICON_YANG_DIR>
<CLICON_YANG_MAIN_FILE>$fyang</CLICON_YANG_MAIN_FILE>
<CLICON_CLISPEC_DIR>$clidir</CLICON_CLISPEC_DIR>
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
<!-- ALL or VARS -->
<CLICON_CLI_GENMODEL_TYPE>ALL</CLICON_CLI_GENMODEL_TYPE>
<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>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
</clixon-config>
EOF
cat <<EOF > $fyang
module $APPNAME {
namespace "urn:example:m";
prefix m;
container x {
list m1 {
key "a b";
leaf a {
type string;
}
leaf b {
type string;
}
leaf c {
type string;
}
}
}
}
EOF
cat <<EOF > $clidir/ex.cli
CLICON_MODE="example";
CLICON_PROMPT="%U@%H> ";
CLICON_PLUGIN="example_cli";
# Positive
set x,cli_merge("/example:x");{
a <a:string> b <b:string>,cli_merge("/example:x/m1=%s,%s/");{
c <c:string>,cli_merge("/example:x/m1=%s,%s/c");
}
}
# Negative
err x,cli_set("/example2:x");{
a <a:string>,cli_merge("/example:x/m1=%s");
}
show config @datamodel, cli_show_auto("candidate", "cli");
EOF
new "test params: -f $cfg"
if [ $BE -ne 0 ]; then
new "kill old backend"
sudo clixon_backend -z -f $cfg
if [ $? -ne 0 ]; then
err
fi
new "start backend -s init -f $cfg"
start_backend -s init -f $cfg
new "waiting"
wait_backend
fi
# Positive tests
new "set x"
expectfn "$clixon_cli -1 -f $cfg set x" 0 ""
new "set x a b"
expectfn "$clixon_cli -1 -f $cfg set x a 99 b 22" 0 ""
new "set x a b c"
expectfn "$clixon_cli -1 -f $cfg set x a 22 b 33 c 55" 0 ""
new "show conf x"
expectfn "$clixon_cli -1 -f $cfg show conf x" 0 "x m1 a 22 b 33"
# Negative tests
new "err x"
expectfn "$clixon_cli -1 -f $cfg err x" 255 "Config error: api-path syntax error \"/example2:x\": application unknown-element No such yang module prefix <bad-element>example2</bad-element>: Invalid argument"
new "err x a"
expectfn "$clixon_cli -1 -f $cfg err x a 99" 255 "Config error: api-path syntax error \"/example:x/m1=%s\": rpc malformed-message List key m1 length mismatch : Invalid argument"
new "Kill backend"
# Check if premature kill
pid=$(pgrep -u root -f clixon_backend)
if [ -z "$pid" ]; then
err "backend already dead"
fi
# kill backend
stop_backend -f $cfg
rm -rf $dir