diff --git a/CHANGELOG.md b/CHANGELOG.md index 626022fe..aec816b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,23 @@ ## 3.6.0 (Upcoming) +### Major changes: +### Minor changes: + +* Use instead of when save/load configuration to file. This +enables saved files to be used as datastore without any editing. Thanks Matt. + +* Added Yang "extension" statement. This includes parsing unknown + statements and identifying them as extensions or not. However, + semantics for specific extensions must still be added. + +* Renamed ytype_id and ytype_prefix to yarg_id and yarg_prefix, respectively + +* Added cli_show_version() + +### Corrected Bugs + + ## 3.5.0 (12 February 2018) ### Major changes: diff --git a/apps/cli/cli_show.c b/apps/cli/cli_show.c index 85645413..13f58339 100644 --- a/apps/cli/cli_show.c +++ b/apps/cli/cli_show.c @@ -587,7 +587,14 @@ done: xml_free(xt); return retval; } + int show_confv_xpath(clicon_handle h, cvec *vars, cvec *argv) { return show_conf_xpath(h, vars, argv); } + +int cli_show_version(clicon_handle h, cvec *vars, cvec *argv) +{ + cli_output(stdout, "%s\n", CLIXON_VERSION_STRING); + return 0; +} diff --git a/example/example.yang b/example/example.yang index 3c6a6f3a..f3c39917 100644 --- a/example/example.yang +++ b/example/example.yang @@ -1,10 +1,14 @@ module example { + prefix ex; import ietf-ip { - prefix ip; + prefix ip; } import ietf-routing { - prefix rt; + prefix rt; + } + import ietf-netconf-acm { + prefix nacm; /* See RFC 6536 */ } description - "Example code that includes ietf-ip and ietf-routing"; + "Example code that includes ietf-ip and ietf-routing"; } diff --git a/example/routing_cli.c b/example/routing_cli.c index b054d943..bdb621b7 100644 --- a/example/routing_cli.c +++ b/example/routing_cli.c @@ -81,7 +81,7 @@ mycallback(clicon_handle h, cvec *cvv, cvec *argv) /* Show eth0 interfaces config using XPATH */ if (clicon_rpc_get_config(h, "running","/interfaces/interface[name=eth0]", - &xret) < 0) + NULL, &xret) < 0) goto done; xml_print(stdout, xret); diff --git a/example/routing_cli.cli b/example/routing_cli.cli index 3c8a6a2d..63a285eb 100644 --- a/example/routing_cli.cli +++ b/example/routing_cli.cli @@ -30,6 +30,7 @@ compare("Compare running and candidate"), compare_dbs((int32)1); show("Show a particular state of the system"){ xpath("Show configuration") ("XPATH expression"), show_conf_xpath("candidate"); + version("Show version"), cli_show_version("candidate", "text", "/"); compare("Compare candidate and running databases"), compare_dbs((int32)0);{ xml("Show comparison in xml"), compare_dbs((int32)0); text("Show comparison in text"), compare_dbs((int32)1); diff --git a/lib/clixon/clixon_yang.h b/lib/clixon/clixon_yang.h index 084fe3c5..c89a8f80 100644 --- a/lib/clixon/clixon_yang.h +++ b/lib/clixon/clixon_yang.h @@ -114,6 +114,7 @@ enum rfc_6020{ Y_TYPEDEF, Y_UNIQUE, Y_UNITS, + Y_UNKNOWN, Y_USES, Y_VALUE, Y_WHEN, @@ -161,7 +162,9 @@ struct yang_stmt{ leaf-list, config: boolean true or false mandatory: boolean true or false - fraction-digits for fraction-digits */ + fraction-digits for fraction-digits + unkown-stmt (argument) + */ cvec *ys_cvec; /* List of stmt-specific variables Y_RANGE: range_min, range_max Y_LIST: vector of keys @@ -206,8 +209,8 @@ yang_stmt *ys_dup(yang_stmt *old); int yn_insert(yang_node *yn_parent, yang_stmt *ys_child); yang_stmt *yn_each(yang_node *yn, yang_stmt *ys); char *yang_key2str(int keyword); -char *ytype_prefix(yang_stmt *ys); -char *ytype_id(yang_stmt *ys); +char *yarg_prefix(yang_stmt *ys); +char *yarg_id(yang_stmt *ys); yang_stmt *ys_module(yang_stmt *ys); yang_spec *ys_spec(yang_stmt *ys); yang_stmt *yang_find_module_by_prefix(yang_stmt *ys, char *prefix); @@ -227,7 +230,7 @@ int yang_abs_schema_nodeid(yang_spec *yspec, char *schema_nodeid, int yang_desc_schema_nodeid(yang_node *yn, char *schema_nodeid, yang_stmt **yres); cg_var *ys_parse(yang_stmt *ys, enum cv_type cvtype); -int ys_parse_sub(yang_stmt *ys); +int ys_parse_sub(yang_stmt *ys, char *extra); int yang_mandatory(yang_stmt *ys); int yang_config(yang_stmt *ys); yang_spec *yang_spec_netconf(clicon_handle h); diff --git a/lib/clixon/clixon_yang_type.h b/lib/clixon/clixon_yang_type.h index 291766cf..61b581af 100644 --- a/lib/clixon/clixon_yang_type.h +++ b/lib/clixon/clixon_yang_type.h @@ -68,7 +68,6 @@ char *cv2yang_type(enum cv_type cv_type); yang_stmt *yang_find_identity(yang_stmt *ys, char *identity); int ys_cv_validate(cg_var *cv, yang_stmt *ys, char **reason); int clicon_type2cv(char *type, char *rtype, enum cv_type *cvtype); -char *ytype_id(yang_stmt *ys); int yang_type_get(yang_stmt *ys, char **otype, yang_stmt **restype, int *options, cg_var **mincv, cg_var **maxcv, char **pattern, uint8_t *fraction_digits); diff --git a/lib/src/clixon_yang.c b/lib/src/clixon_yang.c index 1014b0f0..ba3758b7 100644 --- a/lib/src/clixon_yang.c +++ b/lib/src/clixon_yang.c @@ -133,7 +133,8 @@ static const map_str2int ykmap[] = { {"type", Y_TYPE}, {"typedef", Y_TYPEDEF}, {"unique", Y_UNIQUE}, - {"units", Y_UNITS}, + {"units", Y_UNITS}, + {"unknown", Y_UNKNOWN}, {"uses", Y_USES}, {"value", Y_VALUE}, {"when", Y_WHEN}, @@ -668,13 +669,15 @@ ys_spec(yang_stmt *ys) return (yang_spec*)ys; } -/* Extract id from type argument. two cases: - * argument is prefix:id, - * argument is id, +/* Assume argument is id on the type: <[prefix:]id>, return 'id' * Just return string from id + * @param[in] ys A yang statement + * @retval NULL No id (argument is NULL) + * @retval id Pointer to identifier + * @see yarg_prefix */ char* -ytype_id(yang_stmt *ys) +yarg_id(yang_stmt *ys) { char *id; @@ -685,13 +688,14 @@ ytype_id(yang_stmt *ys) return id; } -/* Extract prefix from type argument. two cases: - * argument is prefix:id, - * argument is id, - * return either NULL or a new prefix string that needs to be freed by caller. +/* Assume argument is id on the type: <[prefix:]id>, return 'prefix' + * @param[in] ys A yang statement + * @retval NULL No prefix + * @retval prefix Malloced string that needs to be freed by caller. + * @see yarg_id */ char* -ytype_prefix(yang_stmt *ys) +yarg_prefix(yang_stmt *ys) { char *id; char *prefix = NULL; @@ -822,7 +826,11 @@ yang_print_cbuf(cbuf *cb, yang_stmt *ys = NULL; while ((ys = yn_each(yn, ys)) != NULL) { - cprintf(cb, "%*s%s", marginal, "", yang_key2str(ys->ys_keyword)); + if (ys->ys_keyword == Y_UNKNOWN){ /* dont print unknown - proxy for extension*/ + cprintf(cb, "%*s", marginal-1, ""); + } + else + cprintf(cb, "%*s%s", marginal, "", yang_key2str(ys->ys_keyword)); if (ys->ys_argument){ if (quotedstring(ys->ys_argument)) cprintf(cb, " \"%s\"", ys->ys_argument); @@ -974,7 +982,7 @@ ys_populate_range(yang_stmt *ys, &options, NULL, NULL, NULL, &fraction_digits) < 0) goto done; restype = yrestype?yrestype->ys_argument:NULL; - origtype = ytype_id((yang_stmt*)yparent); + origtype = yarg_id((yang_stmt*)yparent); /* This handles non-resolved also */ if (clicon_type2cv(origtype, restype, &cvtype) < 0) goto done; @@ -1291,8 +1299,8 @@ yang_expand(yang_node *yn) switch(ys->ys_keyword){ case Y_USES: /* Split argument into prefix and name */ - name = ytype_id(ys); /* This is uses/grouping name to resolve */ - prefix = ytype_prefix(ys); /* And this its prefix */ + name = yarg_id(ys); /* This is uses/grouping name to resolve */ + prefix = yarg_prefix(ys); /* And this its prefix */ if (ys_grouping_resolve(ys, prefix, name, &ygrouping) < 0) goto done; if (prefix) @@ -2016,6 +2024,8 @@ ys_parse(yang_stmt *ys, * Specific syntax checks and variable creation for stand-alone yang statements. * That is, siblings, etc, may not be there. Complete checks are made in * ys_populate instead. + * @param[in] ys yang statement + * @param[in] extra Yang extra for cornercases (unknown/extension) * * The cv:s created in parse-tree as follows: * fraction-digits : Create cv as uint8, check limits [1:8] (must be made in 1st pass) @@ -2023,13 +2033,19 @@ ys_parse(yang_stmt *ys, * @see ys_populate */ int -ys_parse_sub(yang_stmt *ys) +ys_parse_sub(yang_stmt *ys, + char *extra) { int retval = -1; - + int cvret; + char *reason = NULL; + yang_stmt *ymod; + uint8_t fd; + char *prefix = NULL; + char *name; + switch (ys->ys_keyword){ - case Y_FRACTION_DIGITS:{ - uint8_t fd; + case Y_FRACTION_DIGITS: if (ys_parse(ys, CGV_UINT8) == NULL) goto done; fd = cv_uint8_get(ys->ys_cv); @@ -2038,12 +2054,41 @@ ys_parse_sub(yang_stmt *ys) goto done; } break; - } + case Y_UNKNOWN: + if (extra == NULL) + break; + /* Find extension, if found, store it as unknown, if not, + break for error */ + prefix = yarg_prefix(ys); /* And this its prefix */ + name = yarg_id(ys); /* This is the type to resolve */ + if ((ymod = yang_find_module_by_prefix(ys, prefix)) == NULL) + goto ok; /* shouldnt happen */ + if (yang_find((yang_node*)ymod, Y_EXTENSION, name) == NULL){ + clicon_err(OE_YANG, errno, "Extension %s:%s not found", prefix, name); + goto done; + } + if ((ys->ys_cv = cv_new(CGV_STRING)) == NULL){ + clicon_err(OE_YANG, errno, "%s: cv_new", __FUNCTION__); + goto done; + } + if ((cvret = cv_parse1(extra, ys->ys_cv, &reason)) < 0){ /* error */ + clicon_err(OE_YANG, errno, "parsing cv"); + goto done; + } + if (cvret == 0){ /* parsing failed */ + clicon_err(OE_YANG, errno, "Parsing CV: %s", reason); + goto done; + } + free(extra); + break; default: break; } + ok: retval = 0; done: + if (prefix) + free(prefix); return retval; } diff --git a/lib/src/clixon_yang_parse.l b/lib/src/clixon_yang_parse.l index eb235115..8c80af65 100644 --- a/lib/src/clixon_yang_parse.l +++ b/lib/src/clixon_yang_parse.l @@ -101,12 +101,13 @@ clixon_yang_parsewrap(void) %s ESCAPE %s COMMENT1 %s COMMENT2 +%s UNKNOWN %% /* Common tokens */ [ \t] -<> { return MY_EOF; } -\n { _YY->yy_linenum++; } +<> { return MY_EOF; } +\n { _YY->yy_linenum++; } "/*" { _YY->yy_lex_state = YYSTATE; BEGIN(COMMENT1); } "//" { _YY->yy_lex_state = YYSTATE; BEGIN(COMMENT2); } @@ -182,7 +183,14 @@ clixon_yang_parsewrap(void) : { return *yytext; } ; { return *yytext; } . { clixon_yang_parselval.string = strdup(yytext); - return CHAR;} + BEGIN(UNKNOWN); return CHAR; } + +: { return *yytext; } +; { BEGIN(KEYWORD); return *yytext; } +[ \t] { return ' '; } +. { clixon_yang_parselval.string = strdup(yytext); + return CHAR; } + ; { BEGIN(KEYWORD); return *yytext; } diff --git a/lib/src/clixon_yang_parse.y b/lib/src/clixon_yang_parse.y index 68748c8a..b27f63ea 100644 --- a/lib/src/clixon_yang_parse.y +++ b/lib/src/clixon_yang_parse.y @@ -46,7 +46,6 @@ %token MY_EOF %token DQ /* Double quote: " */ -%token K_UNKNOWN /* template for error */ %token CHAR %type ustring @@ -239,12 +238,18 @@ ystack_push(struct clicon_yang_yacc_arg *yy, /*! Add a yang statement to existing top-of-stack. * - * Note: consumes 'argument' which assumes it is malloced and not freed by caller + * @param[in] yy Yang yacc argument + * @param[in] keyword Yang keyword + * @param[in] argument Yang argument + * @param[in] extra Yang extra for cornercases (unknown/extension) + + * @note consumes 'argument' and 'extra' which assumes it is malloced and not freed by caller */ static yang_stmt * ysp_add(struct clicon_yang_yacc_arg *yy, enum rfc_6020 keyword, - char *argument) + char *argument, + char *extra) { struct ys_stack *ystack = yy->yy_stack; yang_stmt *ys = NULL; @@ -262,7 +267,7 @@ ysp_add(struct clicon_yang_yacc_arg *yy, ys->ys_argument = argument; if (yn_insert(yn, ys) < 0) /* Insert into hierarchy */ goto err; - if (ys_parse_sub(ys) < 0) /* Check statement-specific syntax */ + if (ys_parse_sub(ys, extra) < 0) /* Check statement-specific syntax */ goto err2; /* dont free since part of tree */ // done: return ys; @@ -276,12 +281,12 @@ ysp_add(struct clicon_yang_yacc_arg *yy, /*! combination of ysp_add and ysp_push for sub-modules */ static yang_stmt * ysp_add_push(struct clicon_yang_yacc_arg *yy, - int keyword, + enum rfc_6020 keyword, char *argument) { yang_stmt *ys; - if ((ys = ysp_add(yy, keyword, argument)) == NULL) + if ((ys = ysp_add(yy, keyword, argument, NULL)) == NULL) return NULL; if (ystack_push(yy, (yang_node*)ys) == NULL) return NULL; @@ -330,12 +335,22 @@ file : module_stmt MY_EOF { clicon_debug(2,"file->submodule-stmt"); YYACCEPT; } ; -unknown_stmt : K_UNKNOWN { clixon_yang_parseerror(_yy, "unknown statement");clicon_debug(2,"unknown-stmt"); _YYERROR("0"); } - ; + /* For extensions */ +unknown_stmt : ustring ':' ustring ';' + { char *id; if ((id=prefix_id_join($1, $3)) == NULL) _YYERROR("0"); + if (ysp_add(_yy, Y_UNKNOWN, id, NULL) == NULL) _YYERROR("0"); + clicon_debug(2,"unknown-stmt -> ustring : ustring"); + } + | ustring ':' ustring ' ' string ';' + { char *id; if ((id=prefix_id_join($1, $3)) == NULL) _YYERROR("0"); + if (ysp_add(_yy, Y_UNKNOWN, id, $5) == NULL) _YYERROR("0"); + clicon_debug(2,"unknown-stmt -> ustring : ustring string"); + } + ; /* module */ module_stmt : K_MODULE id_arg_str - { if ((_YY->yy_module = ysp_add_push(_yy, Y_MODULE, $2)) == NULL) _YYERROR("1"); + { if ((_YY->yy_module = ysp_add_push(_yy, Y_MODULE, $2)) == NULL) _YYERROR("1"); } '{' module_substmts '}' { if (ystack_pop(_yy) < 0) _YYERROR("2"); @@ -359,7 +374,7 @@ module_substmt : module_header_stmts { clicon_debug(2,"module-substmt -> module- /* submodule */ submodule_stmt : K_SUBMODULE id_arg_str '{' submodule_substmts '}' - { if ((_YY->yy_module = ysp_add_push(_yy, Y_SUBMODULE, $2)) == NULL) _YYERROR("3"); + { if ((_YY->yy_module = ysp_add_push(_yy, Y_SUBMODULE, $2)) == NULL) _YYERROR("3"); clicon_debug(2,"submodule -> id-arg-str { submodule-stmts }"); } ; @@ -422,7 +437,7 @@ revision_stmts : revision_stmts revision_stmt ; revision_stmt : K_REVISION string ';' /* XXX date-arg-str */ - { if (ysp_add(_yy, Y_REVISION, $2) == NULL) _YYERROR("4"); + { if (ysp_add(_yy, Y_REVISION, $2, NULL) == NULL) _YYERROR("4"); clicon_debug(2,"revision-stmt -> date-arg-str ;"); } | K_REVISION string { if (ysp_add_push(_yy, Y_REVISION, $2) == NULL) _YYERROR("5"); } @@ -482,7 +497,7 @@ data_def_stmt : container_stmt { clicon_debug(2,"data-def-stmt -> containe /* container */ container_stmt : K_CONTAINER id_arg_str ';' - { if (ysp_add(_yy, Y_CONTAINER, $2) == NULL) _YYERROR("7"); + { if (ysp_add(_yy, Y_CONTAINER, $2, NULL) == NULL) _YYERROR("7"); clicon_debug(2,"container-stmt -> CONTAINER id-arg-str ;");} | K_CONTAINER id_arg_str { if (ysp_add_push(_yy, Y_CONTAINER, $2) == NULL) _YYERROR("8"); } @@ -512,7 +527,7 @@ container_substmt : when_stmt { clicon_debug(2,"container-substmt -> when- /* leaf */ leaf_stmt : K_LEAF id_arg_str ';' - { if (ysp_add(_yy, Y_LEAF, $2) == NULL) _YYERROR("10"); + { if (ysp_add(_yy, Y_LEAF, $2, NULL) == NULL) _YYERROR("10"); clicon_debug(2,"leaf-stmt -> LEAF id-arg-str ;");} | K_LEAF id_arg_str { if (ysp_add_push(_yy, Y_LEAF, $2) == NULL) _YYERROR("11"); } @@ -542,7 +557,7 @@ leaf_substmt : when_stmt { clicon_debug(2,"leaf-substmt -> when-stmt /* leaf-list */ leaf_list_stmt : K_LEAF_LIST id_arg_str ';' - { if (ysp_add(_yy, Y_LEAF_LIST, $2) == NULL) _YYERROR("13"); + { if (ysp_add(_yy, Y_LEAF_LIST, $2, NULL) == NULL) _YYERROR("13"); clicon_debug(2,"leaf-list-stmt -> LEAF id-arg-str ;");} | K_LEAF_LIST id_arg_str { if (ysp_add_push(_yy, Y_LEAF_LIST, $2) == NULL) _YYERROR("14"); } @@ -573,7 +588,7 @@ leaf_list_substmt : when_stmt { clicon_debug(2,"leaf-list-substmt -> when /* list */ list_stmt : K_LIST id_arg_str ';' - { if (ysp_add(_yy, Y_LIST, $2) == NULL) _YYERROR("16"); + { if (ysp_add(_yy, Y_LIST, $2, NULL) == NULL) _YYERROR("16"); clicon_debug(2,"list-stmt -> LIST id-arg-str ;"); } | K_LIST id_arg_str { if (ysp_add_push(_yy, Y_LIST, $2) == NULL) _YYERROR("17"); } @@ -609,7 +624,7 @@ list_substmt : when_stmt { clicon_debug(2,"list-substmt -> when-stmt /* choice */ choice_stmt : K_CHOICE id_arg_str ';' - { if (ysp_add(_yy, Y_CHOICE, $2) == NULL) _YYERROR("19"); + { if (ysp_add(_yy, Y_CHOICE, $2, NULL) == NULL) _YYERROR("19"); clicon_debug(2,"choice-stmt -> CHOICE id-arg-str ;"); } | K_CHOICE id_arg_str { if (ysp_add_push(_yy, Y_CHOICE, $2) == NULL) _YYERROR("20"); } @@ -648,7 +663,7 @@ short_case_stmt : container_stmt { clicon_debug(2,"short-case-substmt -> conta /* case */ case_stmt : K_CASE id_arg_str ';' - { if (ysp_add(_yy, Y_CASE, $2) == NULL) _YYERROR("22"); + { if (ysp_add(_yy, Y_CASE, $2, NULL) == NULL) _YYERROR("22"); clicon_debug(2,"case-stmt -> CASE id-arg-str ;"); } | K_CASE id_arg_str { if (ysp_add_push(_yy, Y_CASE, $2) == NULL) _YYERROR("23"); } @@ -676,7 +691,7 @@ case_substmt : when_stmt { clicon_debug(2,"case-substmt -> when-stmt /* anyxml */ anyxml_stmt : K_ANYXML id_arg_str ';' - { if (ysp_add(_yy, Y_ANYXML, $2) == NULL) _YYERROR("25"); + { if (ysp_add(_yy, Y_ANYXML, $2, NULL) == NULL) _YYERROR("25"); clicon_debug(2,"anyxml-stmt -> ANYXML id-arg-str ;"); } | K_ANYXML id_arg_str { if (ysp_add_push(_yy, Y_ANYXML, $2) == NULL) _YYERROR("26"); } @@ -704,7 +719,7 @@ anyxml_substmt : when_stmt { clicon_debug(2,"anyxml-substmt -> when-st /* uses */ uses_stmt : K_USES identifier_ref_arg_str ';' - { if (ysp_add(_yy, Y_USES, $2) == NULL) _YYERROR("28"); + { if (ysp_add(_yy, Y_USES, $2, NULL) == NULL) _YYERROR("28"); clicon_debug(2,"uses-stmt -> USES id-arg-str ;"); } | K_USES identifier_ref_arg_str { if (ysp_add_push(_yy, Y_USES, $2) == NULL) _YYERROR("29"); } @@ -732,7 +747,7 @@ uses_substmt : when_stmt { clicon_debug(2,"uses-substmt -> when-stmt /* refine XXX need further refining */ refine_stmt : K_REFINE id_arg_str ';' - { if (ysp_add(_yy, Y_REFINE, $2) == NULL) _YYERROR("31"); + { if (ysp_add(_yy, Y_REFINE, $2, NULL) == NULL) _YYERROR("31"); clicon_debug(2,"refine-stmt -> REFINE id-arg-str ;"); } | K_REFINE id_arg_str { if (ysp_add_push(_yy, Y_REFINE, $2) == NULL) _YYERROR("32"); } @@ -782,7 +797,7 @@ augment_substmt : when_stmt { clicon_debug(2,"augment-substmt -> when-s /* when */ when_stmt : K_WHEN string ';' - { if (ysp_add(_yy, Y_WHEN, $2) == NULL) _YYERROR("36"); + { if (ysp_add(_yy, Y_WHEN, $2, NULL) == NULL) _YYERROR("36"); clicon_debug(2,"when-stmt -> WHEN string ;"); } | K_WHEN string { if (ysp_add_push(_yy, Y_WHEN, $2) == NULL) _YYERROR("37"); } @@ -804,7 +819,7 @@ when_substmt : description_stmt { clicon_debug(2,"when-substmt -> description-s /* rpc */ rpc_stmt : K_RPC id_arg_str ';' - { if (ysp_add(_yy, Y_RPC, $2) == NULL) _YYERROR("39"); + { if (ysp_add(_yy, Y_RPC, $2, NULL) == NULL) _YYERROR("39"); clicon_debug(2,"rpc-stmt -> RPC id-arg-str ;"); } | K_RPC id_arg_str { if (ysp_add_push(_yy, Y_RPC, $2) == NULL) _YYERROR("40"); } @@ -885,7 +900,7 @@ typedef_substmt : type_stmt { clicon_debug(2,"typedef-substmt -> type-s /* Type */ type_stmt : K_TYPE identifier_ref_arg_str ';' - { if (ysp_add(_yy, Y_TYPE, $2) == NULL) _YYERROR("48"); + { if (ysp_add(_yy, Y_TYPE, $2, NULL) == NULL) _YYERROR("48"); clicon_debug(2,"type-stmt -> TYPE identifier-ref-arg-str ;");} | K_TYPE identifier_ref_arg_str { if (ysp_add_push(_yy, Y_TYPE, $2) == NULL) _YYERROR("49"); @@ -953,7 +968,7 @@ grouping_substmt : status_stmt { clicon_debug(2,"grouping-substmt -> st /* length-stmt */ length_stmt : K_LENGTH string ';' /* XXX length-arg-str */ - { if (ysp_add(_yy, Y_LENGTH, $2) == NULL) _YYERROR("53"); + { if (ysp_add(_yy, Y_LENGTH, $2, NULL) == NULL) _YYERROR("53"); clicon_debug(2,"length-stmt -> LENGTH string ;"); } | K_LENGTH string @@ -978,7 +993,7 @@ length_substmt : error_message_stmt { clicon_debug(2,"length-substmt -> error-m /* Pattern */ pattern_stmt : K_PATTERN string ';' - { if (ysp_add(_yy, Y_PATTERN, $2) == NULL) _YYERROR("56"); + { if (ysp_add(_yy, Y_PATTERN, $2, NULL) == NULL) _YYERROR("56"); clicon_debug(2,"pattern-stmt -> PATTERN string ;"); } | K_PATTERN string @@ -1002,7 +1017,7 @@ pattern_substmt : reference_stmt { clicon_debug(2,"pattern-substmt -> refere /* Extension */ extension_stmt: K_EXTENSION id_arg_str ';' - { if (ysp_add(_yy, Y_EXTENSION, $2) == NULL) _YYERROR("59"); + { if (ysp_add(_yy, Y_EXTENSION, $2, NULL) == NULL) _YYERROR("59"); clicon_debug(2,"extenstion-stmt -> EXTENSION id-arg-str ;"); } | K_EXTENSION id_arg_str { if (ysp_add_push(_yy, Y_EXTENSION, $2) == NULL) _YYERROR("60"); } @@ -1033,7 +1048,7 @@ argument_stmt : K_ARGUMENT id_arg_str ';' /* Feature */ feature_stmt : K_FEATURE id_arg_str ';' - { if (ysp_add(_yy, Y_FEATURE, $2) == NULL) _YYERROR("62"); + { if (ysp_add(_yy, Y_FEATURE, $2, NULL) == NULL) _YYERROR("62"); clicon_debug(2,"feature-stmt -> FEATURE id-arg-str ;"); } | K_FEATURE id_arg_str { if (ysp_add_push(_yy, Y_FEATURE, $2) == NULL) _YYERROR("63"); } @@ -1059,7 +1074,7 @@ feature_substmt : if_feature_stmt { clicon_debug(2,"feature-substmt -> if-fea /* Identity */ identity_stmt : K_IDENTITY string ';' /* XXX identifier-arg-str */ - { if (ysp_add(_yy, Y_IDENTITY, $2) == NULL) _YYERROR("65"); + { if (ysp_add(_yy, Y_IDENTITY, $2, NULL) == NULL) _YYERROR("65"); clicon_debug(2,"identity-stmt -> IDENTITY string ;"); } | K_IDENTITY string @@ -1085,7 +1100,7 @@ identity_substmt : base_stmt { clicon_debug(2,"identity-substmt -> base- /* range-stmt */ range_stmt : K_RANGE string ';' /* XXX range-arg-str */ - { if (ysp_add(_yy, Y_RANGE, $2) == NULL) _YYERROR("68"); + { if (ysp_add(_yy, Y_RANGE, $2, NULL) == NULL) _YYERROR("68"); clicon_debug(2,"range-stmt -> RANGE string ;"); } | K_RANGE string @@ -1110,7 +1125,7 @@ range_substmt : error_message_stmt { clicon_debug(2,"range-substmt -> error-me /* enum-stmt */ enum_stmt : K_ENUM string ';' - { if (ysp_add(_yy, Y_ENUM, $2) == NULL) _YYERROR("71"); + { if (ysp_add(_yy, Y_ENUM, $2, NULL) == NULL) _YYERROR("71"); clicon_debug(2,"enum-stmt -> ENUM string ;"); } | K_ENUM string { if (ysp_add_push(_yy, Y_ENUM, $2) == NULL) _YYERROR("72"); } @@ -1135,7 +1150,7 @@ enum_substmt : value_stmt { clicon_debug(2,"enum-substmt -> value-stm /* bit-stmt */ bit_stmt : K_BIT string ';' - { if (ysp_add(_yy, Y_BIT, $2) == NULL) _YYERROR("74"); + { if (ysp_add(_yy, Y_BIT, $2, NULL) == NULL) _YYERROR("74"); clicon_debug(2,"bit-stmt -> BIT string ;"); } | K_BIT string { if (ysp_add_push(_yy, Y_BIT, $2) == NULL) _YYERROR("75"); } @@ -1159,7 +1174,7 @@ bit_substmt : position_stmt { clicon_debug(2,"bit-substmt -> positition /* mus-stmt */ must_stmt : K_MUST string ';' - { if (ysp_add(_yy, Y_MUST, $2) == NULL) _YYERROR("77"); + { if (ysp_add(_yy, Y_MUST, $2, NULL) == NULL) _YYERROR("77"); clicon_debug(2,"must-stmt -> MUST string ;"); } | K_MUST string @@ -1183,7 +1198,7 @@ must_substmt : error_message_stmt { clicon_debug(2,"must-substmt -> error-mes /* error-message-stmt */ error_message_stmt : K_ERROR_MESSAGE string ';' - { if (ysp_add(_yy, Y_ERROR_MESSAGE, $2) == NULL) _YYERROR("80"); } + { if (ysp_add(_yy, Y_ERROR_MESSAGE, $2, NULL) == NULL) _YYERROR("80"); } /* import */ import_stmt : K_IMPORT id_arg_str @@ -1206,144 +1221,144 @@ import_substmt : prefix_stmt { clicon_debug(2,"import-stmt -> prefix-stmt"); } /* Simple statements */ yang_version_stmt : K_YANG_VERSION string ';' /* XXX yang-version-arg-str */ - { if (ysp_add(_yy, Y_YANG_VERSION, $2) == NULL) _YYERROR("83"); + { if (ysp_add(_yy, Y_YANG_VERSION, $2, NULL) == NULL) _YYERROR("83"); clicon_debug(2,"yang-version-stmt -> YANG-VERSION string"); } ; fraction_digits_stmt : K_FRACTION_DIGITS string ';' /* XXX: fraction-digits-arg-str */ - { if (ysp_add(_yy, Y_FRACTION_DIGITS, $2) == NULL) _YYERROR("84"); + { if (ysp_add(_yy, Y_FRACTION_DIGITS, $2, NULL) == NULL) _YYERROR("84"); clicon_debug(2,"fraction-digits-stmt -> FRACTION-DIGITS string"); } ; if_feature_stmt : K_IF_FEATURE identifier_ref_arg_str ';' - { if (ysp_add(_yy, Y_IF_FEATURE, $2) == NULL) _YYERROR("85"); + { if (ysp_add(_yy, Y_IF_FEATURE, $2, NULL) == NULL) _YYERROR("85"); clicon_debug(2,"if-feature-stmt -> IF-FEATURE identifier-ref-arg-str"); } ; value_stmt : K_VALUE integer_value ';' - { if (ysp_add(_yy, Y_VALUE, $2) == NULL) _YYERROR("86"); + { if (ysp_add(_yy, Y_VALUE, $2, NULL) == NULL) _YYERROR("86"); clicon_debug(2,"value-stmt -> VALUE integer-value"); } ; position_stmt : K_POSITION integer_value ';' - { if (ysp_add(_yy, Y_POSITION, $2) == NULL) _YYERROR("87"); + { if (ysp_add(_yy, Y_POSITION, $2, NULL) == NULL) _YYERROR("87"); clicon_debug(2,"position-stmt -> POSITION integer-value"); } ; status_stmt : K_STATUS string ';' /* XXX: status-arg-str */ - { if (ysp_add(_yy, Y_STATUS, $2) == NULL) _YYERROR("88"); + { if (ysp_add(_yy, Y_STATUS, $2, NULL) == NULL) _YYERROR("88"); clicon_debug(2,"status-stmt -> STATUS string"); } ; config_stmt : K_CONFIG config_arg_str ';' - { if (ysp_add(_yy, Y_CONFIG, $2) == NULL) _YYERROR("89"); + { if (ysp_add(_yy, Y_CONFIG, $2, NULL) == NULL) _YYERROR("89"); clicon_debug(2,"config-stmt -> CONFIG config-arg-str"); } ; base_stmt : K_BASE identifier_ref_arg_str ';' - { if (ysp_add(_yy, Y_BASE, $2)== NULL) _YYERROR("90"); + { if (ysp_add(_yy, Y_BASE, $2, NULL)== NULL) _YYERROR("90"); clicon_debug(2,"base-stmt -> BASE identifier-ref-arg-str"); } ; path_stmt : K_PATH string ';' /* XXX: path-arg-str */ - { if (ysp_add(_yy, Y_PATH, $2)== NULL) _YYERROR("91"); + { if (ysp_add(_yy, Y_PATH, $2, NULL)== NULL) _YYERROR("91"); clicon_debug(2,"path-stmt -> PATH string"); } ; require_instance_stmt : K_REQUIRE_INSTANCE string ';' /* XXX: require-instance-arg-str */ - { if (ysp_add(_yy, Y_REQUIRE_INSTANCE, $2)== NULL) _YYERROR("92"); + { if (ysp_add(_yy, Y_REQUIRE_INSTANCE, $2, NULL)== NULL) _YYERROR("92"); clicon_debug(2,"require-instance-stmt -> REQUIRE-INSTANCE string"); } ; units_stmt : K_UNITS string ';' - { if (ysp_add(_yy, Y_UNITS, $2)== NULL) _YYERROR("93"); + { if (ysp_add(_yy, Y_UNITS, $2, NULL)== NULL) _YYERROR("93"); clicon_debug(2,"units-stmt -> UNITS string"); } ; default_stmt : K_DEFAULT string ';' - { if (ysp_add(_yy, Y_DEFAULT, $2)== NULL) _YYERROR("94"); + { if (ysp_add(_yy, Y_DEFAULT, $2, NULL)== NULL) _YYERROR("94"); clicon_debug(2,"default-stmt -> DEFAULT string"); } ; contact_stmt : K_CONTACT string ';' - { if (ysp_add(_yy, Y_CONTACT, $2)== NULL) _YYERROR("95"); + { if (ysp_add(_yy, Y_CONTACT, $2, NULL)== NULL) _YYERROR("95"); clicon_debug(2,"contact-stmt -> CONTACT string"); } ; revision_date_stmt : K_REVISION_DATE string ';' /* XXX date-arg-str */ - { if (ysp_add(_yy, Y_REVISION_DATE, $2) == NULL) _YYERROR("96"); + { if (ysp_add(_yy, Y_REVISION_DATE, $2, NULL) == NULL) _YYERROR("96"); clicon_debug(2,"revision-date-stmt -> date;"); } ; include_stmt : K_INCLUDE id_arg_str ';' - { if (ysp_add(_yy, Y_INCLUDE, $2)== NULL) _YYERROR("97"); + { if (ysp_add(_yy, Y_INCLUDE, $2, NULL)== NULL) _YYERROR("97"); clicon_debug(2,"include-stmt -> id-arg-str"); } | K_INCLUDE id_arg_str '{' revision_date_stmt '}' - { if (ysp_add(_yy, Y_INCLUDE, $2)== NULL) _YYERROR("98"); + { if (ysp_add(_yy, Y_INCLUDE, $2, NULL)== NULL) _YYERROR("98"); clicon_debug(2,"include-stmt -> id-arg-str { revision-date-stmt }"); } ; namespace_stmt : K_NAMESPACE string ';' /* XXX uri-str */ - { if (ysp_add(_yy, Y_NAMESPACE, $2)== NULL) _YYERROR("99"); + { if (ysp_add(_yy, Y_NAMESPACE, $2, NULL)== NULL) _YYERROR("99"); clicon_debug(2,"namespace-stmt -> NAMESPACE string"); } ; prefix_stmt : K_PREFIX string ';' /* XXX prefix-arg-str */ - { if (ysp_add(_yy, Y_PREFIX, $2)== NULL) _YYERROR("100"); + { if (ysp_add(_yy, Y_PREFIX, $2, NULL)== NULL) _YYERROR("100"); clicon_debug(2,"prefix-stmt -> PREFIX string ;");} ; description_stmt: K_DESCRIPTION string ';' - { if (ysp_add(_yy, Y_DESCRIPTION, $2)== NULL) _YYERROR("101"); + { if (ysp_add(_yy, Y_DESCRIPTION, $2, NULL)== NULL) _YYERROR("101"); clicon_debug(2,"description-stmt -> DESCRIPTION string ;");} ; organization_stmt: K_ORGANIZATION string ';' - { if (ysp_add(_yy, Y_ORGANIZATION, $2)== NULL) _YYERROR("102"); + { if (ysp_add(_yy, Y_ORGANIZATION, $2, NULL)== NULL) _YYERROR("102"); clicon_debug(2,"organization-stmt -> ORGANIZATION string ;");} ; min_elements_stmt: K_MIN_ELEMENTS integer_value ';' - { if (ysp_add(_yy, Y_MIN_ELEMENTS, $2)== NULL) _YYERROR("103"); + { if (ysp_add(_yy, Y_MIN_ELEMENTS, $2, NULL)== NULL) _YYERROR("103"); clicon_debug(2,"min-elements-stmt -> MIN-ELEMENTS integer ;");} ; max_elements_stmt: K_MAX_ELEMENTS integer_value ';' - { if (ysp_add(_yy, Y_MAX_ELEMENTS, $2)== NULL) _YYERROR("104"); + { if (ysp_add(_yy, Y_MAX_ELEMENTS, $2, NULL)== NULL) _YYERROR("104"); clicon_debug(2,"max-elements-stmt -> MIN-ELEMENTS integer ;");} ; reference_stmt: K_REFERENCE string ';' - { if (ysp_add(_yy, Y_REFERENCE, $2)== NULL) _YYERROR("105"); + { if (ysp_add(_yy, Y_REFERENCE, $2, NULL)== NULL) _YYERROR("105"); clicon_debug(2,"reference-stmt -> REFERENCE string ;");} ; mandatory_stmt: K_MANDATORY string ';' { yang_stmt *ys; - if ((ys = ysp_add(_yy, Y_MANDATORY, $2))== NULL) _YYERROR("106"); + if ((ys = ysp_add(_yy, Y_MANDATORY, $2, NULL))== NULL) _YYERROR("106"); clicon_debug(2,"mandatory-stmt -> MANDATORY mandatory-arg-str ;");} ; presence_stmt: K_PRESENCE string ';' { yang_stmt *ys; - if ((ys = ysp_add(_yy, Y_PRESENCE, $2))== NULL) _YYERROR("107"); + if ((ys = ysp_add(_yy, Y_PRESENCE, $2, NULL))== NULL) _YYERROR("107"); clicon_debug(2,"presence-stmt -> PRESENCE string ;");} ; ordered_by_stmt: K_ORDERED_BY string ';' { yang_stmt *ys; - if ((ys = ysp_add(_yy, Y_ORDERED_BY, $2))== NULL) _YYERROR("108"); + if ((ys = ysp_add(_yy, Y_ORDERED_BY, $2, NULL))== NULL) _YYERROR("108"); clicon_debug(2,"ordered-by-stmt -> ORDERED-BY ordered-by-arg ;");} ; key_stmt : K_KEY id_arg_str ';' /* XXX key_arg_str */ - { if (ysp_add(_yy, Y_KEY, $2)== NULL) _YYERROR("109"); + { if (ysp_add(_yy, Y_KEY, $2, NULL)== NULL) _YYERROR("109"); clicon_debug(2,"key-stmt -> KEY id-arg-str ;");} ; unique_stmt : K_UNIQUE id_arg_str ';' /* XXX key_arg_str */ - { if (ysp_add(_yy, Y_UNIQUE, $2)== NULL) _YYERROR("110"); + { if (ysp_add(_yy, Y_UNIQUE, $2, NULL)== NULL) _YYERROR("110"); clicon_debug(2,"key-stmt -> KEY id-arg-str ;");} ; diff --git a/lib/src/clixon_yang_type.c b/lib/src/clixon_yang_type.c index 335e0ed6..2494cf5c 100644 --- a/lib/src/clixon_yang_type.c +++ b/lib/src/clixon_yang_type.c @@ -905,8 +905,8 @@ yang_type_resolve(yang_stmt *ys, if (options) *options = 0x0; *yrestype = NULL; /* Initialization of resolved type that may not be necessary */ - type = ytype_id(ytype); /* This is the type to resolve */ - prefix = ytype_prefix(ytype); /* And this its prefix */ + type = yarg_id(ytype); /* This is the type to resolve */ + prefix = yarg_prefix(ytype); /* And this its prefix */ /* Cache does not work for eg string length 32 */ if (!yang_builtin(type) && ytype->ys_typecache != NULL){ if (yang_type_cache_get(ytype->ys_typecache, @@ -1034,7 +1034,7 @@ yang_type_get(yang_stmt *ys, goto done; } /* XXX: here we seem to have some problems if type is union */ - type = ytype_id(ytype); + type = yarg_id(ytype); if (origtype) *origtype = type; if (yang_type_resolve(ys, ytype, yrestype, diff --git a/test/test_restconf2.sh b/test/test_restconf2.sh index f0ae519e..5e73ac31 100755 --- a/test/test_restconf2.sh +++ b/test/test_restconf2.sh @@ -13,11 +13,9 @@ cat < $cfg $cfg /usr/local/var $fyang - false /usr/local/var/routing/routing.sock - /usr/local/var/routing/routing.pidfile - 1 + $dir/restconf.pidfile /usr/local/var/routing /usr/local/lib/xmldb/text.so @@ -25,7 +23,7 @@ EOF cat < $fyang module example{ - container interfaces-config{ + container cont1{ list interface{ key name; leaf name{ @@ -37,6 +35,11 @@ module example{ } } } + container cont2{ + leaf name{ + type string; + } + } } EOF @@ -62,56 +65,77 @@ sleep 1 new "restconf tests" + new "restconf POST initial tree" -expectfn 'curl -s -X POST -d {"interfaces-config":{"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' "" new "restconf GET datastore" -expectfn "curl -s -X GET http://localhost/restconf/data" '{"data": {"interfaces-config": {"interface": \[{"name": "local0","type": "regular"}\]}}}' +expectfn "curl -s -X GET http://localhost/restconf/data" '{"data": {"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}}' new "restconf GET interface" -expectfn "curl -s -X GET http://localhost/restconf/data/interfaces-config/interface=local0" '{"interface": \[{"name": "local0","type": "regular"}\]}' +expectfn "curl -s -X GET http://localhost/restconf/data/cont1/interface=local0" '{"interface": \[{"name": "local0","type": "regular"}\]}' new "restconf GET if-type" -expectfn "curl -s -X GET http://localhost/restconf/data/interfaces-config/interface=local0/type" '{"type": "regular"}' +expectfn "curl -s -X GET http://localhost/restconf/data/cont1/interface=local0/type" '{"type": "regular"}' new "restconf POST interface" -expectfn 'curl -s -X POST -d {"interface":{"name":"TEST","type":"eth0"}} http://localhost/restconf/data/interfaces-config' "" +expectfn 'curl -s -X POST -d {"interface":{"name":"TEST","type":"eth0"}} http://localhost/restconf/data/cont1' "" new "restconf POST again" -expectfn 'curl -s -X POST -d {"interface":{"name":"TEST","type":"eth0"}} http://localhost/restconf/data/interfaces-config' "Data resource already exis" +expectfn 'curl -s -X POST -d {"interface":{"name":"TEST","type":"eth0"}} http://localhost/restconf/data/cont1' "Data resource already exis" new "restconf POST from top" -expectfn 'curl -s -X POST -d {"interfaces-config":{"interface":{"name":"TEST","type":"eth0"}}} http://localhost/restconf/data' "Data resource already exists" +expectfn 'curl -s -X POST -d {"cont1":{"interface":{"name":"TEST","type":"eth0"}}} http://localhost/restconf/data' "Data resource already exists" new "restconf DELETE" -expectfn 'curl -s -X DELETE http://localhost/restconf/data/interfaces-config' "" +expectfn 'curl -s -X DELETE http://localhost/restconf/data/cont1' "" new "restconf GET null datastore" expectfn "curl -s -X GET http://localhost/restconf/data" '{"data": null}' new "restconf POST initial tree" -expectfn 'curl -s -X POST -d {"interfaces-config":{"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' "" + +new "restconf GET initial tree" +expectfn "curl -s -X GET http://localhost/restconf/data" '{"data": {"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}}' + +new "restconf DELETE whole datastore" +expectfn 'curl -s -X DELETE http://localhost/restconf/data' "" + +new "restconf GET null datastore" +expectfn "curl -s -X GET http://localhost/restconf/data" '{"data": null}' new "restconf PUT initial datastore" -expectfn 'curl -s -X PUT -d {"data":{"interfaces-config":{"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' "" new "restconf GET datastore" -expectfn "curl -s -X GET http://localhost/restconf/data" '{"data": {"interfaces-config": {"interface": \[{"name": "local0","type": "regular"}\]}}}' +expectfn "curl -s -X GET http://localhost/restconf/data" '{"data": {"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}}' + +new "restconf PUT replace datastore" +expectfn 'curl -s -X PUT -d {"data":{"cont2":{"name":"foo"}}} http://localhost/restconf/data' "" + +new "restconf GET replaced datastore" +expectfn "curl -s -X GET http://localhost/restconf/data" '{"data": {"cont2": {"name": "foo"}}}' + + +new "restconf PUT initial datastore again" +expectfn 'curl -s -X PUT -d {"data":{"cont1":{"interface":{"name":"local0","type":"regular"}}}} http://localhost/restconf/data' "" new "restconf PUT change interface" -expectfn 'curl -s -X PUT -d {"interface":{"name":"local0","type":"atm0"}} http://localhost/restconf/data/interfaces-config/interface=local0' "" +expectfn 'curl -s -X PUT -d {"interface":{"name":"local0","type":"atm0"}} http://localhost/restconf/data/cont1/interface=local0' "" + new "restconf GET datastore atm" -expectfn "curl -s -X GET http://localhost/restconf/data" '{"data": {"interfaces-config": {"interface": \[{"name": "local0","type": "atm0"}\]}}}' +expectfn "curl -s -X GET http://localhost/restconf/data" '{"data": {"cont1": {"interface": \[{"name": "local0","type": "atm0"}\]}}}' new "restconf PUT add interface" -expectfn 'curl -s -X PUT -d {"interface":{"name":"TEST","type":"eth0"}} http://localhost/restconf/data/interfaces-config/interface=TEST' "" +expectfn 'curl -s -X PUT -d {"interface":{"name":"TEST","type":"eth0"}} http://localhost/restconf/data/cont1/interface=TEST' "" new "restconf PUT change key error" -expectfn 'curl -is -X PUT -d {"interface":{"name":"ALPHA","type":"eth0"}} http://localhost/restconf/data/interfaces-config/interface=TEST' "Bad request" +expectfn 'curl -is -X PUT -d {"interface":{"name":"ALPHA","type":"eth0"}} http://localhost/restconf/data/cont1/interface=TEST' "Bad request" new "restconf POST invalid no type" -expectfn 'curl -s -X POST -d {"interface":{"name":"ALPHA"}} http://localhost/restconf/data/interfaces-config' "Bad request" +expectfn 'curl -s -X POST -d {"interface":{"name":"ALPHA"}} http://localhost/restconf/data/cont1' "Bad request" new "Kill restconf daemon" sudo pkill -u www-data clixon_restconf diff --git a/test/test_yang.sh b/test/test_yang.sh index 15eeba11..b53ad8d3 100755 --- a/test/test_yang.sh +++ b/test/test_yang.sh @@ -6,6 +6,7 @@ cfg=$dir/conf_yang.xml fyang=$dir/test.yang +fyangerr=$dir/err.yang cat < $cfg @@ -25,6 +26,12 @@ EOF cat < $fyang module example{ + prefix ex; + extension c-define { + description "Example from RFC 6020"; + argument "name"; + } + ex:c-define "MY_INTERFACES"; container x { list y { key "a b"; @@ -75,6 +82,17 @@ module example{ } EOF +# This yang definition uses an extension which is not defined. Error when loading +cat < $fyangerr +module example{ + prefix ex; + extension c-define { + description "Example from RFC 6020"; + argument "name"; + } + ex:not-defined ARGUMENT; +} +EOF # kill old backend (if any) new "kill old backend" sudo clixon_backend -zf $cfg -y $fyang @@ -89,6 +107,13 @@ if [ $? -ne 0 ]; then err fi +new "cli defined extension" +expectfn "$clixon_cli -1f $cfg -y $fyang show version" "3." + +new "cli not defined extension" +# 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" + new "netconf edit config" expecteof "$clixon_netconf -qf $cfg -y $fyang" "125]]>]]>" "^]]>]]>$" diff --git a/yang/ietf-netconf-acm@2012-02-22.yang b/yang/ietf-netconf-acm@2012-02-22.yang index 99ad961f..32888d51 100644 --- a/yang/ietf-netconf-acm@2012-02-22.yang +++ b/yang/ietf-netconf-acm@2012-02-22.yang @@ -194,7 +194,7 @@ module ietf-netconf-acm { */ container nacm { - /* nacm:default-deny-all; XXX How is this parsed ?? */ + nacm:default-deny-all; description "Parameters for NETCONF Access Control Model.";