* Support for YANG identity and identityref according to RFC 7950 Sec 7.18 and 9.10
* Previous support did no validation of values. * Validation of types and CLI expansion * Example extended with inclusion of iana-if-type RFC 7224 interface identities
This commit is contained in:
parent
ea13727e97
commit
7e4e1d6deb
27 changed files with 2124 additions and 203 deletions
|
|
@ -2,7 +2,13 @@
|
||||||
|
|
||||||
## 3.7.0 (Upcoming)
|
## 3.7.0 (Upcoming)
|
||||||
### Major changes:
|
### Major changes:
|
||||||
|
* Support for YANG identity and identityref according to RFC 7950 Sec 7.18 and 9.10
|
||||||
|
* Previous support did no validation of values.
|
||||||
|
* Validation of types and CLI expansion
|
||||||
|
* Example extended with inclusion of iana-if-type RFC 7224 interface identities
|
||||||
|
|
||||||
### Minor changes:
|
### Minor changes:
|
||||||
|
* Added yang identityref runtime validation
|
||||||
* Removed cli callback vector functions. Set COMPAT_COMPAT_CLIV if you need to keep these functions in clixon_custom.h.
|
* Removed cli callback vector functions. Set COMPAT_COMPAT_CLIV if you need to keep these functions in clixon_custom.h.
|
||||||
* Replace functions as follows in CLI SPEC files:
|
* Replace functions as follows in CLI SPEC files:
|
||||||
* cli_setv --> cli_set
|
* cli_setv --> cli_set
|
||||||
|
|
@ -27,7 +33,9 @@
|
||||||
* Added --enable-debug.
|
* Added --enable-debug.
|
||||||
* Added cligen variable translation.
|
* Added cligen variable translation.
|
||||||
* See FAQ and example
|
* See FAQ and example
|
||||||
|
|
||||||
### Corrected Bugs
|
### Corrected Bugs
|
||||||
|
* Added cli returna value also for single commands (eg -1)
|
||||||
* Fixed JSON unbalanced braces resulting in assert.
|
* Fixed JSON unbalanced braces resulting in assert.
|
||||||
|
|
||||||
## 3.6.1 (29 May 2018)
|
## 3.6.1 (29 May 2018)
|
||||||
|
|
|
||||||
|
|
@ -99,8 +99,9 @@ also manages an XML datastore.
|
||||||
|
|
||||||
Clixon mainly follows [YANG 1.0 RFC 6020](https://www.rfc-editor.org/rfc/rfc6020.txt) with some exceptions:
|
Clixon mainly follows [YANG 1.0 RFC 6020](https://www.rfc-editor.org/rfc/rfc6020.txt) with some exceptions:
|
||||||
- conformance: feature, if-feature, deviation
|
- conformance: feature, if-feature, deviation
|
||||||
- identity, base, identityref
|
|
||||||
- list features: min/max-elements, unique
|
- list features: min/max-elements, unique
|
||||||
|
- when, must, action statements
|
||||||
|
- notifications
|
||||||
|
|
||||||
The aim is also to cover new features in YANG 1.1 [YANG RFC 7950](https://www.rfc-editor.org/rfc/rfc7950.txt)
|
The aim is also to cover new features in YANG 1.1 [YANG RFC 7950](https://www.rfc-editor.org/rfc/rfc7950.txt)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -204,9 +204,12 @@ yang2cli_var_sub(clicon_handle h,
|
||||||
}
|
}
|
||||||
type = ytype?ytype->ys_argument:NULL;
|
type = ytype?ytype->ys_argument:NULL;
|
||||||
cvtypestr = cv_type2str(cvtype);
|
cvtypestr = cv_type2str(cvtype);
|
||||||
|
if (strcmp(type, "identityref") == 0)
|
||||||
|
cprintf(cb, "(");
|
||||||
cprintf(cb, "<%s:%s", ys->ys_argument, cvtypestr);
|
cprintf(cb, "<%s:%s", ys->ys_argument, cvtypestr);
|
||||||
/* enumeration special case completion */
|
/* enumeration special case completion */
|
||||||
if (type && (strcmp(type, "enumeration") == 0 || strcmp(type, "bits") == 0)){
|
if (type){
|
||||||
|
if (strcmp(type, "enumeration") == 0 || strcmp(type, "bits") == 0){
|
||||||
cprintf(cb, " choice:");
|
cprintf(cb, " choice:");
|
||||||
i = 0;
|
i = 0;
|
||||||
while ((yi = yn_each((yang_node*)ytype, yi)) != NULL){
|
while ((yi = yn_each((yang_node*)ytype, yi)) != NULL){
|
||||||
|
|
@ -218,6 +221,32 @@ yang2cli_var_sub(clicon_handle h,
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (strcmp(type, "identityref") == 0){
|
||||||
|
yang_stmt *ybaseref;
|
||||||
|
yang_stmt *ybaseid;
|
||||||
|
cg_var *cv = NULL;
|
||||||
|
char *name;
|
||||||
|
char *id;
|
||||||
|
/* Add a wildchar string first -let validate take it for default prefix */
|
||||||
|
cprintf(cb, ">");
|
||||||
|
if (helptext)
|
||||||
|
cprintf(cb, "(\"%s\")", helptext);
|
||||||
|
cprintf(cb, "|<%s:%s choice:", ys->ys_argument, cvtypestr);
|
||||||
|
if ((ybaseref = yang_find((yang_node*)ytype, Y_BASE, NULL)) != NULL &&
|
||||||
|
(ybaseid = yang_find_identity(ys, ybaseref->ys_argument)) != NULL){
|
||||||
|
i = 0;
|
||||||
|
while ((cv = cvec_each(ybaseid->ys_cvec, cv)) != NULL){
|
||||||
|
if (i++)
|
||||||
|
cprintf(cb, "|");
|
||||||
|
name = strdup(cv_name_get(cv));
|
||||||
|
if ((id=strchr(name, ':')) != NULL)
|
||||||
|
*id = '\0';
|
||||||
|
cprintf(cb, "%s:%s", name, id+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (options & YANG_OPTIONS_FRACTION_DIGITS)
|
if (options & YANG_OPTIONS_FRACTION_DIGITS)
|
||||||
cprintf(cb, " fraction-digits:%u", fraction_digits);
|
cprintf(cb, " fraction-digits:%u", fraction_digits);
|
||||||
if (options & (YANG_OPTIONS_RANGE|YANG_OPTIONS_LENGTH)){
|
if (options & (YANG_OPTIONS_RANGE|YANG_OPTIONS_LENGTH)){
|
||||||
|
|
@ -259,10 +288,12 @@ yang2cli_var_sub(clicon_handle h,
|
||||||
}
|
}
|
||||||
if (options & YANG_OPTIONS_PATTERN)
|
if (options & YANG_OPTIONS_PATTERN)
|
||||||
cprintf(cb, " regexp:\"%s\"", pattern);
|
cprintf(cb, " regexp:\"%s\"", pattern);
|
||||||
|
|
||||||
cprintf(cb, ">");
|
cprintf(cb, ">");
|
||||||
if (helptext)
|
if (helptext)
|
||||||
cprintf(cb, "(\"%s\")", helptext);
|
cprintf(cb, "(\"%s\")", helptext);
|
||||||
|
if (strcmp(type, "identityref") == 0)
|
||||||
|
cprintf(cb, ")");
|
||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
return retval;
|
return retval;
|
||||||
|
|
@ -385,6 +416,7 @@ yang2cli_var(clicon_handle h,
|
||||||
enum cv_type cvtype;
|
enum cv_type cvtype;
|
||||||
int options = 0;
|
int options = 0;
|
||||||
int completionp;
|
int completionp;
|
||||||
|
char *type;
|
||||||
|
|
||||||
if (yang_type_get(ys, &origtype, &yrestype,
|
if (yang_type_get(ys, &origtype, &yrestype,
|
||||||
&options, &mincv, &maxcv, &pattern, &fraction_digits) < 0)
|
&options, &mincv, &maxcv, &pattern, &fraction_digits) < 0)
|
||||||
|
|
@ -413,11 +445,11 @@ yang2cli_var(clicon_handle h,
|
||||||
cprintf(cb, ")");
|
cprintf(cb, ")");
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
char *type;
|
|
||||||
type = yrestype?yrestype->ys_argument:NULL;
|
type = yrestype?yrestype->ys_argument:NULL;
|
||||||
if (type)
|
if (type)
|
||||||
completionp = clicon_cli_genmodel_completion(h) &&
|
completionp = clicon_cli_genmodel_completion(h) &&
|
||||||
strcmp(type, "enumeration") != 0 &&
|
strcmp(type, "enumeration") != 0 &&
|
||||||
|
strcmp(type, "identityref") != 0 &&
|
||||||
strcmp(type, "bits") != 0;
|
strcmp(type, "bits") != 0;
|
||||||
else
|
else
|
||||||
completionp = clicon_cli_genmodel_completion(h);
|
completionp = clicon_cli_genmodel_completion(h);
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,8 @@ cli_signal_init (clicon_handle h)
|
||||||
|
|
||||||
/*! Interactive CLI command loop
|
/*! Interactive CLI command loop
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
|
* @retval 0
|
||||||
|
* @retval -1
|
||||||
* @see cligen_loop
|
* @see cligen_loop
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
|
|
@ -124,7 +126,6 @@ cli_interactive(clicon_handle h)
|
||||||
new_mode = cli_syntax_mode(h);
|
new_mode = cli_syntax_mode(h);
|
||||||
if ((cmd = clicon_cliread(h)) == NULL) {
|
if ((cmd = clicon_cliread(h)) == NULL) {
|
||||||
cligen_exiting_set(cli_cligen(h), 1); /* EOF */
|
cligen_exiting_set(cli_cligen(h), 1); /* EOF */
|
||||||
retval = -1;
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((res = clicon_parse(h, cmd, &new_mode, &result)) < 0)
|
if ((res = clicon_parse(h, cmd, &new_mode, &result)) < 0)
|
||||||
|
|
@ -229,6 +230,7 @@ usage(char *argv0, clicon_handle h)
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
int retval = -1;
|
||||||
char c;
|
char c;
|
||||||
int once;
|
int once;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
|
|
@ -476,11 +478,19 @@ main(int argc, char **argv)
|
||||||
if (restarg != NULL && strlen(restarg)){
|
if (restarg != NULL && strlen(restarg)){
|
||||||
char *mode = cli_syntax_mode(h);
|
char *mode = cli_syntax_mode(h);
|
||||||
int result;
|
int result;
|
||||||
clicon_parse(h, restarg, &mode, &result);
|
|
||||||
|
/* */
|
||||||
|
if (clicon_parse(h, restarg, &mode, &result) != 1){
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (result < 0)
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
/* Go into event-loop unless -1 command-line */
|
/* Go into event-loop unless -1 command-line */
|
||||||
if (!once)
|
if (!once)
|
||||||
cli_interactive(h);
|
retval = cli_interactive(h);
|
||||||
|
else
|
||||||
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (treename)
|
if (treename)
|
||||||
free(treename);
|
free(treename);
|
||||||
|
|
@ -491,6 +501,5 @@ main(int argc, char **argv)
|
||||||
clicon_log(LOG_NOTICE, "%s: %u Terminated\n", __PROGRAM__, getpid());
|
clicon_log(LOG_NOTICE, "%s: %u Terminated\n", __PROGRAM__, getpid());
|
||||||
if (h)
|
if (h)
|
||||||
cli_terminate(h);
|
cli_terminate(h);
|
||||||
|
return retval;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -481,6 +481,7 @@ clicon_eval(clicon_handle h,
|
||||||
* @param[out] result -2 On eof (shouldnt happen)
|
* @param[out] result -2 On eof (shouldnt happen)
|
||||||
* -1 On parse error
|
* -1 On parse error
|
||||||
* >=0 Number of matches
|
* >=0 Number of matches
|
||||||
|
* @retval 0 XXX How does this relate to result???
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
clicon_parse(clicon_handle h,
|
clicon_parse(clicon_handle h,
|
||||||
|
|
@ -490,7 +491,7 @@ clicon_parse(clicon_handle h,
|
||||||
{
|
{
|
||||||
char *modename;
|
char *modename;
|
||||||
char *modename0;
|
char *modename0;
|
||||||
int res = -1;
|
int retval = -1;
|
||||||
int r;
|
int r;
|
||||||
cli_syntax_t *stx = NULL;
|
cli_syntax_t *stx = NULL;
|
||||||
cli_syntaxmode_t *smode;
|
cli_syntaxmode_t *smode;
|
||||||
|
|
@ -511,10 +512,11 @@ clicon_parse(clicon_handle h,
|
||||||
else {
|
else {
|
||||||
if ((smode = syntax_mode_find(stx, modename, 0)) == NULL) {
|
if ((smode = syntax_mode_find(stx, modename, 0)) == NULL) {
|
||||||
cli_output(f, "Can't find syntax mode '%s'\n", modename);
|
cli_output(f, "Can't find syntax mode '%s'\n", modename);
|
||||||
return -1;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while(smode) {
|
if (smode)
|
||||||
|
while(1) {
|
||||||
modename0 = NULL;
|
modename0 = NULL;
|
||||||
if ((pt = cligen_tree_active_get(cli_cligen(h))) != NULL)
|
if ((pt = cligen_tree_active_get(cli_cligen(h))) != NULL)
|
||||||
modename0 = pt->pt_name;
|
modename0 = pt->pt_name;
|
||||||
|
|
@ -530,24 +532,24 @@ clicon_parse(clicon_handle h,
|
||||||
clicon_err(OE_UNIX, errno, "cvec_new");
|
clicon_err(OE_UNIX, errno, "cvec_new");
|
||||||
goto done;;
|
goto done;;
|
||||||
}
|
}
|
||||||
res = cliread_parse(cli_cligen(h), cmd, pt, &match_obj, cvv);
|
retval = cliread_parse(cli_cligen(h), cmd, pt, &match_obj, cvv);
|
||||||
if (res != CG_MATCH)
|
if (retval != CG_MATCH)
|
||||||
pt_expand_cleanup_1(pt); /* XXX change to pt_expand_treeref_cleanup */
|
pt_expand_cleanup_1(pt); /* XXX change to pt_expand_treeref_cleanup */
|
||||||
if (modename0){
|
if (modename0){
|
||||||
cligen_tree_active_set(cli_cligen(h), modename0);
|
cligen_tree_active_set(cli_cligen(h), modename0);
|
||||||
modename0 = NULL;
|
modename0 = NULL;
|
||||||
}
|
}
|
||||||
switch (res) {
|
switch (retval) {
|
||||||
case CG_EOF: /* eof */
|
case CG_EOF: /* eof */
|
||||||
case CG_ERROR:
|
case CG_ERROR:
|
||||||
cli_output(f, "CLI parse error: %s\n", cmd);
|
cli_output(f, "CLI parse error: %s\n", cmd);
|
||||||
goto done;
|
goto done;
|
||||||
case CG_NOMATCH: /* no match */
|
case CG_NOMATCH: /* no match */
|
||||||
smode = NULL;
|
|
||||||
/* clicon_err(OE_CFG, 0, "CLI syntax error: \"%s\": %s",
|
/* clicon_err(OE_CFG, 0, "CLI syntax error: \"%s\": %s",
|
||||||
cmd, cli_nomatch(h));*/
|
cmd, cli_nomatch(h));*/
|
||||||
cli_output(f, "CLI syntax error: \"%s\": %s\n",
|
cli_output(f, "CLI syntax error: \"%s\": %s\n",
|
||||||
cmd, cli_nomatch(h));
|
cmd, cli_nomatch(h));
|
||||||
|
goto done;
|
||||||
break;
|
break;
|
||||||
case CG_MATCH:
|
case CG_MATCH:
|
||||||
if (strcmp(modename, *modenamep)){ /* Command in different mode */
|
if (strcmp(modename, *modenamep)){ /* Command in different mode */
|
||||||
|
|
@ -565,12 +567,12 @@ clicon_parse(clicon_handle h,
|
||||||
cli_output(f, "CLI syntax error: \"%s\" is ambiguous\n", cmd);
|
cli_output(f, "CLI syntax error: \"%s\" is ambiguous\n", cmd);
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
}
|
} /* switch retval */
|
||||||
}
|
} /* while smode */
|
||||||
done:
|
done:
|
||||||
if (cvv)
|
if (cvv)
|
||||||
cvec_free(cvv);
|
cvec_free(cvv);
|
||||||
return res;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Read command from CLIgen's cliread() using current syntax mode.
|
/*! Read command from CLIgen's cliread() using current syntax mode.
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@ YANGSPECS += ietf-routing@2014-10-26.yang
|
||||||
YANGSPECS += ietf-ipv4-unicast-routing@2014-10-26.yang
|
YANGSPECS += ietf-ipv4-unicast-routing@2014-10-26.yang
|
||||||
YANGSPECS += ietf-ipv6-unicast-routing@2014-10-26.yang
|
YANGSPECS += ietf-ipv6-unicast-routing@2014-10-26.yang
|
||||||
YANGSPECS += ietf-ipsec@2016-03-09.yang
|
YANGSPECS += ietf-ipsec@2016-03-09.yang
|
||||||
|
YANGSPECS += iana-if-type@2014-05-08.yang
|
||||||
|
|
||||||
# Backend plugin
|
# Backend plugin
|
||||||
BE_SRC = $(APPNAME)_backend.c
|
BE_SRC = $(APPNAME)_backend.c
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,28 @@
|
||||||
module example {
|
module example {
|
||||||
prefix ex;
|
prefix ex;
|
||||||
|
import ietf-interfaces {
|
||||||
|
prefix if;
|
||||||
|
}
|
||||||
import ietf-ip {
|
import ietf-ip {
|
||||||
prefix ip;
|
prefix ip;
|
||||||
}
|
}
|
||||||
import ietf-routing {
|
import ietf-routing {
|
||||||
prefix rt;
|
prefix rt;
|
||||||
}
|
}
|
||||||
|
import iana-if-type {
|
||||||
|
prefix ianaift;
|
||||||
|
}
|
||||||
description
|
description
|
||||||
"Example code that includes ietf-ip and ietf-routing";
|
"Example code that includes ietf-ip and ietf-routing";
|
||||||
|
/* Example interface type for tests, local callbacks, etc */
|
||||||
|
identity eth {
|
||||||
|
base if:interface-type;
|
||||||
|
}
|
||||||
|
identity loopback {
|
||||||
|
base if:interface-type;
|
||||||
|
}
|
||||||
/* Translation function example - See also example_cli */
|
/* Translation function example - See also example_cli */
|
||||||
|
|
||||||
list translate{
|
list translate{
|
||||||
leaf value{
|
leaf value{
|
||||||
type string;
|
type string;
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ plugin_statedata(clicon_handle h,
|
||||||
/* Example of (static) statedata, real code would poll state */
|
/* Example of (static) statedata, real code would poll state */
|
||||||
if (xml_parse_string("<interfaces-state><interface>"
|
if (xml_parse_string("<interfaces-state><interface>"
|
||||||
"<name>eth0</name>"
|
"<name>eth0</name>"
|
||||||
"<type>eth</type>"
|
"<type>ex:eth</type>"
|
||||||
"<if-index>42</if-index>"
|
"<if-index>42</if-index>"
|
||||||
"</interface></interfaces-state>", NULL, &xstate) < 0)
|
"</interface></interfaces-state>", NULL, &xstate) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -221,7 +221,7 @@ plugin_reset(clicon_handle h,
|
||||||
cxobj *xt = NULL;
|
cxobj *xt = NULL;
|
||||||
|
|
||||||
if (xml_parse_string("<config><interfaces><interface>"
|
if (xml_parse_string("<config><interfaces><interface>"
|
||||||
"<name>lo</name><type>local</type>"
|
"<name>lo</name><type>ex:loopback</type>"
|
||||||
"</interface></interfaces></config>", NULL, &xt) < 0)
|
"</interface></interfaces></config>", NULL, &xt) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Replace parent w fiorst child */
|
/* Replace parent w fiorst child */
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ load("Load configuration from XML file") <filename:string>("Filename (local file
|
||||||
merge("Merge file with existent candidate"), load_config_file("filename", "merge");
|
merge("Merge file with existent candidate"), load_config_file("filename", "merge");
|
||||||
}
|
}
|
||||||
example("This is a comment") <var:int32>("Just a random number"), mycallback("myarg");
|
example("This is a comment") <var:int32>("Just a random number"), mycallback("myarg");
|
||||||
rpc("fib-route rpc") <instance:string>("routing instance"), fib_route_rpc("myarg");
|
rpc("ex:fib-route rpc") <instance:string>("routing instance"), fib_route_rpc("myarg");
|
||||||
notify("Get notifications from backend"), cli_notify("ROUTING", "1", "text");
|
notify("Get notifications from backend"), cli_notify("ROUTING", "1", "text");
|
||||||
no("Negate") notify("Get notifications from backend"), cli_notify("ROUTING", "0", "xml");
|
no("Negate") notify("Get notifications from backend"), cli_notify("ROUTING", "0", "xml");
|
||||||
lock,cli_lock("candidate");
|
lock,cli_lock("candidate");
|
||||||
|
|
|
||||||
1506
example/iana-if-type@2014-05-08.yang
Normal file
1506
example/iana-if-type@2014-05-08.yang
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -91,8 +91,9 @@ typedef int (plgexit_t)(clicon_handle); /* Plugin exit */
|
||||||
/* Plugin authorization. Set username option (or not)
|
/* Plugin authorization. Set username option (or not)
|
||||||
* @param[in] Clicon handle
|
* @param[in] Clicon handle
|
||||||
* @param[in] void*, eg Fastcgihandle request restconf
|
* @param[in] void*, eg Fastcgihandle request restconf
|
||||||
* @retval 0 if credentials OK
|
* @retval -1 Fatal error
|
||||||
* @retval -1 credentials not OK
|
* @retval 0 Credential not OK
|
||||||
|
* @retval 1 Credential OK
|
||||||
*/
|
*/
|
||||||
typedef int (plgauth_t)(clicon_handle, void *);
|
typedef int (plgauth_t)(clicon_handle, void *);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -202,6 +202,7 @@ struct yang_stmt{
|
||||||
cvec *ys_cvec; /* List of stmt-specific variables
|
cvec *ys_cvec; /* List of stmt-specific variables
|
||||||
Y_RANGE: range_min, range_max
|
Y_RANGE: range_min, range_max
|
||||||
Y_LIST: vector of keys
|
Y_LIST: vector of keys
|
||||||
|
Y_TYPE & identity: store all derived types
|
||||||
*/
|
*/
|
||||||
yang_type_cache *ys_typecache; /* If ys_keyword==Y_TYPE, cache all typedef data except unions */
|
yang_type_cache *ys_typecache; /* If ys_keyword==Y_TYPE, cache all typedef data except unions */
|
||||||
};
|
};
|
||||||
|
|
@ -252,6 +253,7 @@ yang_stmt *yang_find(yang_node *yn, int keyword, char *argument);
|
||||||
yang_stmt *yang_find_datanode(yang_node *yn, char *argument);
|
yang_stmt *yang_find_datanode(yang_node *yn, char *argument);
|
||||||
yang_stmt *yang_find_schemanode(yang_node *yn, char *argument);
|
yang_stmt *yang_find_schemanode(yang_node *yn, char *argument);
|
||||||
yang_stmt *yang_find_topnode(yang_spec *ysp, char *name, yang_class class);
|
yang_stmt *yang_find_topnode(yang_spec *ysp, char *name, yang_class class);
|
||||||
|
char *yang_find_myprefix(yang_stmt *ys);
|
||||||
int yang_order(yang_stmt *y);
|
int yang_order(yang_stmt *y);
|
||||||
int yang_print(FILE *f, yang_node *yn);
|
int yang_print(FILE *f, yang_node *yn);
|
||||||
int yang_print_cbuf(cbuf *cb, yang_node *yn, int marginal);
|
int yang_print_cbuf(cbuf *cb, yang_node *yn, int marginal);
|
||||||
|
|
|
||||||
|
|
@ -186,6 +186,7 @@ clicon_option_readfile_xml(clicon_hash_t *copt,
|
||||||
/*! Initialize option values
|
/*! Initialize option values
|
||||||
*
|
*
|
||||||
* Set default options, Read config-file, Check that all values are set.
|
* Set default options, Read config-file, Check that all values are set.
|
||||||
|
* Read clixon system config files
|
||||||
* @param[in] h clicon handle
|
* @param[in] h clicon handle
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
|
|
||||||
|
|
@ -226,7 +226,7 @@ xml2cli(FILE *f,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Validate an xml node of type leafref, ensure the value is one of that path's reference
|
/*! Validate xml node of type leafref, ensure the value is one of that path's reference
|
||||||
* @param[in] xt XML leaf node of type leafref
|
* @param[in] xt XML leaf node of type leafref
|
||||||
* @param[in] ytype Yang type statement belonging to the XML node
|
* @param[in] ytype Yang type statement belonging to the XML node
|
||||||
*/
|
*/
|
||||||
|
|
@ -270,6 +270,70 @@ validate_leafref(cxobj *xt,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Validate xml node of type identityref, ensure value is a defined identity
|
||||||
|
* Check if a given node has value derived from base identity. This is
|
||||||
|
* a run-time check necessary when validating eg netconf.
|
||||||
|
* Valid values for an identityref are any identities derived from all
|
||||||
|
* the identityref's base identities.
|
||||||
|
* Example:
|
||||||
|
* b0 --> b1 --> b2 (b1 & b2 are derived)
|
||||||
|
* identityref b2
|
||||||
|
* base b0;
|
||||||
|
* This function does: derived_from(b2, b0);
|
||||||
|
* @param[in] xt XML leaf node of type identityref
|
||||||
|
* @param[in] ys Yang spec of leaf
|
||||||
|
* @param[in] ytype Yang type field of type identityref
|
||||||
|
* @see ys_populate_identity where the derived types are set
|
||||||
|
* @see RFC7950 Sec 9.10.2:
|
||||||
|
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
validate_identityref(cxobj *xt,
|
||||||
|
yang_stmt *ys,
|
||||||
|
yang_stmt *ytype)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char *node;
|
||||||
|
yang_stmt *ybaseref; /* This is the type's base reference */
|
||||||
|
yang_stmt *ybaseid;
|
||||||
|
char *prefix = NULL;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
|
/* Get idref value. Then see if this value is derived from ytype.
|
||||||
|
* Always add default prefix because derived identifiers are stored with
|
||||||
|
* prefixes in the base identifiers derived-list.
|
||||||
|
*/
|
||||||
|
if ((node = xml_body(xt)) == NULL)
|
||||||
|
return 0;
|
||||||
|
if (strchr(node, ':') == NULL){
|
||||||
|
prefix = yang_find_myprefix(ys);
|
||||||
|
if ((cb = cbuf_new()) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
cprintf(cb, "%s:%s", prefix, node);
|
||||||
|
node = cbuf_get(cb);
|
||||||
|
}
|
||||||
|
/* This is the type's base reference */
|
||||||
|
if ((ybaseref = yang_find((yang_node*)ytype, Y_BASE, NULL)) == NULL){
|
||||||
|
clicon_err(OE_DB, 0, "Identityref validation failed, no base");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* This is the actual base identity */
|
||||||
|
if ((ybaseid = yang_find_identity(ybaseref, ybaseref->ys_argument)) == NULL){
|
||||||
|
clicon_err(OE_DB, 0, "Identityref validation failed, no base identity");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* Here check if node is in the derived node list of the base identity */
|
||||||
|
if (cvec_find(ybaseid->ys_cvec, node) == NULL){
|
||||||
|
clicon_err(OE_DB, 0, "Identityref validation failed, %s not derived from %s", node, ybaseid->ys_argument);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Validate a single XML node with yang specification for added entry
|
/*! Validate a single XML node with yang specification for added entry
|
||||||
* 1. Check if mandatory leafs present as subs.
|
* 1. Check if mandatory leafs present as subs.
|
||||||
* 2. Check leaf values, eg int ranges and string regexps.
|
* 2. Check leaf values, eg int ranges and string regexps.
|
||||||
|
|
@ -374,10 +438,16 @@ xml_yang_validate_all(cxobj *xt,
|
||||||
/* Special case if leaf is leafref, then first check against
|
/* Special case if leaf is leafref, then first check against
|
||||||
current xml tree
|
current xml tree
|
||||||
*/
|
*/
|
||||||
if ((ytype = yang_find((yang_node*)ys, Y_TYPE, NULL)) != NULL &&
|
if ((ytype = yang_find((yang_node*)ys, Y_TYPE, NULL)) != NULL){
|
||||||
strcmp(ytype->ys_argument, "leafref") == 0)
|
if (strcmp(ytype->ys_argument, "leafref") == 0){
|
||||||
if (validate_leafref(xt, ytype) < 0)
|
if (validate_leafref(xt, ytype) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
}
|
||||||
|
else if (strcmp(ytype->ys_argument, "identityref") == 0){
|
||||||
|
if (validate_identityref(xt, ys, ytype) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -817,8 +817,6 @@ yarg_prefix(yang_stmt *ys)
|
||||||
return prefix;
|
return prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*! Given a yang statement and a prefix, return yang module to that prefix
|
/*! Given a yang statement and a prefix, return yang module to that prefix
|
||||||
* Note, not the other module but the proxy import statement only
|
* Note, not the other module but the proxy import statement only
|
||||||
* @param[in] ys A yang statement
|
* @param[in] ys A yang statement
|
||||||
|
|
@ -1168,6 +1166,8 @@ ys_populate_range(yang_stmt *ys,
|
||||||
|
|
||||||
/*! Sanity check yang type statement
|
/*! Sanity check yang type statement
|
||||||
* XXX: Replace with generic parent/child type-check
|
* XXX: Replace with generic parent/child type-check
|
||||||
|
* @param[in] ys The yang statement (type) to populate.
|
||||||
|
* @
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ys_populate_type(yang_stmt *ys,
|
ys_populate_type(yang_stmt *ys,
|
||||||
|
|
@ -1199,28 +1199,82 @@ ys_populate_type(yang_stmt *ys,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Sanity check yang type statement
|
/*! Sanity check yang identity statement recursively
|
||||||
|
*
|
||||||
|
* Find base identities if any and add this identity to derived list.
|
||||||
|
* Do this recursively
|
||||||
|
* @param[in] ys The yang identity to populate.
|
||||||
|
* @param[in] arg If set contains a derived identifier
|
||||||
|
* @see validate_identityref which in runtime validates actual valoues
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ys_populate_identity(yang_stmt *ys,
|
ys_populate_identity(yang_stmt *ys,
|
||||||
void *arg)
|
void *arg)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
yang_stmt *ybase;
|
yang_stmt *yc = NULL;
|
||||||
|
yang_stmt *ybaseid;
|
||||||
|
cg_var *cv;
|
||||||
|
char *derid;
|
||||||
|
char *baseid;
|
||||||
|
char *prefix = NULL;
|
||||||
|
cbuf *cb = NULL;
|
||||||
|
char *idref = (char*)arg;
|
||||||
|
char *p;
|
||||||
|
|
||||||
if ((ybase = yang_find((yang_node*)ys, Y_BASE, NULL)) == NULL)
|
if (idref == NULL){
|
||||||
return 0;
|
/* Create derived identity through prefix:id if not recursively called*/
|
||||||
if ((yang_find_identity(ys, ybase->ys_argument)) == NULL){
|
derid = ys->ys_argument; /* derived id */
|
||||||
clicon_err(OE_YANG, 0, "Identity %s not found (base type of %s)",
|
if ((prefix = yarg_prefix(ys)) == NULL){
|
||||||
ybase->ys_argument, ys->ys_argument);
|
if ((p = yang_find_myprefix(ys)) != NULL)
|
||||||
|
prefix = strdup(yang_find_myprefix(ys));
|
||||||
|
}
|
||||||
|
if ((cb = cbuf_new()) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (prefix)
|
||||||
|
cprintf(cb, "%s:%s", prefix, derid);
|
||||||
|
else
|
||||||
|
cprintf(cb, "%s", derid);
|
||||||
|
idref = cbuf_get(cb);
|
||||||
|
}
|
||||||
|
/* Iterate through all base statements and check the base identity exists
|
||||||
|
* AND populate the base identity recursively
|
||||||
|
*/
|
||||||
|
while ((yc = yn_each((yang_node*)ys, yc)) != NULL) {
|
||||||
|
if (yc->ys_keyword != Y_BASE)
|
||||||
|
continue;
|
||||||
|
baseid = yc->ys_argument;
|
||||||
|
if (((ybaseid = yang_find_identity(ys, baseid))) == NULL){
|
||||||
|
clicon_err(OE_YANG, 0, "No such identity: %s", baseid);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
// continue; /* root identity */
|
||||||
|
/* Check if derived id is already in base identifier */
|
||||||
|
if (cvec_find(ybaseid->ys_cvec, idref) != NULL)
|
||||||
|
continue;
|
||||||
|
/* Add derived id to ybaseid */
|
||||||
|
if ((cv = cv_new(CGV_STRING)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "cv_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* add prefix */
|
||||||
|
cv_name_set(cv, idref);
|
||||||
|
cvec_append_var(ybaseid->ys_cvec, cv);
|
||||||
|
/* Transitive to the root */
|
||||||
|
if (ys_populate_identity(ybaseid, idref) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (prefix)
|
||||||
|
free(prefix);
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Populate with cligen-variables, default values, etc. Sanity checks on complete tree.
|
/*! Populate with cligen-variables, default values, etc. Sanity checks on complete tree.
|
||||||
*
|
*
|
||||||
* We do this in 2nd pass after complete parsing to be sure to have a complete parse-tree
|
* We do this in 2nd pass after complete parsing to be sure to have a complete parse-tree
|
||||||
|
|
|
||||||
|
|
@ -380,7 +380,7 @@ clicon_type2cv(char *origtype,
|
||||||
(rmax && (i) > cv_##type##_get(rmax)))
|
(rmax && (i) > cv_##type##_get(rmax)))
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*! Validate CLIgen variable
|
||||||
* @retval -1 Error (fatal), with errno set to indicate error
|
* @retval -1 Error (fatal), with errno set to indicate error
|
||||||
* @retval 0 Validation not OK, malloced reason is returned. Free reason with free()
|
* @retval 0 Validation not OK, malloced reason is returned. Free reason with free()
|
||||||
* @retval 1 Validation OK
|
* @retval 1 Validation OK
|
||||||
|
|
@ -764,9 +764,9 @@ ys_typedef_up(yang_stmt *ys)
|
||||||
return (yang_stmt*)ys;
|
return (yang_stmt*)ys;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Return yang-stmt of identity
|
/*! Find identity yang-stmt
|
||||||
This is a sanity check of base identity of identity-ref and for identity
|
This is a sanity check of base identity of identity-ref and for identity
|
||||||
statements.
|
statements when parsing.
|
||||||
|
|
||||||
Return true if node is identityref and is derived from identity_name
|
Return true if node is identityref and is derived from identity_name
|
||||||
The derived-from() function returns true if the (first) node (in
|
The derived-from() function returns true if the (first) node (in
|
||||||
|
|
@ -779,11 +779,16 @@ ys_typedef_up(yang_stmt *ys)
|
||||||
identityref's base identity.
|
identityref's base identity.
|
||||||
1. (base) identity must exist (be found). This is a sanity check
|
1. (base) identity must exist (be found). This is a sanity check
|
||||||
of the specification and also necessary for identity statements.
|
of the specification and also necessary for identity statements.
|
||||||
|
(This is what is dine here)
|
||||||
2. Check if a given node has value derived from base identity. This is
|
2. Check if a given node has value derived from base identity. This is
|
||||||
a run-time check necessary when validating eg netconf.
|
a run-time check necessary when validating eg netconf.
|
||||||
|
(This is validation)
|
||||||
3. Find all valid derived identities from a identityref base identity.
|
3. Find all valid derived identities from a identityref base identity.
|
||||||
This is for cli generation.
|
(This is for cli generation)
|
||||||
Så vad är det denna function ska göra? Svar: 1
|
* @param[in] ys Yang spec of id statement
|
||||||
|
* @param[in] identity Identity string -check if it exists
|
||||||
|
* @retval 0 OK
|
||||||
|
* @see validate_identityref for (2) above
|
||||||
*/
|
*/
|
||||||
yang_stmt *
|
yang_stmt *
|
||||||
yang_find_identity(yang_stmt *ys,
|
yang_find_identity(yang_stmt *ys,
|
||||||
|
|
|
||||||
24
test/lib.sh
24
test/lib.sh
|
|
@ -55,21 +55,28 @@ new2(){
|
||||||
>&2 echo -n "Test$testnr [$1]"
|
>&2 echo -n "Test$testnr [$1]"
|
||||||
}
|
}
|
||||||
|
|
||||||
# clixon tester. First arg is command and second is expected outcome
|
# clixon command tester.
|
||||||
|
# Arguments:
|
||||||
|
# - command,
|
||||||
|
# - expected command return value (0 if OK)
|
||||||
|
# - expected stdout outcome,
|
||||||
|
# - expected2 stdout outcome,
|
||||||
expectfn(){
|
expectfn(){
|
||||||
cmd=$1
|
cmd=$1
|
||||||
expect=$2
|
retval=$2
|
||||||
|
expect="$3"
|
||||||
|
|
||||||
if [ $# = 3 ]; then
|
if [ $# = 4 ]; then
|
||||||
expect2=$3
|
expect2=$4
|
||||||
else
|
else
|
||||||
expect2=
|
expect2=
|
||||||
fi
|
fi
|
||||||
ret=$($cmd)
|
ret=$($cmd)
|
||||||
|
if [ $? -ne $retval ]; then
|
||||||
# if [ $? -ne 0 ]; then
|
echo -e "\e[31m\nError in Test$testnr [$testname]:"
|
||||||
# err "wrong args"
|
echo -e "\e[0m:"
|
||||||
# fi
|
exit -1
|
||||||
|
fi
|
||||||
# Match if both are empty string
|
# Match if both are empty string
|
||||||
if [ -z "$ret" -a -z "$expect" ]; then
|
if [ -z "$ret" -a -z "$expect" ]; then
|
||||||
return
|
return
|
||||||
|
|
@ -79,7 +86,6 @@ expectfn(){
|
||||||
fi
|
fi
|
||||||
# grep extended grep
|
# grep extended grep
|
||||||
match=`echo $ret | grep -EZo "$expect"`
|
match=`echo $ret | grep -EZo "$expect"`
|
||||||
|
|
||||||
if [ -z "$match" ]; then
|
if [ -z "$match" ]; then
|
||||||
err "$expect" "$ret"
|
err "$expect" "$ret"
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ cat <<EOF > $cfg
|
||||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||||
<CLICON_YANG_DIR>/usr/local/share/$APPNAME/yang</CLICON_YANG_DIR>
|
<CLICON_YANG_DIR>/usr/local/share/$APPNAME/yang</CLICON_YANG_DIR>
|
||||||
<CLICON_YANG_MODULE_MAIN>$APPNAME</CLICON_YANG_MODULE_MAIN>
|
<CLICON_YANG_MODULE_MAIN>$APPNAME</CLICON_YANG_MODULE_MAIN>
|
||||||
|
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
||||||
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||||
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||||
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
||||||
|
|
@ -43,74 +44,73 @@ fi
|
||||||
new "cli tests"
|
new "cli tests"
|
||||||
|
|
||||||
new "cli configure top"
|
new "cli configure top"
|
||||||
expectfn "$clixon_cli -1 -f $cfg set interfaces" "^$"
|
expectfn "$clixon_cli -1 -f $cfg set interfaces" 0 "^$"
|
||||||
|
|
||||||
new "cli show configuration top (no presence)"
|
new "cli show configuration top (no presence)"
|
||||||
expectfn "$clixon_cli -1 -f $cfg show conf cli" "^$"
|
expectfn "$clixon_cli -1 -f $cfg show conf cli" 0 "^$"
|
||||||
|
|
||||||
new "cli configure delete top"
|
new "cli configure delete top"
|
||||||
expectfn "$clixon_cli -1 -f $cfg delete interfaces" "^$"
|
expectfn "$clixon_cli -1 -f $cfg delete interfaces" 0 "^$"
|
||||||
|
|
||||||
new "cli show configuration delete top"
|
new "cli show configuration delete top"
|
||||||
expectfn "$clixon_cli -1 -f $cfg show conf cli" "^$"
|
expectfn "$clixon_cli -1 -f $cfg show conf cli" 0 "^$"
|
||||||
|
|
||||||
new "cli configure"
|
new "cli configure"
|
||||||
expectfn "$clixon_cli -1 -f $cfg set interfaces interface eth/0/0" "^$"
|
expectfn "$clixon_cli -1 -f $cfg set interfaces interface eth/0/0" 0 "^$"
|
||||||
|
|
||||||
new "cli show configuration"
|
new "cli show configuration"
|
||||||
expectfn "$clixon_cli -1 -f $cfg show conf cli" "^interfaces interface eth/0/0 enabled true"
|
expectfn "$clixon_cli -1 -f $cfg show conf cli" 0 "^interfaces interface eth/0/0 enabled true"
|
||||||
|
|
||||||
new "cli configure using encoded chars data <&"
|
new "cli configure using encoded chars data <&"
|
||||||
expectfn "$clixon_cli -1 -f $cfg set interfaces interface eth/0/0 description \"foo<&bar\"" ""
|
expectfn "$clixon_cli -1 -f $cfg set interfaces interface eth/0/0 description \"foo<&bar\"" 0 ""
|
||||||
new "cli configure using encoded chars name <&"
|
new "cli configure using encoded chars name <&"
|
||||||
expectfn "$clixon_cli -1 -f $cfg set interfaces interface fddi&< type eth" ""
|
expectfn "$clixon_cli -1 -f $cfg set interfaces interface fddi&< type ianaift:ethernetCsmacd" 0 ""
|
||||||
|
|
||||||
new "cli failed validate"
|
new "cli failed validate"
|
||||||
expectfn "$clixon_cli -1 -f $cfg -l o validate" "Missing mandatory variable"
|
expectfn "$clixon_cli -1 -f $cfg -l o validate" 0 "Missing mandatory variable"
|
||||||
|
|
||||||
new "cli configure more"
|
new "cli configure more"
|
||||||
expectfn "$clixon_cli -1 -f $cfg set interfaces interface eth/0/0 ipv4 address 1.2.3.4 prefix-length 24" "^$"
|
expectfn "$clixon_cli -1 -f $cfg set interfaces interface eth/0/0 ipv4 address 1.2.3.4 prefix-length 24" 0 "^$"
|
||||||
expectfn "$clixon_cli -1 -f $cfg set interfaces interface eth/0/0 description mydesc" "^$"
|
expectfn "$clixon_cli -1 -f $cfg set interfaces interface eth/0/0 description mydesc" 0 "^$"
|
||||||
expectfn "$clixon_cli -1 -f $cfg set interfaces interface eth/0/0 type bgp" "^$"
|
expectfn "$clixon_cli -1 -f $cfg set interfaces interface eth/0/0 type ex:eth" 0 "^$"
|
||||||
|
|
||||||
new "cli show xpath description"
|
new "cli show xpath description"
|
||||||
expectfn "$clixon_cli -1 -f $cfg -l o show xpath /interfaces/interface/description" "<description>mydesc</description>"
|
expectfn "$clixon_cli -1 -f $cfg -l o show xpath /interfaces/interface/description" 0 "<description>mydesc</description>"
|
||||||
|
|
||||||
new "cli delete description"
|
new "cli delete description"
|
||||||
expectfn "$clixon_cli -1 -f $cfg -l o delete interfaces interface eth/0/0 description mydesc"
|
expectfn "$clixon_cli -1 -f $cfg -l o delete interfaces interface eth/0/0 description mydesc" 0 ""
|
||||||
|
|
||||||
new "cli show xpath no description"
|
new "cli show xpath no description"
|
||||||
expectfn "$clixon_cli -1 -f $cfg -l o show xpath /interfaces/interface/description" "^$"
|
expectfn "$clixon_cli -1 -f $cfg -l o show xpath /interfaces/interface/description" 0 "^$"
|
||||||
|
|
||||||
new "cli copy interface"
|
new "cli copy interface"
|
||||||
expectfn "$clixon_cli -1 -f $cfg copy interface eth/0/0 to eth99" "^$"
|
expectfn "$clixon_cli -1 -f $cfg copy interface eth/0/0 to eth99" 0 "^$"
|
||||||
|
|
||||||
new "cli success validate"
|
new "cli success validate"
|
||||||
expectfn "$clixon_cli -1 -f $cfg -l o validate" "^$"
|
expectfn "$clixon_cli -1 -f $cfg -l o validate" 0 "^$"
|
||||||
|
|
||||||
new "cli commit"
|
new "cli commit"
|
||||||
expectfn "$clixon_cli -1 -f $cfg -l o commit" "^$"
|
expectfn "$clixon_cli -1 -f $cfg -l o commit" 0 "^$"
|
||||||
|
|
||||||
new "cli save"
|
new "cli save"
|
||||||
expectfn "$clixon_cli -1 -f $cfg -l o save /tmp/foo" "^$"
|
expectfn "$clixon_cli -1 -f $cfg -l o save /tmp/foo" 0 "^$"
|
||||||
|
|
||||||
new "cli delete all"
|
new "cli delete all"
|
||||||
expectfn "$clixon_cli -1 -f $cfg -l o delete all" "^$"
|
expectfn "$clixon_cli -1 -f $cfg -l o delete all" 0 "^$"
|
||||||
|
|
||||||
new "cli load"
|
new "cli load"
|
||||||
expectfn "$clixon_cli -1 -f $cfg -l o load /tmp/foo" "^$"
|
expectfn "$clixon_cli -1 -f $cfg -l o load /tmp/foo" 0 "^$"
|
||||||
|
|
||||||
new "cli check load"
|
new "cli check load"
|
||||||
expectfn "$clixon_cli -1 -f $cfg -l o show conf cli" "^interfaces interface name eth/0/0 type bgp
|
expectfn "$clixon_cli -1 -f $cfg -l o show conf cli" 0 "interfaces interface eth/0/0 ipv4 enabled true"
|
||||||
interfaces interface eth/0/0 ipv4 enabled true"
|
|
||||||
|
|
||||||
new "cli debug"
|
new "cli debug"
|
||||||
expectfn "$clixon_cli -1 -f $cfg -l o debug level 1" "^$"
|
expectfn "$clixon_cli -1 -f $cfg -l o debug level 1" 0 "^$"
|
||||||
# How to test this?
|
# How to test this?
|
||||||
expectfn "$clixon_cli -1 -f $cfg -l o debug level 0" "^$"
|
expectfn "$clixon_cli -1 -f $cfg -l o debug level 0" 0 "^$"
|
||||||
|
|
||||||
new "cli rpc"
|
new "cli rpc"
|
||||||
expectfn "$clixon_cli -1 -f $cfg -l o rpc ipv4" "^<rpc-reply>"
|
expectfn "$clixon_cli -1 -f $cfg -l o rpc ipv4" 0 "<address-family>ipv4</address-family>" "<next-hop-list>2.3.4.5</next-hop-list>"
|
||||||
|
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
# Check if still alive
|
# Check if still alive
|
||||||
|
|
|
||||||
|
|
@ -57,99 +57,99 @@ run(){
|
||||||
conf="-d candidate -b $mydir -p ../datastore/$name/$name.so -y $dir -m ietf-ip"
|
conf="-d candidate -b $mydir -p ../datastore/$name/$name.so -y $dir -m ietf-ip"
|
||||||
|
|
||||||
new "datastore $name init"
|
new "datastore $name init"
|
||||||
expectfn "$datastore $conf init" ""
|
expectfn "$datastore $conf init" 0 ""
|
||||||
|
|
||||||
# Whole tree operations
|
# Whole tree operations
|
||||||
new "datastore $name put all replace"
|
new "datastore $name put all replace"
|
||||||
expectfn "$datastore $conf put replace $db" ""
|
expectfn "$datastore $conf put replace $db" 0 ""
|
||||||
|
|
||||||
new "datastore $name get"
|
new "datastore $name get"
|
||||||
expectfn "$datastore $conf get /" "^$db$"
|
expectfn "$datastore $conf get /" 0 "^$db$"
|
||||||
|
|
||||||
new "datastore $name put all remove"
|
new "datastore $name put all remove"
|
||||||
expectfn "$datastore $conf put remove <config/>"
|
expectfn "$datastore $conf put remove <config/>" 0 ""
|
||||||
|
|
||||||
new "datastore $name get"
|
new "datastore $name get"
|
||||||
expectfn "$datastore $conf get /" "^<config/>$"
|
expectfn "$datastore $conf get /" 0 "^<config/>$"
|
||||||
|
|
||||||
new "datastore $name put all merge"
|
new "datastore $name put all merge"
|
||||||
expectfn "$datastore $conf put merge $db" ""
|
expectfn "$datastore $conf put merge $db" 0 ""
|
||||||
|
|
||||||
new "datastore $name get"
|
new "datastore $name get"
|
||||||
expectfn "$datastore $conf get /" "^$db$"
|
expectfn "$datastore $conf get /" 0 "^$db$"
|
||||||
|
|
||||||
new "datastore $name put all delete"
|
new "datastore $name put all delete"
|
||||||
expectfn "$datastore $conf put remove <config/>"
|
expectfn "$datastore $conf put remove <config/>" 0 ""
|
||||||
|
|
||||||
new "datastore $name get"
|
new "datastore $name get"
|
||||||
expectfn "$datastore $conf get /" "^<config/>$"
|
expectfn "$datastore $conf get /" 0 "^<config/>$"
|
||||||
|
|
||||||
new "datastore $name put all create"
|
new "datastore $name put all create"
|
||||||
expectfn "$datastore $conf put create $db" ""
|
expectfn "$datastore $conf put create $db" 0 ""
|
||||||
|
|
||||||
new "datastore $name get"
|
new "datastore $name get"
|
||||||
expectfn "$datastore $conf get /" "^$db$"
|
expectfn "$datastore $conf get /" 0 "^$db$"
|
||||||
|
|
||||||
new "datastore $name put top create"
|
new "datastore $name put top create"
|
||||||
expectfn "$datastore $conf put create <config><x/></config>" "" # error
|
expectfn "$datastore $conf put create <config><x/></config>" 0 "" # error
|
||||||
|
|
||||||
# Single key operations
|
# Single key operations
|
||||||
# leaf
|
# leaf
|
||||||
new "datastore $name put all delete"
|
new "datastore $name put all delete"
|
||||||
expectfn "$datastore $conf delete" ""
|
expectfn "$datastore $conf delete" 0 ""
|
||||||
|
|
||||||
new "datastore $name init"
|
new "datastore $name init"
|
||||||
expectfn "$datastore $conf init" ""
|
expectfn "$datastore $conf init" 0 ""
|
||||||
|
|
||||||
new "datastore $name create leaf"
|
new "datastore $name create leaf"
|
||||||
expectfn "$datastore $conf put create <config><x><y><a>1</a><b>3</b><c>newentry</c></y></x></config>"
|
expectfn "$datastore $conf put create <config><x><y><a>1</a><b>3</b><c>newentry</c></y></x></config>" 0 ""
|
||||||
|
|
||||||
new "datastore $name create leaf"
|
new "datastore $name create leaf"
|
||||||
expectfn "$datastore $conf put create <config><x><y><a>1</a><b>3</b><c>newentry</c></y></x></config>"
|
expectfn "$datastore $conf put create <config><x><y><a>1</a><b>3</b><c>newentry</c></y></x></config>" 0 ""
|
||||||
|
|
||||||
new "datastore $name delete leaf"
|
new "datastore $name delete leaf"
|
||||||
expectfn "$datastore $conf put delete <config><x><y><a>1</a><b>3</b></y></x></config>"
|
expectfn "$datastore $conf put delete <config><x><y><a>1</a><b>3</b></y></x></config>" 0 ""
|
||||||
|
|
||||||
new "datastore $name replace leaf"
|
new "datastore $name replace leaf"
|
||||||
expectfn "$datastore $conf put create <config><x><y><a>1</a><b>3</b><c>newentry</c></y></x></config>"
|
expectfn "$datastore $conf put create <config><x><y><a>1</a><b>3</b><c>newentry</c></y></x></config>" 0 ""
|
||||||
|
|
||||||
new "datastore $name remove leaf"
|
new "datastore $name remove leaf"
|
||||||
expectfn "$datastore $conf put remove <config><x><g/></x></config>"
|
expectfn "$datastore $conf put remove <config><x><g/></x></config>" 0 ""
|
||||||
|
|
||||||
new "datastore $name remove leaf"
|
new "datastore $name remove leaf"
|
||||||
expectfn "$datastore $conf put remove <config><x><y><a>1</a><b>3</b><c/></y></x></config>"
|
expectfn "$datastore $conf put remove <config><x><y><a>1</a><b>3</b><c/></y></x></config>" 0 ""
|
||||||
|
|
||||||
new "datastore $name delete leaf"
|
new "datastore $name delete leaf"
|
||||||
expectfn "$datastore $conf put delete <config><x><g/></x></config>"
|
expectfn "$datastore $conf put delete <config><x><g/></x></config>" 0 ""
|
||||||
|
|
||||||
new "datastore $name merge leaf"
|
new "datastore $name merge leaf"
|
||||||
expectfn "$datastore $conf put merge <config><x><g>nalle</g></x></config>"
|
expectfn "$datastore $conf put merge <config><x><g>nalle</g></x></config>" 0 ""
|
||||||
|
|
||||||
new "datastore $name replace leaf"
|
new "datastore $name replace leaf"
|
||||||
expectfn "$datastore $conf put replace <config><x><g>nalle</g></x></config>"
|
expectfn "$datastore $conf put replace <config><x><g>nalle</g></x></config>" 0 ""
|
||||||
|
|
||||||
new "datastore $name merge leaf"
|
new "datastore $name merge leaf"
|
||||||
expectfn "$datastore $conf put merge <config><x><y><a>1</a><b>3</b><c>newentry</c></y></x></config>"
|
expectfn "$datastore $conf put merge <config><x><y><a>1</a><b>3</b><c>newentry</c></y></x></config>" 0 ""
|
||||||
|
|
||||||
new "datastore $name replace leaf"
|
new "datastore $name replace leaf"
|
||||||
expectfn "$datastore $conf put replace <config><x><y><a>1</a><b>3</b><c>newentry</c></y></x></config>"
|
expectfn "$datastore $conf put replace <config><x><y><a>1</a><b>3</b><c>newentry</c></y></x></config>" 0 ""
|
||||||
|
|
||||||
new "datastore $name create leaf"
|
new "datastore $name create leaf"
|
||||||
expectfn "$datastore $conf put create <config><x><h><j>aaa</j></h></x></config>"
|
expectfn "$datastore $conf put create <config><x><h><j>aaa</j></h></x></config>" 0 ""
|
||||||
|
|
||||||
new "datastore $name create leaf"
|
new "datastore $name create leaf"
|
||||||
expectfn "$datastore $conf put create <config><x><y><a>1</a><b>3</b><c>newentry</c></y></x></config>"
|
expectfn "$datastore $conf put create <config><x><y><a>1</a><b>3</b><c>newentry</c></y></x></config>" 0 ""
|
||||||
|
|
||||||
new "datastore other db init"
|
new "datastore other db init"
|
||||||
expectfn "$datastore -d kalle -b $mydir -p ../datastore/$name/$name.so -y $dir -m ietf-ip init"
|
expectfn "$datastore -d kalle -b $mydir -p ../datastore/$name/$name.so -y $dir -m ietf-ip init" 0 ""
|
||||||
|
|
||||||
new "datastore other db copy"
|
new "datastore other db copy"
|
||||||
expectfn "$datastore $conf copy kalle" ""
|
expectfn "$datastore $conf copy kalle" 0 ""
|
||||||
|
|
||||||
diff $mydir/kalle_db $mydir/candidate_db
|
diff $mydir/kalle_db $mydir/candidate_db
|
||||||
|
|
||||||
new "datastore lock"
|
new "datastore lock"
|
||||||
expectfn "$datastore $conf lock 756" ""
|
expectfn "$datastore $conf lock 756" 0 ""
|
||||||
|
|
||||||
#leaf-list
|
#leaf-list
|
||||||
|
|
||||||
|
|
|
||||||
188
test/test_identity.sh
Executable file
188
test/test_identity.sh
Executable file
|
|
@ -0,0 +1,188 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Identity and identityref tests
|
||||||
|
APPNAME=example
|
||||||
|
# include err() and new() functions and creates $dir
|
||||||
|
. ./lib.sh
|
||||||
|
|
||||||
|
cfg=$dir/conf_yang.xml
|
||||||
|
fyang=$dir/example-my-crypto.yang
|
||||||
|
|
||||||
|
cat <<EOF > $cfg
|
||||||
|
<config>
|
||||||
|
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||||
|
<CLICON_YANG_DIR>$dir</CLICON_YANG_DIR>
|
||||||
|
<CLICON_YANG_MODULE_MAIN>$fyang</CLICON_YANG_MODULE_MAIN>
|
||||||
|
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||||
|
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
|
||||||
|
<CLICON_BACKEND_REGEXP>example_backend.so$</CLICON_BACKEND_REGEXP>
|
||||||
|
<CLICON_NETCONF_DIR>/usr/local/lib/$APPNAME/netconf</CLICON_NETCONF_DIR>
|
||||||
|
<CLICON_RESTCONF_DIR>/usr/local/lib/$APPNAME/restconf</CLICON_RESTCONF_DIR>
|
||||||
|
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||||
|
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
||||||
|
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||||
|
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||||
|
<CLICON_CLI_GENMODEL_COMPLETION>1</CLICON_CLI_GENMODEL_COMPLETION>
|
||||||
|
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||||
|
<CLICON_XMLDB_PLUGIN>/usr/local/lib/xmldb/text.so</CLICON_XMLDB_PLUGIN>
|
||||||
|
</config>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Example from RFC7950 Sec 7.18 and 9.10
|
||||||
|
# with two changes: the leaf statement is in the original module and
|
||||||
|
# a transitive dependent identifier (foo)
|
||||||
|
cat <<EOF > $dir/example-crypto-base.yang
|
||||||
|
module example-crypto-base {
|
||||||
|
yang-version 1.1;
|
||||||
|
namespace "urn:example:crypto-base";
|
||||||
|
prefix "crypto";
|
||||||
|
|
||||||
|
identity crypto-alg {
|
||||||
|
description
|
||||||
|
"Base identity from which all crypto algorithms
|
||||||
|
are derived.";
|
||||||
|
}
|
||||||
|
identity symmetric-key {
|
||||||
|
description
|
||||||
|
"Base identity used to identify symmetric-key crypto
|
||||||
|
algorithms.";
|
||||||
|
}
|
||||||
|
identity public-key {
|
||||||
|
description
|
||||||
|
"Base identity used to identify public-key crypto
|
||||||
|
algorithms.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat <<EOF > $dir/example-des.yang
|
||||||
|
module example-des {
|
||||||
|
yang-version 1.1;
|
||||||
|
namespace "urn:example:des";
|
||||||
|
prefix "des";
|
||||||
|
import "example-crypto-base" {
|
||||||
|
prefix "crypto";
|
||||||
|
}
|
||||||
|
identity des {
|
||||||
|
base "crypto:crypto-alg";
|
||||||
|
base "crypto:symmetric-key";
|
||||||
|
description "DES crypto algorithm.";
|
||||||
|
}
|
||||||
|
identity des3 {
|
||||||
|
base "crypto:crypto-alg";
|
||||||
|
base "crypto:symmetric-key";
|
||||||
|
description "Triple DES crypto algorithm.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat <<EOF > $fyang
|
||||||
|
module example {
|
||||||
|
yang-version 1.1;
|
||||||
|
namespace "urn:example:my-crypto";
|
||||||
|
prefix mc;
|
||||||
|
import "example-crypto-base" {
|
||||||
|
prefix "crypto";
|
||||||
|
}
|
||||||
|
import "example-des" {
|
||||||
|
prefix "des";
|
||||||
|
}
|
||||||
|
identity aes {
|
||||||
|
base "crypto:crypto-alg";
|
||||||
|
}
|
||||||
|
identity foo {
|
||||||
|
description "transitive dependent identifier";
|
||||||
|
base "des:des";
|
||||||
|
}
|
||||||
|
leaf crypto {
|
||||||
|
description "Value can be any transitively derived from crypto-alg";
|
||||||
|
type identityref {
|
||||||
|
base "crypto:crypto-alg";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
container aes-parameters {
|
||||||
|
when "../crypto = 'mc:aes'";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# kill old backend (if any)
|
||||||
|
new "kill old backend"
|
||||||
|
sudo clixon_backend -zf $cfg
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
err
|
||||||
|
fi
|
||||||
|
new "start backend -s init -f $cfg -y $fyang"
|
||||||
|
# start new backend
|
||||||
|
sudo clixon_backend -s init -f $cfg -y $fyang # -D 1
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
err
|
||||||
|
fi
|
||||||
|
|
||||||
|
new "Set crypto to aes"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><crypto>aes</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "netconf validate "
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "Set crypto to mc:aes"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><crypto>mc:aes</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "netconf validate"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "Set crypto to des:des3"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><crypto>des:des3</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "netconf validate"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "Set crypto to mc:foo"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><crypto>mc:foo</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "netconf validate"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
#new "Set crypto to x:des3"
|
||||||
|
#expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><crypto xmlns:x=\"urn:example:des\">x:des3</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "netconf validate"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "Set crypto to foo:bar"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><crypto>foo:bar</crypto></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "netconf validate"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>operation-failed</error-tag><error-type>application</error-type><error-severity>error</error-severity><error-message>Identityref validation failed, foo:bar not derived from crypto-alg</error-message></rpc-error></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
|
new "cli set crypto to mc:aes"
|
||||||
|
expectfn "$clixon_cli -1 -f $cfg -l o set crypto mc:aes" 0 "^$"
|
||||||
|
|
||||||
|
new "cli validate"
|
||||||
|
expectfn "$clixon_cli -1 -f $cfg -l o validate" 0 "^$"
|
||||||
|
|
||||||
|
new "cli set crypto to aes"
|
||||||
|
expectfn "$clixon_cli -1 -f $cfg -l o set crypto aes" 0 "^$"
|
||||||
|
|
||||||
|
new "cli validate"
|
||||||
|
expectfn "$clixon_cli -1 -f $cfg -l o validate" 0 "^$"
|
||||||
|
|
||||||
|
new "cli set crypto to des:des3"
|
||||||
|
expectfn "$clixon_cli -1 -f $cfg -l o set crypto des:des3" 0 "^$"
|
||||||
|
|
||||||
|
new "cli validate"
|
||||||
|
expectfn "$clixon_cli -1 -f $cfg -l o validate" 0 "^$"
|
||||||
|
|
||||||
|
new "Kill backend"
|
||||||
|
# Check if still alive
|
||||||
|
pid=`pgrep clixon_backend`
|
||||||
|
if [ -z "$pid" ]; then
|
||||||
|
err "backend already dead"
|
||||||
|
fi
|
||||||
|
# kill backend
|
||||||
|
sudo clixon_backend -zf $cfg
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
err "kill backend"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf $dir
|
||||||
|
|
@ -24,9 +24,19 @@ EOF
|
||||||
|
|
||||||
cat <<EOF > $fyang
|
cat <<EOF > $fyang
|
||||||
module example{
|
module example{
|
||||||
|
prefix ex;
|
||||||
|
import ietf-interfaces {
|
||||||
|
prefix if;
|
||||||
|
}
|
||||||
import ietf-ip {
|
import ietf-ip {
|
||||||
prefix ip;
|
prefix ip;
|
||||||
}
|
}
|
||||||
|
identity eth {
|
||||||
|
base if:interface-type;
|
||||||
|
}
|
||||||
|
identity lo {
|
||||||
|
base if:interface-type;
|
||||||
|
}
|
||||||
container default-address {
|
container default-address {
|
||||||
leaf absname {
|
leaf absname {
|
||||||
type leafref {
|
type leafref {
|
||||||
|
|
@ -75,8 +85,8 @@ fi
|
||||||
|
|
||||||
new "leafref base config"
|
new "leafref base config"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><interfaces>
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><interfaces>
|
||||||
<interface><name>eth0</name> <type>eth</type> <ipv4><address><ip>192.0.2.1</ip></address><address><ip>192.0.2.2</ip></address></ipv4></interface>
|
<interface><name>eth0</name><type>ex:eth</type> <ipv4><address><ip>192.0.2.1</ip></address><address><ip>192.0.2.2</ip></address></ipv4></interface>
|
||||||
<interface><name>lo</name><type>lo</type><ipv4><address><ip>127.0.0.1</ip></address></ipv4></interface>
|
<interface><name>lo</name><type>ex:lo</type><ipv4><address><ip>127.0.0.1</ip></address></ipv4></interface>
|
||||||
</interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
</interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "leafref get config"
|
new "leafref get config"
|
||||||
|
|
@ -115,16 +125,16 @@ new "leafref discard-changes"
|
||||||
expecteof "$clixon_netconf -qf $cfg" "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "cli leafref lo"
|
new "cli leafref lo"
|
||||||
expectfn "$clixon_cli -1f $cfg -y $fyang -l o set default-address absname lo" "^$"
|
expectfn "$clixon_cli -1f $cfg -y $fyang -l o set default-address absname lo" 0 "^$"
|
||||||
|
|
||||||
new "cli leafref validate"
|
new "cli leafref validate"
|
||||||
expectfn "$clixon_cli -1f $cfg -y $fyang -l o validate" "^$"
|
expectfn "$clixon_cli -1f $cfg -y $fyang -l o validate" 0 "^$"
|
||||||
|
|
||||||
new "cli sender"
|
new "cli sender"
|
||||||
expectfn "$clixon_cli -1f $cfg -y $fyang -l o set sender a" "^$"
|
expectfn "$clixon_cli -1f $cfg -y $fyang -l o set sender a" 0 "^$"
|
||||||
|
|
||||||
new "cli sender template"
|
new "cli sender template"
|
||||||
expectfn "$clixon_cli -1f $cfg -y $fyang -l o set sender b template a" "^$"
|
expectfn "$clixon_cli -1f $cfg -y $fyang -l o set sender b template a" 0 "^$"
|
||||||
|
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
# Check if still alive
|
# Check if still alive
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,9 @@ EOF
|
||||||
cat <<EOF > $fyang
|
cat <<EOF > $fyang
|
||||||
module example{
|
module example{
|
||||||
prefix ex;
|
prefix ex;
|
||||||
|
import ietf-interfaces {
|
||||||
|
prefix if;
|
||||||
|
}
|
||||||
import ietf-ip {
|
import ietf-ip {
|
||||||
prefix ip;
|
prefix ip;
|
||||||
}
|
}
|
||||||
|
|
@ -42,6 +45,9 @@ module example{
|
||||||
}
|
}
|
||||||
rpc empty {
|
rpc empty {
|
||||||
}
|
}
|
||||||
|
identity eth {
|
||||||
|
base if:interface-type;
|
||||||
|
}
|
||||||
rpc client-rpc {
|
rpc client-rpc {
|
||||||
description "Example local client-side RPC that is processed by the
|
description "Example local client-side RPC that is processed by the
|
||||||
the netconf/restconf and not sent to the backend.
|
the netconf/restconf and not sent to the backend.
|
||||||
|
|
@ -84,22 +90,22 @@ new "Check nothing added"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc message-id="101"><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '^<rpc-reply message-id="101"><data/></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc message-id="101"><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '^<rpc-reply message-id="101"><data/></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
new "Add subtree eth/0/0 using none and create which should add eth/0/0"
|
new "Add subtree eth/0/0 using none and create which should add eth/0/0"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="create"><name>eth/0/0</name><type>eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="create"><name>eth/0/0</name><type>ex:eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "Check eth/0/0 added using xpath"
|
new "Check eth/0/0 added using xpath"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface[name=eth/0/0]"/></get-config></rpc>]]>]]>' "^<rpc-reply><data><interfaces><interface><name>eth/0/0</name><type>eth</type><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface[name=eth/0/0]"/></get-config></rpc>]]>]]>' "^<rpc-reply><data><interfaces><interface><name>eth/0/0</name><type>ex:eth</type><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "Re-create same eth/0/0 which should generate error"
|
new "Re-create same eth/0/0 which should generate error"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="create"><name>eth/0/0</name><type>eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><rpc-error>"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="create"><name>eth/0/0</name><type>ex:eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><rpc-error>"
|
||||||
|
|
||||||
new "Delete eth/0/0 using none config"
|
new "Delete eth/0/0 using none config"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="delete"><name>eth/0/0</name><type>eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="delete"><name>eth/0/0</name><type>ex:eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "Check deleted eth/0/0 (non-presence container)"
|
new "Check deleted eth/0/0 (non-presence container)"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc message-id="101"><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '^<rpc-reply message-id="101"><data/></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc message-id="101"><get-config><source><candidate/></source></get-config></rpc>]]>]]>' '^<rpc-reply message-id="101"><data/></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
new "Re-Delete eth/0/0 using none should generate error"
|
new "Re-Delete eth/0/0 using none should generate error"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="delete"><name>eth/0/0</name><type>eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><rpc-error>"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="delete"><name>eth/0/0</name><type>ex:eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><rpc-error>"
|
||||||
|
|
||||||
new "netconf edit config"
|
new "netconf edit config"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth/0/0</name></interface><interface><name>eth1</name><enabled>true</enabled><ipv4><address><ip>9.2.3.4</ip><prefix-length>24</prefix-length></address></ipv4></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth/0/0</name></interface><interface><name>eth1</name><enabled>true</enabled><ipv4><address><ip>9.2.3.4</ip><prefix-length>24</prefix-length></address></ipv4></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
@ -126,7 +132,7 @@ new "netconf discard-changes"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf edit config eth1"
|
new "netconf edit config eth1"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth1</name><type>eth</type></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth1</name><type>ex:eth</type></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf validate"
|
new "netconf validate"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
@ -135,26 +141,26 @@ new "netconf commit"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf edit config merge"
|
new "netconf edit config merge"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth2</name><type>eth</type></interface></interfaces></config><default-operation>merge</default-operation></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth2</name><type>ex:eth</type></interface></interfaces></config><default-operation>merge</default-operation></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf edit ampersand encoding(<&): name:'eth&' type:'t<>'"
|
new "netconf edit ampersand encoding(<&): name:'eth&' type:'t<>'"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth& </name><type>t< > </type></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth& </name><type>t< > </type></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf get replaced config"
|
new "netconf get replaced config"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><interfaces><interface><name>eth& </name><type>t< > </type><enabled>true</enabled></interface><interface><name>eth1</name><type>eth</type><enabled>true</enabled></interface><interface><name>eth2</name><type>eth</type><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><interfaces><interface><name>eth& </name><type>t< > </type><enabled>true</enabled></interface><interface><name>eth1</name><type>ex:eth</type><enabled>true</enabled></interface><interface><name>eth2</name><type>ex:eth</type><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "cli show configuration eth& - encoding tests"
|
new "cli show configuration eth& - encoding tests"
|
||||||
expectfn "$clixon_cli -1 -f $cfg -y $fyang show conf cli" "interfaces interface eth& type t<>
|
expectfn "$clixon_cli -1 -f $cfg -y $fyang show conf cli" 0 "interfaces interface eth& type t<>
|
||||||
interfaces interface eth& enabled true"
|
interfaces interface eth& enabled true"
|
||||||
|
|
||||||
new "netconf discard-changes"
|
new "netconf discard-changes"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf edit state operation should fail"
|
new "netconf edit state operation should fail"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><interfaces-state><interface><name>eth1</name><type>eth</type></interface></interfaces-state></config></edit-config></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>invalid-value</error-tag>"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><interfaces-state><interface><name>eth1</name><type>ex:eth</type></interface></interfaces-state></config></edit-config></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>invalid-value</error-tag>"
|
||||||
|
|
||||||
new "netconf get state operation"
|
new "netconf get state operation"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get><filter type=\"xpath\" select=\"/interfaces-state\"/></get></rpc>]]>]]>" "^<rpc-reply><data><interfaces-state><interface><name>eth0</name><type>eth</type><if-index>42</if-index></interface></interfaces-state></data></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get><filter type=\"xpath\" select=\"/interfaces-state\"/></get></rpc>]]>]]>" "^<rpc-reply><data><interfaces-state><interface><name>eth0</name><type>ex:eth</type><if-index>42</if-index></interface></interfaces-state></data></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf lock/unlock"
|
new "netconf lock/unlock"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><lock><target><candidate/></target></lock></rpc>]]>]]><rpc><unlock><target><candidate/></target></unlock></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]><rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><lock><target><candidate/></target></lock></rpc>]]>]]><rpc><unlock><target><candidate/></target></unlock></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]><rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
@ -175,7 +181,7 @@ new "copy startup"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><copy-config><target><startup/></target><source><candidate/></source></copy-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><copy-config><target><startup/></target><source><candidate/></source></copy-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf get startup"
|
new "netconf get startup"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><startup/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><interfaces><interface><name>eth1</name><type>eth</type><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get-config><source><startup/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><interfaces><interface><name>eth1</name><type>ex:eth</type><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "netconf delete startup"
|
new "netconf delete startup"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><delete-config><target><startup/></target></delete-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><delete-config><target><startup/></target></delete-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,9 @@ EOF
|
||||||
cat <<EOF > $fyang
|
cat <<EOF > $fyang
|
||||||
module example{
|
module example{
|
||||||
prefix ex;
|
prefix ex;
|
||||||
|
import ietf-interfaces {
|
||||||
|
prefix if;
|
||||||
|
}
|
||||||
import ietf-ip {
|
import ietf-ip {
|
||||||
prefix ip;
|
prefix ip;
|
||||||
}
|
}
|
||||||
|
|
@ -41,6 +44,9 @@ module example{
|
||||||
prefix "inet";
|
prefix "inet";
|
||||||
revision-date "2013-07-15";
|
revision-date "2013-07-15";
|
||||||
}
|
}
|
||||||
|
identity eth {
|
||||||
|
base if:interface-type;
|
||||||
|
}
|
||||||
rpc empty {
|
rpc empty {
|
||||||
}
|
}
|
||||||
rpc input {
|
rpc input {
|
||||||
|
|
@ -68,7 +74,7 @@ module example{
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# This is a fixed 'state' implemented in routing_backend. It is assumed to be always there
|
# This is a fixed 'state' implemented in routing_backend. It is assumed to be always there
|
||||||
state='{"interfaces-state": {"interface": \[{"name": "eth0","type": "eth","if-index": 42}\]}}'
|
state='{"interfaces-state": {"interface": \[{"name": "eth0","type": "ex:eth","if-index": 42}\]}}'
|
||||||
|
|
||||||
# kill old backend (if any)
|
# kill old backend (if any)
|
||||||
new "kill old backend"
|
new "kill old backend"
|
||||||
|
|
@ -130,113 +136,113 @@ if [ -z "$match" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "restconf options. RFC 8040 4.1"
|
new "restconf options. RFC 8040 4.1"
|
||||||
expectfn "curl -i -s -X OPTIONS http://localhost/restconf/data" "Allow: OPTIONS,HEAD,GET,POST,PUT,DELETE"
|
expectfn "curl -i -s -X OPTIONS http://localhost/restconf/data" 0 "Allow: OPTIONS,HEAD,GET,POST,PUT,DELETE"
|
||||||
|
|
||||||
new "restconf head. RFC 8040 4.2"
|
new "restconf head. RFC 8040 4.2"
|
||||||
expectfn "curl -s -I http://localhost/restconf/data" "HTTP/1.1 200 OK"
|
expectfn "curl -s -I http://localhost/restconf/data" 0 "HTTP/1.1 200 OK"
|
||||||
#Content-Type: application/yang-data+json"
|
#Content-Type: application/yang-data+json"
|
||||||
|
|
||||||
new2 "restconf empty rpc"
|
new2 "restconf empty rpc"
|
||||||
expecteq "$(curl -s -X POST -d {\"input\":{\"name\":\"\"}} http://localhost/restconf/operations/ex:empty)" ""
|
expecteq "$(curl -s -X POST -d {\"input\":{\"name\":\"\"}} http://localhost/restconf/operations/ex:empty)" ""
|
||||||
|
|
||||||
new2 "restconf get empty config + state json"
|
new2 "restconf get empty config + state json"
|
||||||
expecteq "$(curl -sSG http://localhost/restconf/data)" '{"data": {"interfaces-state": {"interface": [{"name": "eth0","type": "eth","if-index": 42}]}}}
|
expecteq "$(curl -sSG http://localhost/restconf/data)" '{"data": {"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}}
|
||||||
'
|
'
|
||||||
|
|
||||||
new "restconf get empty config + state xml"
|
new "restconf get empty config + state xml"
|
||||||
ret=$(curl -s -H "Accept: application/yang-data+xml" -G http://localhost/restconf/data)
|
ret=$(curl -s -H "Accept: application/yang-data+xml" -G http://localhost/restconf/data)
|
||||||
expect="<data><interfaces-state><interface><name>eth0</name><type>eth</type><if-index>42</if-index></interface></interfaces-state></data>"
|
expect="<data><interfaces-state><interface><name>eth0</name><type>ex:eth</type><if-index>42</if-index></interface></interfaces-state></data>"
|
||||||
match=`echo $ret | grep -EZo "$expect"`
|
match=`echo $ret | grep -EZo "$expect"`
|
||||||
if [ -z "$match" ]; then
|
if [ -z "$match" ]; then
|
||||||
err "$expect" "$ret"
|
err "$expect" "$ret"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new2 "restconf get data/interfaces-state/interface=eth0 json"
|
new2 "restconf get data/interfaces-state/interface=eth0 json"
|
||||||
expecteq "$(curl -s -G http://localhost/restconf/data/interfaces-state/interface=eth0)" '{"interface": [{"name": "eth0","type": "eth","if-index": 42}]}
|
expecteq "$(curl -s -G http://localhost/restconf/data/interfaces-state/interface=eth0)" '{"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}
|
||||||
'
|
'
|
||||||
|
|
||||||
new "restconf get state operation eth0 xml"
|
new "restconf get state operation eth0 xml"
|
||||||
# Cant get shell macros to work, inline matching from lib.sh
|
# Cant get shell macros to work, inline matching from lib.sh
|
||||||
ret=$(curl -s -H "Accept: application/yang-data+xml" -G http://localhost/restconf/data/interfaces-state/interface=eth0)
|
ret=$(curl -s -H "Accept: application/yang-data+xml" -G http://localhost/restconf/data/interfaces-state/interface=eth0)
|
||||||
expect="<interface><name>eth0</name><type>eth</type><if-index>42</if-index></interface>"
|
expect="<interface><name>eth0</name><type>ex:eth</type><if-index>42</if-index></interface>"
|
||||||
match=`echo $ret | grep -EZo "$expect"`
|
match=`echo $ret | grep -EZo "$expect"`
|
||||||
if [ -z "$match" ]; then
|
if [ -z "$match" ]; then
|
||||||
err "$expect" "$ret"
|
err "$expect" "$ret"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new2 "restconf get state operation eth0 type json"
|
new2 "restconf get state operation eth0 type json"
|
||||||
expecteq "$(curl -s -G http://localhost/restconf/data/interfaces-state/interface=eth0/type)" '{"type": "eth"}
|
expecteq "$(curl -s -G http://localhost/restconf/data/interfaces-state/interface=eth0/type)" '{"type": "ex:eth"}
|
||||||
'
|
'
|
||||||
|
|
||||||
new "restconf get state operation eth0 type xml"
|
new "restconf get state operation eth0 type xml"
|
||||||
# Cant get shell macros to work, inline matching from lib.sh
|
# Cant get shell macros to work, inline matching from lib.sh
|
||||||
ret=$(curl -s -H "Accept: application/yang-data+xml" -G http://localhost/restconf/data/interfaces-state/interface=eth0/type)
|
ret=$(curl -s -H "Accept: application/yang-data+xml" -G http://localhost/restconf/data/interfaces-state/interface=eth0/type)
|
||||||
expect="<type>eth</type>"
|
expect="<type>ex:eth</type>"
|
||||||
match=`echo $ret | grep -EZo "$expect"`
|
match=`echo $ret | grep -EZo "$expect"`
|
||||||
if [ -z "$match" ]; then
|
if [ -z "$match" ]; then
|
||||||
err "$expect" "$ret"
|
err "$expect" "$ret"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new2 "restconf GET datastore"
|
new2 "restconf GET datastore"
|
||||||
expecteq "$(curl -s -X GET http://localhost/restconf/data)" '{"data": {"interfaces-state": {"interface": [{"name": "eth0","type": "eth","if-index": 42}]}}}
|
expecteq "$(curl -s -X GET http://localhost/restconf/data)" '{"data": {"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}}
|
||||||
'
|
'
|
||||||
|
|
||||||
# Exact match
|
# Exact match
|
||||||
new "restconf Add subtree to datastore using POST"
|
new "restconf Add subtree to datastore using POST"
|
||||||
expectfn 'curl -s -i -X POST -H "Accept: application/yang-data+json" -d {"interfaces":{"interface":{"name":"eth/0/0","type":"eth","enabled":true}}} http://localhost/restconf/data' 'HTTP/1.1 200 OK'
|
expectfn 'curl -s -i -X POST -H "Accept: application/yang-data+json" -d {"interfaces":{"interface":{"name":"eth/0/0","type":"ex:eth","enabled":true}}} http://localhost/restconf/data' 0 'HTTP/1.1 200 OK'
|
||||||
|
|
||||||
new "restconf Re-add subtree which should give error"
|
new "restconf Re-add subtree which should give error"
|
||||||
expectfn 'curl -s -X POST -d {"interfaces":{"interface":{"name":"eth/0/0","type":"eth","enabled":true}}} http://localhost/restconf/data' '{"ietf-restconf:errors" : {"error": {"error-tag": "data-exists","error-type": "application","error-severity": "error","error-message": "Data already exists; cannot create new resource"}}}'
|
expectfn 'curl -s -X POST -d {"interfaces":{"interface":{"name":"eth/0/0","type":"ex:eth","enabled":true}}} http://localhost/restconf/data' 0 '{"ietf-restconf:errors" : {"error": {"error-tag": "data-exists","error-type": "application","error-severity": "error","error-message": "Data already exists; cannot create new resource"}}}'
|
||||||
|
|
||||||
# XXX Cant get this to work
|
# XXX Cant get this to work
|
||||||
#expecteq "$(curl -s -X POST -d {\"interfaces\":{\"interface\":{\"name\":\"eth/0/0\",\"type\":\"eth\",\"enabled\":true}}} http://localhost/restconf/data)" '{"ietf-restconf:errors" : {"error": {"error-tag": "data-exists","error-type": "application","error-severity": "error","error-message": "Data already exists; cannot create new resource"}}}'
|
#expecteq "$(curl -s -X POST -d {\"interfaces\":{\"interface\":{\"name\":\"eth/0/0\",\"type\":\"ex:eth\",\"enabled\":true}}} http://localhost/restconf/data)" '{"ietf-restconf:errors" : {"error": {"error-tag": "data-exists","error-type": "application","error-severity": "error","error-message": "Data already exists; cannot create new resource"}}}'
|
||||||
|
|
||||||
new "restconf Check interfaces eth/0/0 added"
|
new "restconf Check interfaces eth/0/0 added"
|
||||||
expectfn "curl -s -G http://localhost/restconf/data" '{"interfaces": {"interface": \[{"name": "eth/0/0","type": "eth","enabled": true}\]},"interfaces-state": {"interface": \[{"name": "eth0","type": "eth","if-index": 42}\]}}
|
expectfn "curl -s -G http://localhost/restconf/data" 0 '{"interfaces": {"interface": \[{"name": "eth/0/0","type": "ex:eth","enabled": true}\]},"interfaces-state": {"interface": \[{"name": "eth0","type": "ex:eth","if-index": 42}\]}}
|
||||||
'
|
'
|
||||||
|
|
||||||
new2 "restconf delete interfaces"
|
new2 "restconf delete interfaces"
|
||||||
expecteq $(curl -s -X DELETE http://localhost/restconf/data/interfaces) ""
|
expecteq $(curl -s -X DELETE http://localhost/restconf/data/interfaces) ""
|
||||||
|
|
||||||
new "restconf Check empty config"
|
new "restconf Check empty config"
|
||||||
expectfn "curl -sG http://localhost/restconf/data" "$state"
|
expectfn "curl -sG http://localhost/restconf/data" 0 "$state"
|
||||||
|
|
||||||
new "restconf Add interfaces subtree eth/0/0 using POST"
|
new "restconf Add interfaces subtree eth/0/0 using POST"
|
||||||
expectfn 'curl -s -X POST -d {"interface":{"name":"eth/0/0","type":"eth","enabled":true}} http://localhost/restconf/data/interfaces' ""
|
expectfn 'curl -s -X POST -d {"interface":{"name":"eth/0/0","type":"ex:eth","enabled":true}} http://localhost/restconf/data/interfaces' 0 ""
|
||||||
# XXX cant get this to work
|
# XXX cant get this to work
|
||||||
#expecteq "$(curl -s -X POST -d '{"interface":{"name":"eth/0/0","type\":"eth","enabled":true}}' http://localhost/restconf/data/interfaces)" ""
|
#expecteq "$(curl -s -X POST -d '{"interface":{"name":"eth/0/0","type\":"ex:eth","enabled":true}}' http://localhost/restconf/data/interfaces)" ""
|
||||||
|
|
||||||
new2 "restconf Check eth/0/0 added"
|
new2 "restconf Check eth/0/0 added"
|
||||||
expecteq "$(curl -s -G http://localhost/restconf/data)" '{"data": {"interfaces": {"interface": [{"name": "eth/0/0","type": "eth","enabled": true}]},"interfaces-state": {"interface": [{"name": "eth0","type": "eth","if-index": 42}]}}}
|
expecteq "$(curl -s -G http://localhost/restconf/data)" '{"data": {"interfaces": {"interface": [{"name": "eth/0/0","type": "ex:eth","enabled": true}]},"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}}
|
||||||
'
|
'
|
||||||
|
|
||||||
new2 "restconf Re-post eth/0/0 which should generate error"
|
new2 "restconf Re-post eth/0/0 which should generate error"
|
||||||
expecteq "$(curl -s -X POST -d '{"interface":{"name":"eth/0/0","type":"eth","enabled":true}}' http://localhost/restconf/data/interfaces)" '{"ietf-restconf:errors" : {"error": {"error-tag": "data-exists","error-type": "application","error-severity": "error","error-message": "Data already exists; cannot create new resource"}}}
'
|
expecteq "$(curl -s -X POST -d '{"interface":{"name":"eth/0/0","type":"ex:eth","enabled":true}}' http://localhost/restconf/data/interfaces)" '{"ietf-restconf:errors" : {"error": {"error-tag": "data-exists","error-type": "application","error-severity": "error","error-message": "Data already exists; cannot create new resource"}}}
'
|
||||||
|
|
||||||
new "Add leaf description using POST"
|
new "Add leaf description using POST"
|
||||||
expecteq "$(curl -s -X POST -d '{"description":"The-first-interface"}' http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0)" ""
|
expecteq "$(curl -s -X POST -d '{"description":"The-first-interface"}' http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0)" ""
|
||||||
|
|
||||||
new "Add nothing using POST"
|
new "Add nothing using POST"
|
||||||
expectfn 'curl -s -X POST http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0' '"ietf-restconf:errors" : {"error": {"rpc-error": {"error-tag": "malformed-message","error-type": "rpc","error-severity": "error","error-message": " on line 1: syntax error at or before:'
|
expectfn 'curl -s -X POST http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0' 0 '"ietf-restconf:errors" : {"error": {"rpc-error": {"error-tag": "malformed-message","error-type": "rpc","error-severity": "error","error-message": " on line 1: syntax error at or before:'
|
||||||
|
|
||||||
new2 "restconf Check description added"
|
new2 "restconf Check description added"
|
||||||
expecteq "$(curl -s -G http://localhost/restconf/data)" '{"data": {"interfaces": {"interface": [{"name": "eth/0/0","description": "The-first-interface","type": "eth","enabled": true}]},"interfaces-state": {"interface": [{"name": "eth0","type": "eth","if-index": 42}]}}}
|
expecteq "$(curl -s -G http://localhost/restconf/data)" '{"data": {"interfaces": {"interface": [{"name": "eth/0/0","description": "The-first-interface","type": "ex:eth","enabled": true}]},"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}}
|
||||||
'
|
'
|
||||||
|
|
||||||
new "restconf delete eth/0/0"
|
new "restconf delete eth/0/0"
|
||||||
expecteq "$(curl -s -X DELETE http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0)" ""
|
expecteq "$(curl -s -X DELETE http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0)" ""
|
||||||
|
|
||||||
new "Check deleted eth/0/0"
|
new "Check deleted eth/0/0"
|
||||||
expectfn 'curl -s -G http://localhost/restconf/data' $state
|
expectfn 'curl -s -G http://localhost/restconf/data' 0 $state
|
||||||
|
|
||||||
new2 "restconf Re-Delete eth/0/0 using none should generate error"
|
new2 "restconf Re-Delete eth/0/0 using none should generate error"
|
||||||
expecteq "$(curl -s -X DELETE http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0)" '{"ietf-restconf:errors" : {"error": {"error-tag": "data-missing","error-type": "application","error-severity": "error","error-message": "Data does not exist; cannot delete resource"}}}
'
|
expecteq "$(curl -s -X DELETE http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0)" '{"ietf-restconf:errors" : {"error": {"error-tag": "data-missing","error-type": "application","error-severity": "error","error-message": "Data does not exist; cannot delete resource"}}}
'
|
||||||
|
|
||||||
new "restconf Add subtree eth/0/0 using PUT"
|
new "restconf Add subtree eth/0/0 using PUT"
|
||||||
expecteq "$(curl -s -X PUT -d '{"interface":{"name":"eth/0/0","type":"eth","enabled":true}}' http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0)" ""
|
expecteq "$(curl -s -X PUT -d '{"interface":{"name":"eth/0/0","type":"ex:eth","enabled":true}}' http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0)" ""
|
||||||
|
|
||||||
new2 "restconf get subtree"
|
new2 "restconf get subtree"
|
||||||
expecteq "$(curl -s -G http://localhost/restconf/data)" '{"data": {"interfaces": {"interface": [{"name": "eth/0/0","type": "eth","enabled": true}]},"interfaces-state": {"interface": [{"name": "eth0","type": "eth","if-index": 42}]}}}
|
expecteq "$(curl -s -G http://localhost/restconf/data)" '{"data": {"interfaces": {"interface": [{"name": "eth/0/0","type": "ex:eth","enabled": true}]},"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}}
|
||||||
'
|
'
|
||||||
|
|
||||||
new2 "restconf rpc using POST json"
|
new2 "restconf rpc using POST json"
|
||||||
|
|
|
||||||
|
|
@ -66,22 +66,22 @@ sleep 1
|
||||||
new "restconf tests"
|
new "restconf tests"
|
||||||
|
|
||||||
new "restconf POST initial tree"
|
new "restconf POST initial tree"
|
||||||
expectfn 'curl -s -X POST -d {"cont1":{"interface":{"name":"local0","type":"regular"}}} http://localhost/restconf/data' ""
|
expectfn 'curl -s -X POST -d {"cont1":{"interface":{"name":"local0","type":"regular"}}} http://localhost/restconf/data' 0 ""
|
||||||
|
|
||||||
new "restconf GET datastore"
|
new "restconf GET datastore"
|
||||||
expectfn "curl -s -X GET http://localhost/restconf/data" '{"data": {"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}}'
|
expectfn "curl -s -X GET http://localhost/restconf/data" 0 '{"data": {"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}}'
|
||||||
|
|
||||||
new "restconf GET interface"
|
new "restconf GET interface"
|
||||||
expectfn "curl -s -X GET http://localhost/restconf/data/cont1/interface=local0" '{"interface": \[{"name": "local0","type": "regular"}\]}'
|
expectfn "curl -s -X GET http://localhost/restconf/data/cont1/interface=local0" 0 '{"interface": \[{"name": "local0","type": "regular"}\]}'
|
||||||
|
|
||||||
new "restconf GET if-type"
|
new "restconf GET if-type"
|
||||||
expectfn "curl -s -X GET http://localhost/restconf/data/cont1/interface=local0/type" '{"type": "regular"}'
|
expectfn "curl -s -X GET http://localhost/restconf/data/cont1/interface=local0/type" 0 '{"type": "regular"}'
|
||||||
|
|
||||||
new "restconf POST interface without mandatory type"
|
new "restconf POST interface without mandatory type"
|
||||||
expectfn 'curl -s -X POST -d {"interface":{"name":"TEST"}} http://localhost/restconf/data/cont1' '"error-message": "Missing mandatory variable: type"'
|
expectfn 'curl -s -X POST -d {"interface":{"name":"TEST"}} http://localhost/restconf/data/cont1' 0 '"error-message": "Missing mandatory variable: type"'
|
||||||
|
|
||||||
new "restconf POST interface"
|
new "restconf POST interface"
|
||||||
expectfn 'curl -s -X POST -d {"interface":{"name":"TEST","type":"eth0"}} http://localhost/restconf/data/cont1' ""
|
expectfn 'curl -s -X POST -d {"interface":{"name":"TEST","type":"eth0"}} http://localhost/restconf/data/cont1' 0 ""
|
||||||
|
|
||||||
new2 "restconf POST again"
|
new2 "restconf POST again"
|
||||||
expecteq "$(curl -s -X POST -d '{"interface":{"name":"TEST","type":"eth0"}}' http://localhost/restconf/data/cont1)" '{"ietf-restconf:errors" : {"error": {"error-tag": "data-exists","error-type": "application","error-severity": "error","error-message": "Data already exists; cannot create new resource"}}}
'
|
expecteq "$(curl -s -X POST -d '{"interface":{"name":"TEST","type":"eth0"}}' http://localhost/restconf/data/cont1)" '{"ietf-restconf:errors" : {"error": {"error-tag": "data-exists","error-type": "application","error-severity": "error","error-message": "Data already exists; cannot create new resource"}}}
'
|
||||||
|
|
@ -90,51 +90,50 @@ new2 "restconf POST from top"
|
||||||
expecteq "$(curl -s -X POST -d '{"cont1":{"interface":{"name":"TEST","type":"eth0"}}}' http://localhost/restconf/data)" '{"ietf-restconf:errors" : {"error": {"error-tag": "data-exists","error-type": "application","error-severity": "error","error-message": "Data already exists; cannot create new resource"}}}
'
|
expecteq "$(curl -s -X POST -d '{"cont1":{"interface":{"name":"TEST","type":"eth0"}}}' http://localhost/restconf/data)" '{"ietf-restconf:errors" : {"error": {"error-tag": "data-exists","error-type": "application","error-severity": "error","error-message": "Data already exists; cannot create new resource"}}}
'
|
||||||
|
|
||||||
new "restconf DELETE"
|
new "restconf DELETE"
|
||||||
expectfn 'curl -s -X DELETE http://localhost/restconf/data/cont1' ""
|
expectfn 'curl -s -X DELETE http://localhost/restconf/data/cont1' 0 ""
|
||||||
|
|
||||||
new "restconf GET null datastore"
|
new "restconf GET null datastore"
|
||||||
expectfn "curl -s -X GET http://localhost/restconf/data" '{"data": null}'
|
expectfn "curl -s -X GET http://localhost/restconf/data" 0 '{"data": null}'
|
||||||
|
|
||||||
new "restconf POST initial tree"
|
new "restconf POST initial tree"
|
||||||
expectfn 'curl -s -X POST -d {"cont1":{"interface":{"name":"local0","type":"regular"}}} http://localhost/restconf/data' ""
|
expectfn 'curl -s -X POST -d {"cont1":{"interface":{"name":"local0","type":"regular"}}} http://localhost/restconf/data' 0 ""
|
||||||
|
|
||||||
new "restconf GET initial tree"
|
new "restconf GET initial tree"
|
||||||
expectfn "curl -s -X GET http://localhost/restconf/data" '{"data": {"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}}'
|
expectfn "curl -s -X GET http://localhost/restconf/data" 0 '{"data": {"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}}'
|
||||||
|
|
||||||
new "restconf DELETE whole datastore"
|
new "restconf DELETE whole datastore"
|
||||||
expectfn 'curl -s -X DELETE http://localhost/restconf/data' ""
|
expectfn 'curl -s -X DELETE http://localhost/restconf/data' 0 ""
|
||||||
|
|
||||||
new "restconf GET null datastore"
|
new "restconf GET null datastore"
|
||||||
expectfn "curl -s -X GET http://localhost/restconf/data" '{"data": null}'
|
expectfn "curl -s -X GET http://localhost/restconf/data" 0 '{"data": null}'
|
||||||
|
|
||||||
new "restconf PUT initial datastore"
|
new "restconf PUT initial datastore"
|
||||||
expectfn 'curl -s -X PUT -d {"data":{"cont1":{"interface":{"name":"local0","type":"regular"}}}} http://localhost/restconf/data' ""
|
expectfn 'curl -s -X PUT -d {"data":{"cont1":{"interface":{"name":"local0","type":"regular"}}}} http://localhost/restconf/data' 0 ""
|
||||||
|
|
||||||
new "restconf GET datastore"
|
new "restconf GET datastore"
|
||||||
expectfn "curl -s -X GET http://localhost/restconf/data" '{"data": {"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}}'
|
expectfn "curl -s -X GET http://localhost/restconf/data" 0 '{"data": {"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}}'
|
||||||
|
|
||||||
new "restconf PUT replace datastore"
|
new "restconf PUT replace datastore"
|
||||||
expectfn 'curl -s -X PUT -d {"data":{"cont2":{"name":"foo"}}} http://localhost/restconf/data' ""
|
expectfn 'curl -s -X PUT -d {"data":{"cont2":{"name":"foo"}}} http://localhost/restconf/data' 0 ""
|
||||||
|
|
||||||
new "restconf GET replaced datastore"
|
new "restconf GET replaced datastore"
|
||||||
expectfn "curl -s -X GET http://localhost/restconf/data" '{"data": {"cont2": {"name": "foo"}}}'
|
expectfn "curl -s -X GET http://localhost/restconf/data" 0 '{"data": {"cont2": {"name": "foo"}}}'
|
||||||
|
|
||||||
|
|
||||||
new "restconf PUT initial datastore again"
|
new "restconf PUT initial datastore again"
|
||||||
expectfn 'curl -s -X PUT -d {"data":{"cont1":{"interface":{"name":"local0","type":"regular"}}}} http://localhost/restconf/data' ""
|
expectfn 'curl -s -X PUT -d {"data":{"cont1":{"interface":{"name":"local0","type":"regular"}}}} http://localhost/restconf/data' 0 ""
|
||||||
|
|
||||||
new "restconf PUT change interface"
|
new "restconf PUT change interface"
|
||||||
expectfn 'curl -s -X PUT -d {"interface":{"name":"local0","type":"atm0"}} http://localhost/restconf/data/cont1/interface=local0' ""
|
expectfn 'curl -s -X PUT -d {"interface":{"name":"local0","type":"atm0"}} http://localhost/restconf/data/cont1/interface=local0' 0 ""
|
||||||
|
|
||||||
|
|
||||||
new "restconf GET datastore atm"
|
new "restconf GET datastore atm"
|
||||||
expectfn "curl -s -X GET http://localhost/restconf/data" '{"data": {"cont1": {"interface": \[{"name": "local0","type": "atm0"}\]}}}'
|
expectfn "curl -s -X GET http://localhost/restconf/data" 0 '{"data": {"cont1": {"interface": \[{"name": "local0","type": "atm0"}\]}}}'
|
||||||
|
|
||||||
new "restconf PUT add interface"
|
new "restconf PUT add interface"
|
||||||
expectfn 'curl -s -X PUT -d {"interface":{"name":"TEST","type":"eth0"}} http://localhost/restconf/data/cont1/interface=TEST' ""
|
expectfn 'curl -s -X PUT -d {"interface":{"name":"TEST","type":"eth0"}} http://localhost/restconf/data/cont1/interface=TEST' 0 ""
|
||||||
|
|
||||||
new "restconf PUT change key error"
|
new "restconf PUT change key error"
|
||||||
expectfn 'curl -is -X PUT -d {"interface":{"name":"ALPHA","type":"eth0"}} http://localhost/restconf/data/cont1/interface=TEST' '{"ietf-restconf:errors" : {"error": {"rpc-error": {"error-tag": "operation-failed","error-type": "protocol","error-severity": "error","error-message": "api-path keys do not match data keys"}}}}'
|
expectfn 'curl -is -X PUT -d {"interface":{"name":"ALPHA","type":"eth0"}} http://localhost/restconf/data/cont1/interface=TEST' 0 '{"ietf-restconf:errors" : {"error": {"rpc-error": {"error-tag": "operation-failed","error-type": "protocol","error-severity": "error","error-message": "api-path keys do not match data keys"}}}}'
|
||||||
|
|
||||||
new "Kill restconf daemon"
|
new "Kill restconf daemon"
|
||||||
sudo pkill -u www-data clixon_restconf
|
sudo pkill -u www-data clixon_restconf
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ run(){
|
||||||
<interfaces>
|
<interfaces>
|
||||||
<interface>
|
<interface>
|
||||||
<name>run</name>
|
<name>run</name>
|
||||||
<type>eth</type>
|
<type>ex:eth</type>
|
||||||
</interface>
|
</interface>
|
||||||
</interfaces>
|
</interfaces>
|
||||||
</config>
|
</config>
|
||||||
|
|
@ -55,7 +55,7 @@ EOF
|
||||||
<interfaces>
|
<interfaces>
|
||||||
<interface>
|
<interface>
|
||||||
<name>startup</name>
|
<name>startup</name>
|
||||||
<type>eth</type>
|
<type>ex:eth</type>
|
||||||
</interface>
|
</interface>
|
||||||
</interfaces>
|
</interfaces>
|
||||||
</config>
|
</config>
|
||||||
|
|
@ -67,7 +67,7 @@ EOF
|
||||||
<interfaces>
|
<interfaces>
|
||||||
<interface>
|
<interface>
|
||||||
<name>extra</name>
|
<name>extra</name>
|
||||||
<type>eth</type>
|
<type>ex:eth</type>
|
||||||
</interface>
|
</interface>
|
||||||
</interfaces>
|
</interfaces>
|
||||||
</config>
|
</config>
|
||||||
|
|
@ -103,8 +103,8 @@ EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
run init '<data/>'
|
run init '<data/>'
|
||||||
run none '<data><interfaces><interface><name>run</name><type>eth</type><enabled>true</enabled></interface></interfaces></data>'
|
run none '<data><interfaces><interface><name>run</name><type>ex:eth</type><enabled>true</enabled></interface></interfaces></data>'
|
||||||
run running '<data><interfaces><interface><name>extra</name><type>eth</type><enabled>true</enabled></interface><interface><name>lo</name><type>local</type><enabled>true</enabled></interface><interface><name>run</name><type>eth</type><enabled>true</enabled></interface></interfaces></data>'
|
run running '<data><interfaces><interface><name>extra</name><type>ex:eth</type><enabled>true</enabled></interface><interface><name>lo</name><type>ex:loopback</type><enabled>true</enabled></interface><interface><name>run</name><type>ex:eth</type><enabled>true</enabled></interface></interfaces></data>'
|
||||||
run startup '<data><interfaces><interface><name>extra</name><type>eth</type><enabled>true</enabled></interface><interface><name>lo</name><type>local</type><enabled>true</enabled></interface><interface><name>startup</name><type>eth</type><enabled>true</enabled></interface></interfaces></data>'
|
run startup '<data><interfaces><interface><name>extra</name><type>ex:eth</type><enabled>true</enabled></interface><interface><name>lo</name><type>ex:loopback</type><enabled>true</enabled></interface><interface><name>startup</name><type>ex:eth</type><enabled>true</enabled></interface></interfaces></data>'
|
||||||
|
|
||||||
rm -rf $dir
|
rm -rf $dir
|
||||||
|
|
|
||||||
|
|
@ -139,25 +139,25 @@ if [ $? -ne 0 ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "cli set ab"
|
new "cli set ab"
|
||||||
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set list a.b.a.b" "^$"
|
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set list a.b.a.b" 0 "^$"
|
||||||
|
|
||||||
new "cli set cd"
|
new "cli set cd"
|
||||||
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set list c.d.c.d" "^$"
|
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set list c.d.c.d" 0 "^$"
|
||||||
|
|
||||||
new "cli set ef"
|
new "cli set ef"
|
||||||
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set list e.f.e.f" "^$"
|
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set list e.f.e.f" 0 "^$"
|
||||||
|
|
||||||
new "cli set ab fail"
|
new "cli set ab fail"
|
||||||
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set list a&b&a&b" "^CLI syntax error"
|
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set list a&b&a&b" 255 "^CLI syntax error"
|
||||||
|
|
||||||
new "cli set ad fail"
|
new "cli set ad fail"
|
||||||
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set list a.b.c.d" "^CLI syntax error"
|
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set list a.b.c.d" 255 "^CLI syntax error"
|
||||||
|
|
||||||
new "cli validate"
|
new "cli validate"
|
||||||
expectfn "$clixon_cli -1f $cfg -l o -y $fyang -l o validate" "^$"
|
expectfn "$clixon_cli -1f $cfg -l o -y $fyang -l o validate" 0 "^$"
|
||||||
|
|
||||||
new "cli commit"
|
new "cli commit"
|
||||||
expectfn "$clixon_cli -1f $cfg -l o -y $fyang -l o commit" "^$"
|
expectfn "$clixon_cli -1f $cfg -l o -y $fyang -l o commit" 0 "^$"
|
||||||
|
|
||||||
new "netconf validate ok"
|
new "netconf validate ok"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
@ -175,7 +175,7 @@ new "netconf commit"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><commit/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "cli enum value"
|
new "cli enum value"
|
||||||
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set status down" "^$"
|
expectfn "$clixon_cli -1f $cfg -l o -y $fyang set status down" 0 "^$"
|
||||||
|
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
# Check if still alive
|
# Check if still alive
|
||||||
|
|
|
||||||
|
|
@ -111,11 +111,11 @@ if [ $? -ne 0 ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "cli defined extension"
|
new "cli defined extension"
|
||||||
expectfn "$clixon_cli -1f $cfg -y $fyang show version" "3."
|
expectfn "$clixon_cli -1f $cfg -y $fyang show version" 0 "3."
|
||||||
|
|
||||||
new "cli not defined extension"
|
new "cli not defined extension"
|
||||||
# This text yields an error, but the test cannot detect the error message yet
|
# This text yields an error, but the test cannot detect the error message yet
|
||||||
#expectfn "$clixon_cli -1f $cfg -y $fyangerr show version" "Yang error: Extension ex:not-defined not found"
|
#expectfn "$clixon_cli -1f $cfg -y $fyangerr show version" 0 "Yang error: Extension ex:not-defined not found"
|
||||||
|
|
||||||
new "netconf edit config"
|
new "netconf edit config"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><y><a>1</a><b>2</b><c>5</c><val>one</val></y><d/></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><x><y><a>1</a><b>2</b><c>5</c><val>one</val></y><d/></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
@ -143,10 +143,10 @@ new "netconf get (should be some)"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get><filter type=\"xpath\" select=\"/\"/></get></rpc>]]>]]>" "^<rpc-reply><data><x><y><a>1</a><b>2</b><c>5</c><val>one</val></y><d/></x></data></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><get><filter type=\"xpath\" select=\"/\"/></get></rpc>]]>]]>" "^<rpc-reply><data><x><y><a>1</a><b>2</b><c>5</c><val>one</val></y><d/></x></data></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "cli set leaf-list"
|
new "cli set leaf-list"
|
||||||
expectfn "$clixon_cli -1f $cfg -y $fyang set x f e foo" ""
|
expectfn "$clixon_cli -1f $cfg -y $fyang set x f e foo" 0 ""
|
||||||
|
|
||||||
new "cli show leaf-list"
|
new "cli show leaf-list"
|
||||||
expectfn "$clixon_cli -1f $cfg -y $fyang show xpath /x/f/e" "<e>foo</e>"
|
expectfn "$clixon_cli -1f $cfg -y $fyang show xpath /x/f/e" 0 "<e>foo</e>"
|
||||||
new "netconf set state data (not allowed)"
|
new "netconf set state data (not allowed)"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><state><op>42</op></state></config></edit-config></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>invalid-value"
|
expecteof "$clixon_netconf -qf $cfg -y $fyang" "<rpc><edit-config><target><candidate/></target><config><state><op>42</op></state></config></edit-config></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>invalid-value"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue