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]
153 [--no-strict-sections] [--no-strict-options] [--no-strict-validators]
154 [--no-strict-lists] {verify|genspec} config[.section[.option]]
158 Display this help message.
161 Don't produce any output.
164 Use DIR as scheme directory.
167 Don't treat sections found in config but not in scheme as error.
170 Don't treat options found in config but not in scheme as error.
172 --no-strict-validators
173 Don't invalidate config if an external validator fails.
176 Don't invalidate lists that are stored options.
180 Validate given configuration, section or option.
183 Generate a scheme skeleton from given configuration.
186 elseif arguments[1] == "verify" then
187 luci.uvl.STRICT_UNKNOWN_SECTIONS =
188 ( options['no-strict-sections'] and false or true )
189 luci.uvl.STRICT_UNKNOWN_OPTIONS =
190 ( options['no-strict-options'] and false or true )
191 luci.uvl.STRICT_EXTERNAL_VALIDATORS =
192 ( options['no-strict-validators'] and false or true )
193 luci.uvl.STRICT_LIST_TYPE =
194 ( options['no-strict-lists'] and false or true )
196 local uvl = luci.uvl.UVL(
197 type(options.schemedir) == "string" and options.schemedir or nil
200 local cso = luci.util.split( arguments[2], "." )
201 local ok, err = uvl:validate( unpack(cso) )
204 if not options.silent then
205 print( string.format(
206 '%s "%s" validates fine!',
207 ( #cso == 1 and "Config" or
208 ( #cso == 2 and "Section" or "Option" ) ),
209 table.concat(cso, ".")
214 if not options.silent then print( err and err:string() or "Unknown error" ) end
218 genspec( arguments[2] )