Skip to content

Commit ca4c0ba

Browse files
committed
yanglint UPDATE extension parsing and validation
1 parent a8458ba commit ca4c0ba

File tree

6 files changed

+151
-11
lines changed

6 files changed

+151
-11
lines changed

tools/lint/cmd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ COMMAND commands[] = {
7070
},
7171
{
7272
"data", cmd_data_opt, cmd_data_dep, cmd_data_store, cmd_data_process, cmd_data_help, NULL,
73-
"Load, validate and optionally print instance data", "d:ef:F:hmo:O:R:r:nt:x:"
73+
"Load, validate and optionally print instance data", "d:ef:F:hmo:O:R:r:nt:x:ik:"
7474
},
7575
{
7676
"list", cmd_list_opt, cmd_list_dep, cmd_list_exec, NULL, cmd_list_help, NULL,

tools/lint/cmd.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,15 @@ int cmd_debug_dep(struct yl_opt *yo, int posc);
381381
*/
382382
int cmd_debug_store(struct ly_ctx **ctx, struct yl_opt *yo, const char *posv);
383383

384+
/**
385+
* @brief Store the values: prefix, name, argument of extension.
386+
*
387+
* @param[in] extension_name String in format "<prefix>:<name>:<argument>".
388+
* @param[in,out] yo Options for yanglint.
389+
* @return 0 on success.
390+
*/
391+
int parse_ext_string(char *extension_name, struct yl_opt *yo);
392+
384393
/**
385394
* @brief Set debug logging.
386395
*

tools/lint/cmd_data.c

Lines changed: 113 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* @author Michal Vasko <[email protected]>
44
* @author Radek Krejci <[email protected]>
55
* @author Adam Piecek <[email protected]>
6+
* @author Juraj Budai <[email protected]>
67
* @brief 'data' command of the libyang's yanglint tool.
78
*
89
* Copyright (c) 2015-2023 CESNET, z.s.p.o.
@@ -68,7 +69,9 @@ cmd_data_help_type(void)
6869
" element without <eventTime>).\n"
6970
" nc-notif - Similar to 'notif' but expect and check also the NETCONF\n"
7071
" envelope <notification> with element <eventTime> and its\n"
71-
" sibling as the actual notification.\n");
72+
" sibling as the actual notification.\n"
73+
" ext - Validates extension data based on loaded YANG modules.\n"
74+
" Need to be used with -k parameter.\n");
7275
}
7376

7477
static void
@@ -139,7 +142,12 @@ cmd_data_help(void)
139142
" existence is also checked in these operational data.\n"
140143
" -R FILE, --reply-rpc=FILE\n"
141144
" Provide source RPC for parsing of the 'nc-reply' TYPE. The FILE\n"
142-
" is supposed to contain the source 'nc-rpc' operation of the reply.\n");
145+
" is supposed to contain the source 'nc-rpc' operation of the reply.\n"
146+
" -k, --ext-id <name>\n"
147+
" Name of extension instance in format:\n"
148+
" <prefix>:<name>:<argument>\n"
149+
" -i --ext\n"
150+
" Validates extension data based on loaded YANG modules\n");
143151
cmd_data_help_format();
144152
cmd_data_help_in_format();
145153
printf(" -o OUTFILE, --output=OUTFILE\n"
@@ -166,6 +174,8 @@ cmd_data_opt(struct yl_opt *yo, const char *cmdline, char ***posv, int *posc)
166174
{"not-strict", no_argument, NULL, 'n'},
167175
{"type", required_argument, NULL, 't'},
168176
{"xpath", required_argument, NULL, 'x'},
177+
{"ext-id", required_argument, NULL, 'k'},
178+
{"ext", no_argument, NULL, 'i'},
169179
{NULL, 0, NULL, 0}
170180
};
171181

@@ -255,6 +265,15 @@ cmd_data_opt(struct yl_opt *yo, const char *cmdline, char ***posv, int *posc)
255265
return 1;
256266
}
257267
break;
268+
case 'k': /* --ext-id */
269+
if (parse_ext_string(optarg, yo)) {
270+
YLMSG_E("Invalid name of extension instance.");
271+
return 1;
272+
}
273+
break;
274+
case 'i': /* --ext */
275+
yo->data_ext = 1;
276+
break;
258277

259278
case 'h': /* --help */
260279
cmd_data_help();
@@ -346,6 +365,23 @@ cmd_data_dep(struct yl_opt *yo, int posc)
346365
}
347366
}
348367

