aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/apt-panopticon-report-email-web.lua
diff options
context:
space:
mode:
authoronefang2019-12-10 15:45:11 +1000
committeronefang2019-12-10 15:45:11 +1000
commit4bb51520521d9ab612d50dd2bcf904d70cf15735 (patch)
tree8d9fde355e1ecc1b06f400f99b2285ca6492023d /apt-panopticon-report-email-web.lua
parentAdd freedom -1. (diff)
downloadapt-panopticon-4bb51520521d9ab612d50dd2bcf904d70cf15735.zip
apt-panopticon-4bb51520521d9ab612d50dd2bcf904d70cf15735.tar.gz
apt-panopticon-4bb51520521d9ab612d50dd2bcf904d70cf15735.tar.bz2
apt-panopticon-4bb51520521d9ab612d50dd2bcf904d70cf15735.tar.xz
Move common code to it's own module.
Some minor clean ups and test tweaks likely came for the ride.
Diffstat (limited to 'apt-panopticon-report-email-web.lua')
-rwxr-xr-xapt-panopticon-report-email-web.lua250
1 files changed, 47 insertions, 203 deletions
diff --git a/apt-panopticon-report-email-web.lua b/apt-panopticon-report-email-web.lua
index 1144550..ef61183 100755
--- a/apt-panopticon-report-email-web.lua
+++ b/apt-panopticon-report-email-web.lua
@@ -1,143 +1,22 @@
1#!/usr/bin/env luajit 1#!/usr/bin/env luajit
2 2
3local args = {...} 3local APT = require 'apt-panopticommon'
4local D = APT.D
5local I = APT.I
6local W = APT.W
7local E = APT.E
8local C = APT.C
9local arg, sendArgs = APT.parseArgs({...})
4 10
5verbosity = -1
6local logFile
7local html = false
8
9
10--[[ Ordered table iterator, allow to iterate on the natural order of the keys of a table.
11 From http://lua-users.org/wiki/SortedIteration
12 ]]
13function __genOrderedIndex( t )
14 local orderedIndex = {}
15 for key in pairs(t) do
16 table.insert( orderedIndex, key )
17 end
18 table.sort( orderedIndex )
19 return orderedIndex
20end
21function orderedNext(t, state)
22 -- Equivalent of the next function, but returns the keys in the alphabetic
23 -- order. We use a temporary ordered key table that is stored in the
24 -- table being iterated.
25
26 local key = nil
27 --print("orderedNext: state = "..tostring(state) )
28 if state == nil then
29 -- the first time, generate the index
30 t.__orderedIndex = __genOrderedIndex( t )
31 key = t.__orderedIndex[1]
32 else
33 -- fetch the next value
34 for i = 1,table.getn(t.__orderedIndex) do
35 if t.__orderedIndex[i] == state then
36 key = t.__orderedIndex[i+1]
37 end
38 end
39 end
40
41 if key then
42 return key, t[key]
43 end
44
45 -- no more value to return, cleanup
46 t.__orderedIndex = nil
47 return
48end
49function orderedPairs(t)
50 -- Equivalent of the pairs() function on tables. Allows to iterate
51 -- in order
52 return orderedNext, t, nil
53end
54
55-- Use this to dump a table to a string, with HTML.
56dumpTableHTML = function (table, space, name)
57 local r = name .. "\n"
58 r = r .. dumpTableHTMLSub(table, space .. " ")
59 r = r .. space .. ""
60 return r
61end
62dumpTableHTMLSub = function (table, space)
63 local r = ""
64 for k, v in orderedPairs(table) do
65 if type(v) == "table" then
66 if " " == space then
67 r = r .. space .. dumpTableHTML(v, space, k .. "<ul>") .. "</ul>\n"
68 else
69 r = r .. "<li>" .. space .. dumpTableHTML(v, space, k .. "<ul>") .. "</ul></li>\n"
70 end
71 else
72 r = r .. space .. "<li>" .. k .. "</li>\n"
73 end
74 end
75 return r
76end
77
78local checkFile = function(f)
79 local h, e = io.open(f, "r")
80 if nil == h then return false else h:close(); return true end
81end
82
83local plurals = function(e, w)
84 local result = ""
85 if 1 == e then
86 result = e .. " error"
87 elseif e ~= 0 then
88 result = e .. " errors"
89 end
90 if ("" ~= result) and html then result = "<font color='red'><b>" .. result .. "</b></font>" end
91-- result = " " .. result
92 if 0 < w then
93 if 0 < e then result = result .. ", " end
94 if 1 == w then
95 result = result .. w .. " warning"
96 else
97 result = result .. w .. " warnings"
98 end
99 if ("" ~= result) and html then result = "<font color='yellow'><b>" .. result .. "</b></font>" end
100-- result = " " .. result
101 end
102 if "" ~= result then result = " (" .. result .. ")" end
103 return result
104end
105 11
106local results = {} 12local results = {}
107 13APT.mirrors = loadfile("results/mirrors.lua")()
108local log = function(v, t, s, prot, test, host)
109 local x = ""
110 if nil == prot then prot = "" end
111 if nil ~= test then x = x .. test else test = "" end
112 if nil ~= host then
113 if #x > 0 then x = x .. " " end
114 x = x .. host
115 end
116 if #x > 0 then
117 t = t .. "(" .. x .. ")"
118 end
119 if v <= verbosity then
120 if 3 <= verbosity then t = os.date() .. " " .. t end
121 print(t .. ": " .. s)
122 end
123 if nil ~= logFile then
124 logFile:write(os.date() .. " " .. t .. ": " .. s .. "\n")
125 logFile:flush()
126 end
127end
128local D = function(s) log(3, "DEBUG ", s) end
129local I = function(s) log(2, "INFO ", s) end
130local W = function(s, p, t, h) log(1, "WARNING ", s, p, t, h) end
131local E = function(s, p, t, h) log(0, "ERROR ", s, p, t, h) end
132local C = function(s) log(-1, "CRITICAL", s) end
133
134local mirrors = loadfile("results/mirrors.lua")()
135 14
136local revDNS = function(dom, IP) 15local revDNS = function(dom, IP)
137 if "deb.devuan.org" ~= dom then 16 if "deb.devuan.org" ~= dom then
138 if nil ~= mirrors["deb.devuan.org"] then 17 if nil ~= APT.mirrors["deb.devuan.org"] then
139 if nil ~= mirrors["deb.devuan.org"].IPs["deb.roundr.devuan.org"][IP] then 18 if nil ~= APT.mirrors["deb.devuan.org"].IPs["deb.roundr.devuan.org"][IP] then
140 if html then 19 if APT.html then
141 return "<font color='purple'><b>DNS-RR</b></font>" 20 return "<font color='purple'><b>DNS-RR</b></font>"
142 else 21 else
143 return "DNS-RR" 22 return "DNS-RR"
@@ -145,7 +24,7 @@ local revDNS = function(dom, IP)
145 end 24 end
146 end 25 end
147 else 26 else
148 for k, v in pairs(mirrors) do 27 for k, v in pairs(APT.mirrors) do
149 if "deb.devuan.org" ~= k then 28 if "deb.devuan.org" ~= k then
150 local IPs = v.IPs 29 local IPs = v.IPs
151 for i, u in pairs(IPs) do 30 for i, u in pairs(IPs) do
@@ -168,7 +47,7 @@ local status = function(host, results, typ)
168 local result = "" 47 local result = ""
169 local e = 0 48 local e = 0
170 local w = 0 49 local w = 0
171 local s = nil ~= mirrors[host].Protocols[typ] 50 local s = nil ~= APT.mirrors[host].Protocols[typ]
172 local to = results.timeout 51 local to = results.timeout
173 if ('http' ~= typ) and ('https' ~= typ) and ('ftp' ~= typ) and ('rsync' ~= typ) then s = true end 52 if ('http' ~= typ) and ('https' ~= typ) and ('ftp' ~= typ) and ('rsync' ~= typ) then s = true end
174 if nil ~= results[typ] then 53 if nil ~= results[typ] then
@@ -198,7 +77,7 @@ local status = function(host, results, typ)
198 if to then 77 if to then
199 result = "[TIMEOUT" 78 result = "[TIMEOUT"
200 if not s then result = result .. "*" end 79 if not s then result = result .. "*" end
201 if html then 80 if APT.html then
202 if s then 81 if s then
203 result = "[<font color='blue'><b>TIMEOUT</b></font>" 82 result = "[<font color='blue'><b>TIMEOUT</b></font>"
204 else 83 else
@@ -208,14 +87,14 @@ local status = function(host, results, typ)
208 elseif 0 < e then 87 elseif 0 < e then
209 result = "[FAILED" 88 result = "[FAILED"
210 if not s then result = result .. "*" end 89 if not s then result = result .. "*" end
211 if html then 90 if APT.html then
212 if s then 91 if s then
213 result = "[<font color='red'><b>FAILED</b></font>" 92 result = "[<font color='red'><b>FAILED</b></font>"
214 else 93 else
215 result = "[<font color='darkred'><b>FAILED*</b></font>" 94 result = "[<font color='darkred'><b>FAILED*</b></font>"
216 end 95 end
217 end 96 end
218 if html then 97 if APT.html then
219 faulty = faulty .. host .. " (" .. typ .. ")<br>\n" 98 faulty = faulty .. host .. " (" .. typ .. ")<br>\n"
220 else 99 else
221 faulty = faulty .. host .. " (" .. typ .. ")\n" 100 faulty = faulty .. host .. " (" .. typ .. ")\n"
@@ -223,7 +102,7 @@ local status = function(host, results, typ)
223 else 102 else
224 result = "[OK" 103 result = "[OK"
225 if not s then result = result .. "*" end 104 if not s then result = result .. "*" end
226 if html then 105 if APT.html then
227 if s then 106 if s then
228 result = "[<font color='lime'><b>OK</b></font>" 107 result = "[<font color='lime'><b>OK</b></font>"
229 else 108 else
@@ -231,43 +110,7 @@ local status = function(host, results, typ)
231 end 110 end
232 end 111 end
233 end 112 end
234 return result .. plurals(e, w) .. "]" 113 return result .. APT.plurals(e, w) .. "]"
235end
236
237local collate = function(host, ip, results)
238 local f = "results/" .. host .. "_" .. ip .. ".lua"
239 local rfile, e = io.open(f, "r")
240 if nil == rfile then I("opening " .. f .. " file - " .. e) else
241 rfile:close()
242 local rs = loadfile(f)()
243 for k, v in pairs(rs) do
244 if "table" == type(v) then
245 if "speed" == k then
246 if v.min < results.speed.min then results.speed.min = v.min end
247 if v.max > results.speed.max then results.speed.max = v.max end
248 else
249 for i, u in pairs(v) do
250 if "table" == type(u) then
251 for h, t in pairs(u) do
252 local a = results[k][i][h]
253 if nil == a then a = 0 end
254 results[k][i][h] = a + t
255 end
256 else
257 local a = results[k][i]
258 if nil == a then a = 0 end
259 results[k][i] = a + u
260 end
261 end
262 end
263 elseif "timeout" ~= k then
264 local a = results[k]
265 if nil == a then a = 0 end
266 results[k] = a + v
267 end
268 end
269 end
270 return results
271end 114end
272 115
273local m = {} 116local m = {}
@@ -287,20 +130,20 @@ local logCount = function(domain, ip)
287 if nil ~= l:match("><b>WARNING ") then warnings = warnings + 1 end 130 if nil ~= l:match("><b>WARNING ") then warnings = warnings + 1 end
288 end 131 end
289 rfile:close() 132 rfile:close()
290 if html then 133 if APT.html then
291 if nil == ip then 134 if nil == ip then
292 log = "<a href='" .. nm .. "'>" .. domain .. "</a>" 135 log = "<a href='" .. nm .. "'>" .. domain .. "</a>"
293 else 136 else
294 log = "<a href='" .. nm .. "'>" .. ip .. "</a>" 137 log = "<a href='" .. nm .. "'>" .. ip .. "</a>"
295 end 138 end
296 end 139 end
297 log = log .. plurals(errors, warnings) 140 log = log .. APT.plurals(errors, warnings)
298 end 141 end
299 return log 142 return log
300end 143end
301 144
302 145
303html = false 146APT.html = false
304local email, e = io.open("results/Report-email.txt", "w+") 147local email, e = io.open("results/Report-email.txt", "w+")
305if nil == email then C("opening mirrors file - " .. e) else 148if nil == email then C("opening mirrors file - " .. e) else
306 email:write( "Dear Mirror Admins,\n\n" .. 149 email:write( "Dear Mirror Admins,\n\n" ..
@@ -316,17 +159,17 @@ if nil == email then C("opening mirrors file - " .. e) else
316 "Please see below the current status of the Devuan Package Mirror \nnetwork:\n\n" .. 159 "Please see below the current status of the Devuan Package Mirror \nnetwork:\n\n" ..
317 "==== package mirror status " .. os.date("!%Y-%m-%d %H:%M") .. " GMT ====\n" .. 160 "==== package mirror status " .. os.date("!%Y-%m-%d %H:%M") .. " GMT ====\n" ..
318 "[skip] means that the test hasn't been written yet.\n\n") 161 "[skip] means that the test hasn't been written yet.\n\n")
319 for k, v in orderedPairs(mirrors) do 162 for k, v in APT.orderedPairs(APT.mirrors) do
320 local results = loadfile("results/" .. k .. ".lua")() 163 local results = loadfile("results/" .. k .. ".lua")()
321 email:write(k .. "....\n") 164 email:write(k .. "....\n")
322 local IPs = v.IPs 165 local IPs = v.IPs
323 for i, u in pairs(IPs) do 166 for i, u in pairs(IPs) do
324 if "table" == type(u) then 167 if "table" == type(u) then
325 for h, t in pairs(u) do 168 for h, t in pairs(u) do
326 results = collate(k, h, results) 169 results = APT.collate(k, h, results)
327 end 170 end
328 else 171 else
329 results = collate(k, i, results) 172 results = APT.collate(k, i, results)
330 end 173 end
331 end 174 end
332 local ftp = "[skip]" 175 local ftp = "[skip]"
@@ -340,11 +183,11 @@ if nil == email then C("opening mirrors file - " .. e) else
340 local updated = status(k, results, "Updated") 183 local updated = status(k, results, "Updated")
341 184
342 -- DNS-RR test. 185 -- DNS-RR test.
343 if ("deb.devuan.org" ~= k) and (nil ~= mirrors["deb.devuan.org"]) then 186 if ("deb.devuan.org" ~= k) and (nil ~= APT.mirrors["deb.devuan.org"]) then
344 for l, w in pairs(mirrors[k].IPs) do 187 for l, w in pairs(APT.mirrors[k].IPs) do
345 if type(w) == "table" then 188 if type(w) == "table" then
346 for i, u in pairs(w) do 189 for i, u in pairs(w) do
347 if nil ~= mirrors["deb.devuan.org"].IPs["deb.roundr.devuan.org"][i] then 190 if nil ~= APT.mirrors["deb.devuan.org"].IPs["deb.roundr.devuan.org"][i] then
348 local log = logCount("deb.devuan.org", i) 191 local log = logCount("deb.devuan.org", i)
349 if "" ~= log then 192 if "" ~= log then
350 if "" == dns then dns = " " else dns = dns .. " " end 193 if "" == dns then dns = " " else dns = dns .. " " end
@@ -356,7 +199,7 @@ if nil == email then C("opening mirrors file - " .. e) else
356 end 199 end
357 end 200 end
358 else 201 else
359 if nil ~= mirrors["deb.devuan.org"].IPs["deb.roundr.devuan.org"][l] then 202 if nil ~= APT.mirrors["deb.devuan.org"].IPs["deb.roundr.devuan.org"][l] then
360 local log = logCount("deb.devuan.org", l) 203 local log = logCount("deb.devuan.org", l)
361 if "" ~= log then 204 if "" ~= log then
362 if "" == dns then dns = " " else dns = dns .. " " end 205 if "" == dns then dns = " " else dns = dns .. " " end
@@ -391,7 +234,7 @@ end
391results = {} 234results = {}
392m = {} 235m = {}
393faulty = "" 236faulty = ""
394html = true 237APT.html = true
395local web, e = io.open("results/Report-web.html", "w+") 238local web, e = io.open("results/Report-web.html", "w+")
396if nil == web then C("opening mirrors file - " .. e) else 239if nil == web then C("opening mirrors file - " .. e) else
397 web:write( "<html><head><title>apt-panopticon results</title>\n" .. 240 web:write( "<html><head><title>apt-panopticon results</title>\n" ..
@@ -420,7 +263,7 @@ if nil == web then C("opening mirrors file - " .. e) else
420 "<table>\n<tr><th></th><th>FTP</th><th>HTTP</th><th>HTTPS</th><th>RSYNC</th><th>DNS round robin</th>" .. 263 "<table>\n<tr><th></th><th>FTP</th><th>HTTP</th><th>HTTPS</th><th>RSYNC</th><th>DNS round robin</th>" ..
421 "<th>Protocol</th><th>URL sanity</th><th>Integrity</th><th>Updated</th><th colspan='2'>Speed range</th></tr>\n" 264 "<th>Protocol</th><th>URL sanity</th><th>Integrity</th><th>Updated</th><th colspan='2'>Speed range</th></tr>\n"
422 ) 265 )
423 for k, v in orderedPairs(mirrors) do 266 for k, v in APT.orderedPairs(APT.mirrors) do
424 local results = loadfile("results/" .. k .. ".lua")() 267 local results = loadfile("results/" .. k .. ".lua")()
425 local active = "" 268 local active = ""
426 if "yes" == v.Active then 269 if "yes" == v.Active then
@@ -433,10 +276,10 @@ if nil == web then C("opening mirrors file - " .. e) else
433 for i, u in pairs(IPs) do 276 for i, u in pairs(IPs) do
434 if "table" == type(u) then 277 if "table" == type(u) then
435 for h, t in pairs(u) do 278 for h, t in pairs(u) do
436 results = collate(k, h, results) 279 results = APT.collate(k, h, results)
437 end 280 end
438 else 281 else
439 results = collate(k, i, results) 282 results = APT.collate(k, i, results)
440 end 283 end
441 end 284 end
442 local ftp = "[<font color='grey'><b>skip</b></font>]" 285 local ftp = "[<font color='grey'><b>skip</b></font>]"
@@ -455,11 +298,11 @@ if nil == web then C("opening mirrors file - " .. e) else
455 local spd = '' 298 local spd = ''
456 299
457 -- DNS-RR test. 300 -- DNS-RR test.
458 if ("deb.devuan.org" ~= k) and (nil ~= mirrors["deb.devuan.org"]) then 301 if ("deb.devuan.org" ~= k) and (nil ~= APT.mirrors["deb.devuan.org"]) then
459 for l, w in pairs(mirrors[k].IPs) do 302 for l, w in pairs(APT.mirrors[k].IPs) do
460 if type(w) == "table" then 303 if type(w) == "table" then
461 for i, u in pairs(w) do 304 for i, u in pairs(w) do
462 if nil ~= mirrors["deb.devuan.org"].IPs["deb.roundr.devuan.org"][i] then 305 if nil ~= APT.mirrors["deb.devuan.org"].IPs["deb.roundr.devuan.org"][i] then
463 local log = logCount("deb.devuan.org", i) 306 local log = logCount("deb.devuan.org", i)
464 if "" ~= log then 307 if "" ~= log then
465 if "" == dns then dns = " " else dns = dns .. " &nbsp; " end 308 if "" == dns then dns = " " else dns = dns .. " &nbsp; " end
@@ -471,7 +314,7 @@ if nil == web then C("opening mirrors file - " .. e) else
471 end 314 end
472 end 315 end
473 else 316 else
474 if nil ~= mirrors["deb.devuan.org"].IPs["deb.roundr.devuan.org"][l] then 317 if nil ~= APT.mirrors["deb.devuan.org"].IPs["deb.roundr.devuan.org"][l] then
475 local log = logCount("deb.devuan.org", l) 318 local log = logCount("deb.devuan.org", l)
476 if "" ~= log then 319 if "" ~= log then
477 if "" == dns then dns = " " else dns = dns .. " &nbsp; " end 320 if "" == dns then dns = " " else dns = dns .. " &nbsp; " end
@@ -502,18 +345,18 @@ if nil == web then C("opening mirrors file - " .. e) else
502 web:write( "</table>\n<br>\n<h2>==== faulty mirrors: ====</h2>\n" .. faulty) 345 web:write( "</table>\n<br>\n<h2>==== faulty mirrors: ====</h2>\n" .. faulty)
503 web:write( "<br>\n<br>\n<h2>==== DNS and logs: ====</h2>\n") 346 web:write( "<br>\n<br>\n<h2>==== DNS and logs: ====</h2>\n")
504 347
505 for k, v in pairs(mirrors) do 348 for k, v in pairs(APT.mirrors) do
506 local log = k 349 local log = k
507 local n = {} 350 local n = {}
508 log = logCount(k) 351 log = logCount(k)
509 mirrors[k].Protocols = nil 352 APT.mirrors[k].Protocols = nil
510 mirrors[k].FQDN = nil 353 APT.mirrors[k].FQDN = nil
511 mirrors[k].Active = nil 354 APT.mirrors[k].Active = nil
512 mirrors[k].Rate = nil 355 APT.mirrors[k].Rate = nil
513 mirrors[k].BaseURL = nil 356 APT.mirrors[k].BaseURL = nil
514 mirrors[k].Country = nil 357 APT.mirrors[k].Country = nil
515 mirrors[k].Bandwidth = nil 358 APT.mirrors[k].Bandwidth = nil
516 for l, w in pairs(mirrors[k].IPs) do 359 for l, w in pairs(APT.mirrors[k].IPs) do
517 if type(w) == "table" then 360 if type(w) == "table" then
518 n[l] = {} 361 n[l] = {}
519 for i, u in pairs(w) do 362 for i, u in pairs(w) do
@@ -535,11 +378,12 @@ if nil == web then C("opening mirrors file - " .. e) else
535 "pkgmaster.devuan.org is the master mirror, all the others sync to it. &nbsp; " .. 378 "pkgmaster.devuan.org is the master mirror, all the others sync to it. &nbsp; " ..
536 "</p>\n" 379 "</p>\n"
537 ) 380 )
538 web:write(dumpTableHTML(m, "", ""))
539 web:write( "\n<br>\n<hr>\n\n" .. 381 web:write( "\n<br>\n<hr>\n\n" ..
382 web:write(APT.dumpTableHTML(m, "", ""))
540 "<p>The <a href='Report-email.txt'>email report</a>. &nbsp; " .. 383 "<p>The <a href='Report-email.txt'>email report</a>. &nbsp; " ..
541 "All <a href='../results'>the logs and other output</a>. &nbsp; " .. 384 "All <a href='../results'>the logs and other output</a>. &nbsp; " ..
542 "You can get the <a href='https://sledjhamr.org/cgit/apt-panopticon/about/'>source code here</a>.</p>" .. 385 "You can get the <a href='https://sledjhamr.org/cgit/apt-panopticon/about/'>source code here</a>.</p>" ..
543 "</body></html>\n") 386 "</body></html>\n")
544 web:close() 387 web:close()
545end 388end
389