http://www.apache.org/licenses/LICENSE-2.0
-$Id: uvl.lua 2873 2008-08-17 21:43:56Z jow $
+$Id$
]]--
return tab, args
end
+function genspec(conf)
+ require("luci.model.uci")
+ require("luci.uvl.datatypes")
+
+ local uci = luci.model.uci.cursor()
+ local ok, err = uci:load(conf)
+
+ if not ok then
+ print("Can not load config:", err)
+ os.exit(1)
+ else
+ local function _guess_datatype(v)
+ if type(v) == "table" then v = v[1] end
+
+ for _, type in ipairs({
+ "boolean", "integer", "float", "ip4addr", "ip6addr",
+ "macaddr", "directory", "file"
+ }) do
+ if luci.uvl.datatypes[type](v) then
+ return type
+ end
+ end
+ return "string"
+ end
+
+
+ local co = uci:get_all(conf)
+ local ct = { }
+ local ca = { }
+ local so = { }
+ local to = { }
+
+ -- count section types
+ for _, section in pairs(co) do
+ ct[section['.type']] = ( ct[section['.type']] or 0 ) + 1
+ ca[section['.type']] = section['.anonymous']
+ so[section['.type']] = so[section['.type']] or { }
+ to[section['.type']] = to[section['.type']] or { }
+
+ for option, value in pairs(section) do
+ if option:sub(1,1) ~= "." then
+ so[section['.type']][option] = _guess_datatype(value)
+ to[section['.type']][option] = ( type(value) == "table" and "list" or "variable" )
+ end
+ end
+ end
+
+ -- package name
+ print( "package %s" % conf )
+
+ -- write section schemes
+ for type, count in luci.util.kspairs(ct) do
+ print( "\nconfig section" )
+ print( "\toption name '%s'" % type )
+ print( "\toption title 'Section %s'" % type )
+ print( "\toption package '%s'"% conf )
+ print( "\toption named %s" % ( ca[type] and 'false' or 'true' ) )
+ print( "\toption unique %s" % ( ct[type] > 1 and 'false' or ( ca[type] and 'false' or 'true' ) ) )
+ print( "\toption dynamic false" )
+ print( "\toption required false" )
+
+ -- write option schemes
+ for opt, val in luci.util.kspairs(so[type]) do
+ print( "\nconfig variable" )
+ print( "\toption name '%s'" % opt )
+ print( "\toption title 'Option %s'" % opt )
+ print( "\toption section '%s.%s'" %{ conf, type } )
+ print( "\toption datatype '%s'" % so[type][opt] )
+
+ if to[type][opt] ~= "variable" then
+ print( "\toption type '%s'" % to[type][opt] )
+ end
+ end
+
+ print("")
+ end
+
+ end
+end
+
+
local options, arguments = getopt( arg )
-if #arguments == 0 or options.help then
+if #arguments ~= 2 or options.help then
print([=[
uvl - UCI Validation Layer
-$Id: uvl.lua 2873 2008-08-17 21:43:56Z jow $
+$Id$
(c) 2008 Jo-Philipp Wich, Steven Barth
Usage:
uvl --help
- uvl [--silent] [--schemedir=DIR]
- [--no-strict-sections] [--no-strict-options]
- [--no-strict-validators] config[.section[.option]]
+ uvl [--silent] [--schemedir=DIR] [--configdir=DIR] [--no-strict-sections] \
+ [--no-strict-options] [--no-strict-validators] [--no-strict-lists] \
+ {verify|verify-scheme|genspec} config[.section[.option]]
Options:
--help
--schemedir=DIR
Use DIR as scheme directory.
+ --configdir=DIR
+ Use DIR as config directory.
+
--no-strict-sections
Don't treat sections found in config but not in scheme as error.
--no-strict-validators
Don't invalidate config if an external validator fails.
+
+ --no-strict-lists
+ Don't invalidate lists that are stored options.
+
+Actions:
+ verify
+ Validate given configuration, section or option.
+
+ verify-scheme
+ Validate given scheme against the reference meta scheme.
+
+ genspec
+ Generate a scheme skeleton from given configuration.
]=])
os.exit(255)
-else
+elseif arguments[1] == "verify" or arguments[1] == "verify-scheme" then
luci.uvl.STRICT_UNKNOWN_SECTIONS =
- ( options['no-strict-sections'] and false or true )
+ ( not options['no-strict-sections'] and true or false )
luci.uvl.STRICT_UNKNOWN_OPTIONS =
- ( options['no-strict-options'] and false or true )
+ ( not options['no-strict-options'] and true or false )
luci.uvl.STRICT_EXTERNAL_VALIDATORS =
- ( options['no-strict-validators'] and false or true )
+ ( not options['no-strict-validators'] and true or false )
+ luci.uvl.STRICT_LIST_TYPE =
+ ( not options['no-strict-lists'] and true or false )
local uvl = luci.uvl.UVL(
- type(options.schemedir) == "string" and options.schemedir or nil
+ type(options.schemedir) == "string" and options.schemedir,
+ type(options.configdir) == "string" and options.configdir
)
- local cso = luci.util.split( arguments[1], "." )
- local ok, err = uvl:validate( unpack(cso) )
+ local cso = luci.util.split( arguments[2], "." )
+ local ok, err
+
+ if arguments[1] == "verify-scheme" then
+ uvl:read_scheme( 'schema', cso[1] )
+
+ local uci = uvl.uci.cursor(
+ type(options.configdir) == "string"
+ and options.configdir or uvl.schemedir .. '/default'
+ )
+
+ ok, err = uvl:validate_config( cso[1], uci:get_all(cso[1]) )
+ if err then err.code = luci.uvl.errors.ERR_SCHEME end
+ else
+ ok, err = uvl:validate( unpack(cso) )
+ end
if ok then
if not options.silent then
print( string.format(
'%s "%s" validates fine!',
- ( #cso == 1 and "Config" or
- ( #cso == 2 and "Section" or "Option" ) ),
+ ( arguments[1] == "verify-scheme" and "Scheme" or
+ ( #cso == 1 and "Config" or
+ ( #cso == 2 and "Section" or "Option" ) ) ),
table.concat(cso, ".")
) )
end
os.exit( 0 )
else
- if not options.silent then print( err ) end
+ if not options.silent then print( err and err:string() or "Unknown error" ) end
os.exit( 1 )
end
+else
+ genspec( arguments[2] )
end