368+
if (yo->data_ext && !yo->prefix) {
369+
if (yo->interactive) {
370+
YLMSG_E("When using '-i' the '-k' parameter need to be also set.");
371+
} else {
372+
YLMSG_E("When using '-t ext' the '-k' parameter need to be also set.");
373+
}
374+
return 1;
375+
}
376+
if (!yo->data_ext && yo->prefix) {
377+
if (yo->interactive) {
378+
YLMSG_E("When using '-k' parameter the '-i' need to be also set.");
379+
} else {
380+
YLMSG_E("When using '-k' parameter the '-t ext' need to be also set.");
381+
}
382+
return 1;
383+
}
384+
349385
return 0;
350386
}
351387

@@ -417,6 +453,34 @@ evaluate_xpath(const struct lyd_node *tree, const char *xpath)
417453
return 0;
418454
}
419455

456+
int
457+
parse_ext_string(char *extension_name, struct yl_opt *yo)
458+
{
459+
char *token = strtok(extension_name, ":");
460+
461+
if (token) {
462+
yo->prefix = strdup(token);
463+
token = strtok(NULL, ":");
464+
} else {
465+
return -1;
466+
}
467+
468+
if (token) {
469+
yo->name = strdup(token);
470+
token = strtok(NULL, ":");
471+
} else {
472+
return -1;
473+
}
474+
475+
if (token) {
476+
yo->argument = strdup(token);
477+
} else {
478+
return -1;
479+
}
480+
481+
return 0;
482+
}
483+
420484
/**
421485
* @brief Checking that a parent data node exists in the datastore for the nested-notification and action.
422486
*
@@ -675,11 +739,53 @@ process_data(struct ly_ctx *ctx, enum lyd_type type, uint8_t merge, LYD_FORMAT o
675739
int
676740
cmd_data_process(struct ly_ctx *ctx, struct yl_opt *yo)
677741
{
678-
/* parse, validate and print data */
679-
if (process_data(ctx, yo->data_type, yo->data_merge, yo->data_out_format, yo->out, yo->data_parse_options,
680-
yo->data_validate_options, yo->data_print_options, &yo->data_operational, &yo->reply_rpc,
681-
&yo->data_inputs, &yo->data_xpath)) {
682-
return 1;
742+
if (yo->data_ext) {
743+
struct lyd_node *tree = NULL;
744+
struct cmdline_file *input_f = NULL;
745+
struct lys_module *module = NULL;
746+
uint32_t idx = 0;
747+
748+
while ((module = ly_ctx_get_module_iter(ctx, &idx))) {
749+
if (!strcmp(module->prefix, yo->prefix)) {
750+
break;
751+
}
752+
}
753+
754+
if (!module) {
755+
YLMSG_E("Cannot find the \"%s\" prefix in yang modules.", yo->prefix);
756+
return 1;
757+
}
758+
759+
/* get the extension from module that user is looking for */
760+
for (size_t i = 0; i < LY_ARRAY_COUNT(module->compiled->exts); ++i) {
761+
if (!strcmp(module->compiled->exts[i].def->name, yo->name) &&
762+
!strcmp(module->compiled->exts[i].argument, yo->argument)) {
763+
yo->ext = &module->compiled->exts[i];
764+
break;
765+
}
766+
}
767+
768+
if (!yo->ext) {
769+
YLMSG_E("Extension '%s:%s:%s' not found in module '%s'.", yo->prefix, yo->name, yo->argument, module->name);
770+
return 1;
771+
}
772+
773+
input_f = (struct cmdline_file *)yo->data_inputs.objs[0];
774+
775+
if (lyd_parse_ext_data(yo->ext, NULL, input_f->in, input_f->format, 0, 0, &tree)) {
776+
YLMSG_E("Parsing of extension data failed.")
777+
}
778+
779+
lyd_free_all(tree);
780+
yo->data_ext = 0;
781+
782+
} else {
783+
/* parse, validate and print data */
784+
if (process_data(ctx, yo->data_type, yo->data_merge, yo->data_out_format, yo->out, yo->data_parse_options,
785+
yo->data_validate_options, yo->data_print_options, &yo->data_operational, &yo->reply_rpc,
786+
&yo->data_inputs, &yo->data_xpath)) {
787+
return 1;
788+
}
683789
}
684790

685791
return 0;

tools/lint/main_ni.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,9 @@ help(int shortout)
154154
" notif - Notification instance of a YANG notification.\n"
155155
" nc-notif - Similar to 'notif' but expect and check also the NETCONF\n"
156156
" envelope <notification> with element <eventTime> and its\n"
157-
" sibling as the actual notification.\n\n");
157+
" sibling as the actual notification.\n"
158+
" ext - Validates extension data based on loaded YANG modules.\n"
159+
" Need to be used with -k parameter.\n\n");
158160

