Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tools: ynl: add schema checking

Add a --validate flag to pyynl for explicit schema check with error
reporting and add a schema_check make target to check all YNL specs.

make -C tools/net/ynl schema_check
make: Entering directory '/home/donaldh/net-next/tools/net/ynl'
ok 1 binder.yaml schema validation
not ok 2 conntrack.yaml schema validation
'labels mask' does not match '^[0-9a-z-]+$'

Failed validating 'pattern' in schema['properties']['attribute-sets']['items']['properties']['attributes']['items']['properties']['name']:
{'type': 'string', 'pattern': '^[0-9a-z-]+$'}

On instance['attribute-sets'][14]['attributes'][22]['name']:
'labels mask'

ok 3 devlink.yaml schema validation
[...]

Signed-off-by: Donald Hunter <donald.hunter@gmail.com>
Link: https://patch.msgid.link/20251127123502.89142-2-donald.hunter@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Donald Hunter and committed by
Jakub Kicinski
362d051c 2c80116b

+35 -6
+19 -1
tools/net/ynl/Makefile
··· 12 12 libdir ?= $(prefix)/$(libdir_relative) 13 13 includedir ?= $(prefix)/include 14 14 15 + SPECDIR=../../../Documentation/netlink/specs 16 + 15 17 SUBDIRS = lib generated samples ynltool tests 16 18 17 19 all: $(SUBDIRS) libynl.a ··· 56 54 run_tests: 57 55 @$(MAKE) -C tests run_tests 58 56 59 - .PHONY: all clean distclean install run_tests $(SUBDIRS) 57 + 58 + schema_check: 59 + @N=1; \ 60 + for spec in $(SPECDIR)/*.yaml ; do \ 61 + NAME=$$(basename $$spec) ; \ 62 + OUTPUT=$$(./pyynl/cli.py --spec $$spec --validate) ; \ 63 + if [ $$? -eq 0 ] ; then \ 64 + echo "ok $$N $$NAME schema validation" ; \ 65 + else \ 66 + echo "not ok $$N $$NAME schema validation" ; \ 67 + echo "$$OUTPUT" ; \ 68 + echo ; \ 69 + fi ; \ 70 + N=$$((N+1)) ; \ 71 + done 72 + 73 + .PHONY: all clean distclean install run_tests schema_check $(SUBDIRS)
+16 -5
tools/net/ynl/pyynl/cli.py
··· 10 10 import textwrap 11 11 12 12 sys.path.append(pathlib.Path(__file__).resolve().parent.as_posix()) 13 - from lib import YnlFamily, Netlink, NlError 13 + from lib import YnlFamily, Netlink, NlError, SpecFamily 14 14 15 15 sys_schema_dir='/usr/share/ynl' 16 16 relative_schema_dir='../../../../Documentation/netlink' ··· 127 127 group.add_argument('--list-msgs', action='store_true') 128 128 group.add_argument('--list-attrs', dest='list_attrs', metavar='OPERATION', type=str, 129 129 help='List attributes for an operation') 130 + group.add_argument('--validate', action='store_true') 130 131 131 132 parser.add_argument('--duration', dest='duration', type=int, 132 133 help='when subscribed, watch for DURATION seconds') ··· 169 168 170 169 if args.family: 171 170 spec = f"{spec_dir()}/{args.family}.yaml" 172 - if args.schema is None and spec.startswith(sys_schema_dir): 173 - args.schema = '' # disable schema validation when installed 174 - if args.process_unknown is None: 175 - args.process_unknown = True 176 171 else: 177 172 spec = args.spec 178 173 if not os.path.isfile(spec): 179 174 raise Exception(f"Spec file {spec} does not exist") 175 + 176 + if args.validate: 177 + try: 178 + SpecFamily(spec, args.schema) 179 + except Exception as error: 180 + print(error) 181 + exit(1) 182 + return 183 + 184 + if args.family: # set behaviour when using installed specs 185 + if args.schema is None and spec.startswith(sys_schema_dir): 186 + args.schema = '' # disable schema validation when installed 187 + if args.process_unknown is None: 188 + args.process_unknown = True 180 189 181 190 ynl = YnlFamily(spec, args.schema, args.process_unknown, 182 191 recv_size=args.dbg_small_recv)