X-Git-Url: https://git.archive.openwrt.org/?a=blobdiff_plain;f=libs%2Fuvl%2Froot%2Fusr%2Fbin%2Fuvl;h=83ed73941d329776bb9176879fc3696ff6f36489;hb=19e22598fd5b43a4e3e23e5e0d5f994281024035;hp=7dc6a00aafaf2e63a96e05eb46d05e3657a650e6;hpb=aa94931fa01c63f9644056eed73ea9c6a665b6ca;p=project%2Fluci.git diff --git a/libs/uvl/root/usr/bin/uvl b/libs/uvl/root/usr/bin/uvl index 7dc6a00aa..83ed73941 100755 --- a/libs/uvl/root/usr/bin/uvl +++ b/libs/uvl/root/usr/bin/uvl @@ -57,9 +57,90 @@ function getopt( arg, options ) 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 @@ -68,9 +149,9 @@ $Id$ Usage: uvl --help - uvl [--silent] [--schemedir=DIR] - [--no-strict-sections] [--no-strict-options] [--no-strict-validators] - [--no-strict-lists] 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 @@ -82,6 +163,9 @@ Options: --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. @@ -93,31 +177,56 @@ Options: --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 = - ( options['no-strict-lists'] and false or true ) + ( 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 ) - 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 @@ -126,4 +235,6 @@ else if not options.silent then print( err and err:string() or "Unknown error" ) end os.exit( 1 ) end +else + genspec( arguments[2] ) end