159161
printf(" -d MODE, --default=MODE\n"
160162
" Print data with default values, according to the MODE\n"
@@ -215,6 +217,10 @@ help(int shortout)
215217
printf(" -J, --json-null\n"
216218
" Allow usage of JSON empty values ('null') within input data\n\n");
217219

220+
printf(" -k, --ext-id\n"
221+
" Name of extension instance in format: <prefix>:<name>:<argument>.\n"
222+
" Need to be used with -t ext parameter.\n\n");
223+
218224
printf(" -G GROUPS, --debug=GROUPS\n"
219225
#ifndef NDEBUG
220226
" Enable printing of specific debugging message group\n"
@@ -499,7 +505,7 @@ fill_context(int argc, char *argv[], struct yl_opt *yo, struct ly_ctx **ctx)
499505
yo->line_length = 0;
500506

501507
opterr = 0;
502-
while ((opt = getopt_long(argc, argv, "hvVQf:I:p:DF:iP:qs:neE:t:d:lL:o:O:R:myY:XJx:G:", options, &opt_index)) != -1) {
508+
while ((opt = getopt_long(argc, argv, "hvVQf:I:p:DF:iP:qs:neE:t:d:lL:o:O:R:myY:XJx:G:k:", options, &opt_index)) != -1) {
503509
switch (opt) {
504510
case 'h': /* --help */
505511
help(0);
@@ -688,7 +694,12 @@ fill_context(int argc, char *argv[], struct yl_opt *yo, struct ly_ctx **ctx)
688694
return -1;
689695
}
690696
break;
691-
697+
case 'k': /* --ext-id */
698+
if (parse_ext_string(optarg, yo)) {
699+
YLMSG_E("Invalid name of extension instance.");
700+
return -1;
701+
}
702+
break;
692703
default:
693704
YLMSG_E("Invalid option or missing argument: -%c.", optopt);
694705
return -1;

tools/lint/yl_opt.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ yl_opt_erase(struct yl_opt *yo)
8686
/* context */
8787
free(yo->searchpaths);
8888

89+
/*extension instance string*/
90+
free(yo->prefix);
91+
free(yo->name);
92+
free(yo->argument);
93+
8994
/* --reply-rpc */
9095
ly_in_free(yo->reply_rpc.in, 1);
9196

@@ -193,6 +198,8 @@ yl_opt_update_data_type(const char *arg, struct yl_opt *yo)
193198
yo->data_type = LYD_TYPE_NOTIF_NETCONF;
194199
} else if (!strcasecmp(arg, "data")) {
195200
/* default option */
201+
} else if (!strcasecmp(arg, "ext")) {
202+
yo->data_ext = 1;
196203
} else {
197204
return 1;
198205
}

tools/lint/yl_opt.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,17 @@ struct yl_opt {
112112
*/
113113
/* various options based on --type option */
114114
enum lyd_type data_type;
115+
ly_bool data_ext;
115116
uint32_t data_parse_options;
116117
uint32_t data_validate_options;
117118
uint32_t data_print_options;
118119

120+
/* unique identifier of extension instance*/
121+
char *prefix;
122+
char *name;
123+
char *argument;
124+
struct lysc_ext_instance *ext;
125+
119126
/* flag for --merge option */
120127
uint8_t data_merge;
121128

0 commit comments

Comments
 (0)