#!/usr/bin/env luajit local args = {...} verbosity = -1 local logFile --[[ Ordered table iterator, allow to iterate on the natural order of the keys of a table. From http://lua-users.org/wiki/SortedIteration ]] function __genOrderedIndex( t ) local orderedIndex = {} for key in pairs(t) do table.insert( orderedIndex, key ) end table.sort( orderedIndex ) return orderedIndex end function orderedNext(t, state) -- Equivalent of the next function, but returns the keys in the alphabetic -- order. We use a temporary ordered key table that is stored in the -- table being iterated. local key = nil --print("orderedNext: state = "..tostring(state) ) if state == nil then -- the first time, generate the index t.__orderedIndex = __genOrderedIndex( t ) key = t.__orderedIndex[1] else -- fetch the next value for i = 1,table.getn(t.__orderedIndex) do if t.__orderedIndex[i] == state then key = t.__orderedIndex[i+1] end end end if key then return key, t[key] end -- no more value to return, cleanup t.__orderedIndex = nil return end function orderedPairs(t) -- Equivalent of the pairs() function on tables. Allows to iterate -- in order return orderedNext, t, nil end local plurals = function(e, w) local result = "" if 1 == e then result = e .. " error" elseif e ~= 0 then result = e .. " errors" end if 0 < w then if 0 < e then result = result .. ", " end if 1 == w then result = result .. w .. " warning" else result = result .. w .. " warnings" end end if "" ~= result then result = " (" .. result .. ")" end return result end local results = {} local log = function(v, t, s, prot, test, host) local x = "" if nil == prot then prot = "" end if nil ~= test then x = x .. test else test = "" end if nil ~= host then if #x > 0 then x = x .. " " end x = x .. host end if #x > 0 then t = t .. "(" .. x .. ")" end if v <= verbosity then if 3 <= verbosity then t = os.date() .. " " .. t end print(t .. ": " .. s) end if nil ~= logFile then logFile:write(os.date() .. " " .. t .. ": " .. s .. "\n") logFile:flush() end end local D = function(s) log(3, "DEBUG ", s) end local I = function(s) log(2, "INFO ", s) end local W = function(s, p, t, h) log(1, "WARNING ", s, p, t, h) end local E = function(s, p, t, h) log(0, "ERROR ", s, p, t, h) end local C = function(s) log(-1, "CRITICAL", s) end local faulty = "" local status = function(host, results, typ) local result = "" local e = 0 local w = 0 if nil ~= results[typ] then e = results[typ].errors w = results[typ].warnings for k, v in pairs(results[typ]) do if "table" == type(v) then e = e + v.errors w = w + v.warnings end end else for k, v in pairs(results) do if "table" == type(v) then for i, u in pairs(v) do if "table" == type(u) then if typ == i then e = e + u.errors w = w + u.warnings end end end end end end if 0 < e then result = e .. " errors" end if 1 == e then result = e .. " error" end if 0 < w then if 0 < e then result = result .. ", " end if 1 == w then result = result .. w .. " warning" else result = result .. w .. " warnings" end end if "[OK]" ~= result then if 0 < e then result = "[FAILED] (" .. result .. ")" faulty = faulty .. host .. " (" .. typ .. ")\n" elseif 0 < w then result = "[OK] (" .. result .. ")" else result = "[OK]" end end return result end local collate = function(host, ip, results) local f = "results/" .. host .. "_" .. ip .. ".lua" local rfile, e = io.open(f, "r") if nil == rfile then I("opening " .. f .. " file - " .. e) else rfile:close() local rs = loadfile(f)() for k, v in pairs(rs) do if "table" == type(v) then for i, u in pairs(v) do if "table" == type(u) then for h, t in pairs(u) do local a = results[k][h] if nil == a then a = 0 end results[k][h] = a + t end else local a = results[k][i] if nil == a then a = 0 end results[k][i] = a + u end end else local a = results[k] if nil == a then a = 0 end results[k] = a + v end end end return results end local mirrors = loadfile("results/mirrors.lua")() local logCount = function(domain, ip) local nm = "LOG_" .. domain local log = "" local extra = "" if nil ~= ip then nm = nm .. "_" .. ip end nm = nm .. ".html" local rfile, e = io.open("results/" .. nm, "r") if nil ~= rfile then local errors = 0 local warnings = 0 for l in rfile:lines() do if nil ~= l:match(">ERROR ") then errors = errors + 1 end if nil ~= l:match(">WARNING ") then warnings = warnings + 1 end end rfile:close() -- if nil == ip then -- log = "" .. domain .. "" -- else -- log = "" .. ip .. "" -- end log = log .. plurals(errors, warnings) end return log end local file, e = io.open("results/Report-email.txt", "w+") if nil == file then C("opening mirrors file - " .. e) else file:write( "Dear Mirror Admins,\n\n" .. "The full list of Devuan package mirrors is available at the URL:\n\n" .. " https://pkgmaster.devuan.org/mirror_list.txt\n\n" .. 'Please contact "mirrors@devuan.org" if any of the information \nin the file above needs to be amended. \n\n' .. "The full results of the mirror checking is available at the URL:\n\n" .. " https://sledjhamr.org/apt-panopticon/results/Report-web.html\n\n" .. "Due to the nature of the tests, some errors or warnings will be \ncounted several times. " .. "Refer to the logs on the web page for details.\n\n" .. "Please see below the current status of the Devuan Package Mirror \nnetwork:\n\n" .. "---- BEGIN MIRROR-STATUS ----\n") for k, v in orderedPairs(mirrors) do local results = loadfile("results/" .. k .. ".lua")() file:write(k .. "....\n") local IPs = v.IPs for i, u in pairs(IPs) do if "table" == type(u) then for h, t in pairs(u) do results = collate(k, h, results) end else results = collate(k, i, results) end end local http = status(k, results, "http") local https = status(k, results, "https") local dns = "" local protocol = status(k, results, "Protocol") local sanity = "[skip]" local integrity = status(k, results, "Integrity") local updated = "[skip]" -- DNS-RR test. if ("deb.devuan.org" ~= k) and (nil ~= mirrors["deb.devuan.org"]) then for l, w in pairs(mirrors[k].IPs) do if type(w) == "table" then for i, u in pairs(w) do if nil ~= mirrors["deb.devuan.org"].IPs["deb.roundr.devuan.org"][i] then local log = logCount("deb.devuan.org", i) if "" ~= log then if "" == dns then dns = " " else dns = dns .. " " end dns = dns .. logCount("deb.devuan.org", i) else if "" == dns then dns = " " else dns = dns .. " " end dns = dns .. i end end end else if nil ~= mirrors["deb.devuan.org"].IPs["deb.roundr.devuan.org"][l] then local log = logCount("deb.devuan.org", l) if "" ~= log then if "" == dns then dns = " " else dns = dns .. " " end dns = dns .. log else if "" == dns then dns = " " else dns = dns .. " " end dns = dns .. l end end end end if "" == dns then dns = "[no]" end dns = " DNS-RR: " .. dns end file:write( " http: " .. http .. " https: " .. https .. dns .. "\n" .. " Protocol: " .. protocol .. " URL-sanity: " .. sanity .. " Integrity: " .. integrity .. " Updated: " .. updated .. "\n") end file:write( "\n==== faulty mirrors: ====\n" .. faulty) file:write( "\n---- END MIRROR-STATUS ----\n\n" .. "Thanks for your precious help in ensuring that Devuan GNU+Linux \nremains a universal, stable, dependable, free operating system.\n\n" .. "Love\n\n" .. "The Dev1Devs\n\n") file:close() end