4 UCI Validation Layer - Command Line Utility
5 (c) 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
6 (c) 2008 Steven Barth <steven@midlink.org>
8 Licensed under the Apache License, Version 2.0 (the "License");
9 you may not use this file except in compliance with the License.
10 You may obtain a copy of the License at
12 http://www.apache.org/licenses/LICENSE-2.0
22 function getopt( arg, options )
23 options = options or ""
26 for k, v in ipairs(arg) do
27 if v:sub(1, 2) == "--" then
28 local x = v:find( "=", 1, true )
30 tab[ v:sub( 3, x-1 ) ] = v:sub( x+1 )
32 tab[ v:sub( 3 ) ] = true
34 elseif v:sub( 1, 1 ) == "-" then
40 if options:find( jopt, 1, true ) then
42 tab[ jopt ] = v:sub( y+1 )
45 tab[ jopt ] = arg[ k + 1 ]
60 function genspec(conf)
61 require("luci.model.uci")
62 require("luci.uvl.datatypes")
64 local uci = luci.model.uci.cursor()
65 local ok, err = uci:load(conf)
68 print("Can not load config:", err)
71 local function _guess_datatype(v)
72 if type(v) == "table" then v = v[1] end
74 for _, type in ipairs({
75 "boolean", "integer", "float", "ip4addr", "ip6addr",
76 "macaddr", "directory", "file"
78 if luci.uvl.datatypes[type](v) then
86 local co = uci:get_all(conf)
92 -- count section types
93 for _, section in pairs(co) do
94 ct[section['.type']] = ( ct[section['.type']] or 0 ) + 1
95 ca[section['.type']] = section['.anonymous']
96 so[section['.type']] = so[section['.type']] or { }
97 to[section['.type']] = to[section['.type']] or { }
99 for option, value in pairs(section) do
100 if option:sub(1,1) ~= "." then
101 so[section['.type']][option] = _guess_datatype(value)
102 to[section['.type']][option] = ( type(value) == "table" and "list" or "variable" )
108 print( "package %s" % conf )
110 -- write section schemes
111 for type, count in luci.util.kspairs(ct) do
112 print( "\nconfig section" )
113 print( "\toption name '%s'" % type )
114 print( "\toption title 'Section %s'" % type )
115 print( "\toption package '%s'"% conf )
116 print( "\toption named %s" % ( ca[type] and 'false' or 'true' ) )
117 print( "\toption unique %s" % ( ct[type] > 1 and 'false' or ( ca[type] and 'false' or 'true' ) ) )
118 print( "\toption dynamic false" )
119 print( "\toption required false" )
121 -- write option schemes
122 for opt, val in luci.util.kspairs(so[type]) do
123 print( "\nconfig variable" )
124 print( "\toption name '%s'" % opt )
125 print( "\toption title 'Option %s'" % opt )
126 print( "\toption section '%s.%s'" %{ conf, type } )
127 print( "\toption datatype '%s'" % so[type][opt] )
129 if to[type][opt] ~= "variable" then
130 print( "\toption type '%s'" % to[type][opt] )
141 local options, arguments = getopt( arg )
143 if #arguments ~= 2 or options.help then
146 uvl - UCI Validation Layer
148 (c) 2008 Jo-Philipp Wich, Steven Barth
152 uvl [--silent] [--schemedir=DIR] [--configdir=DIR] [--no-strict-sections] \
153 [--no-strict-options] [--no-strict-validators] [--no-strict-lists] \
154 {verify|verify-scheme|genspec} config[.section[.option]]
158 Display this help message.
161 Don't produce any output.
164 Use DIR as scheme directory.
167 Use DIR as config directory.
170 Don't treat sections found in config but not in scheme as error.
173 Don't treat options found in config but not in scheme as error.
175 --no-strict-validators
176 Don't invalidate config if an external validator fails.
179 Don't invalidate lists that are stored options.
183 Validate given configuration, section or option.
186 Validate given scheme against the reference meta scheme.
189 Generate a scheme skeleton from given configuration.
192 elseif arguments[1] == "verify" or arguments[1] == "verify-scheme" then
193 luci.uvl.STRICT_UNKNOWN_SECTIONS =
194 ( not options['no-strict-sections'] and true or false )
195 luci.uvl.STRICT_UNKNOWN_OPTIONS =
196 ( not options['no-strict-options'] and true or false )
197 luci.uvl.STRICT_EXTERNAL_VALIDATORS =
198 ( not options['no-strict-validators'] and true or false )
199 luci.uvl.STRICT_LIST_TYPE =
200 ( not options['no-strict-lists'] and true or false )
202 local uvl = luci.uvl.UVL(
203 type(options.schemedir) == "string" and options.schemedir,
204 type(options.configdir) == "string" and options.configdir
207 local cso = luci.util.split( arguments[2], "." )
210 if arguments[1] == "verify-scheme" then
211 uvl:read_scheme( 'schema', cso[1] )
213 local uci = uvl.uci.cursor(
214 type(options.configdir) == "string"
215 and options.configdir or uvl.schemedir .. '/default'
218 ok, err = uvl:validate_config( cso[1], uci:get_all(cso[1]) )
219 if err then err.code = luci.uvl.errors.ERR_SCHEME end
221 ok, err = uvl:validate( unpack(cso) )
225 if not options.silent then
226 print( string.format(
227 '%s "%s" validates fine!',
228 ( arguments[1] == "verify-scheme" and "Scheme" or
229 ( #cso == 1 and "Config" or
230 ( #cso == 2 and "Section" or "Option" ) ) ),
231 table.concat(cso, ".")
236 if not options.silent then print( err and err:string() or "Unknown error" ) end
240 genspec( arguments[2] )