From fbb01a5f5862aa29009d479c495e02f45ba845f2 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 10 Nov 2020 13:10:11 +0000 Subject: [PATCH] mod_update_check, mod_update_notify: Split into multiple modules and finish implementation (see also mod_admin_notify upstream) --- .../mod_update_check/mod_update_check.lua | 47 +++---- .../mod_update_notify/mod_update_notify.lua | 116 ++++++++++++++++++ 2 files changed, 131 insertions(+), 32 deletions(-) create mode 100644 snikket-modules/mod_update_notify/mod_update_notify.lua diff --git a/snikket-modules/mod_update_check/mod_update_check.lua b/snikket-modules/mod_update_check/mod_update_check.lua index 719cfe9..74252dd 100644 --- a/snikket-modules/mod_update_check/mod_update_check.lua +++ b/snikket-modules/mod_update_check/mod_update_check.lua @@ -20,45 +20,28 @@ do end function check_for_updates() + local record_name = render_hostname(update_dns, version_info); + module:log("debug", "Checking for updates on %s...", record_name); r:lookup(function (records) + if not records or #records == 0 then + module:log("warn", "Update check failed"); + return; + end local result = {}; for _, record in ipairs(records) do - local key, val = record.txt:match("(%S+)=(%S+)"); - if key then - result[key] = val; + if record.txt then + local key, val = record.txt:match("(%S+)=(%S+)"); + if key then + result[key] = val; + end end end - module:fire_event("update-check/result", { result = result }); - end, render_hostname(update_dns, version_info), "TXT", "IN"); + module:log("debug", "Finished checking for updates"); + module:fire_event("update-check/result", { current = version_info, latest = result }); + end, record_name, "TXT", "IN"); return check_interval; end function module.load() - module:add_timer(300, check_for_updates); + module:add_timer(5, check_for_updates); end - -module:hook("update-check/result", function (event) - local ver_secure = tonumber(event.result.secure); - local ver_latest = tonumber(event.result.latest); - local ver_installed = tonumber(version_info.level); - - if not ver_installed then - module:log_status("warn", "Unable to determine local version number"); - return; - end - - if ver_secure and ver_installed < ver_secure then - module:log_status("warn", "Security update available!"); - return; - end - - if ver_latest and ver_installed < ver_latest then - module:log_status("info", "Update available!"); - return; - end - - if event.result.support_status == "unsupported" then - module:log_status("warn", "%s is no longer supported", version_info.branch); - return; - end -end); diff --git a/snikket-modules/mod_update_notify/mod_update_notify.lua b/snikket-modules/mod_update_notify/mod_update_notify.lua new file mode 100644 index 0000000..f5c9fa4 --- /dev/null +++ b/snikket-modules/mod_update_notify/mod_update_notify.lua @@ -0,0 +1,116 @@ +local urlencode = require "util.http".urlencode; +local interpolation = require "util.interpolation"; + +local render_url = interpolation.new("%b{}", urlencode); +local render_text = interpolation.new("%b{}", function (s) return s; end); + +local security_notification = [[There is an important security release available +for {software}. The latest secure version is {current.branch}.{latest.secure}. +You are currently running {software} {current.branch}.{current.level}. + + +For more information please see: {url} +]]; + +local version_notification = [[There is a new {software} release available. You are +currently running {software} {current.branch}.{current.level}, and an upgrade to +{current.branch}.{latest.latest} is now available. + +For more information please see: {url} +]]; + +local message_notification = [[There is a new announcement related to {software}, for more +information please see: {url} +]]; + +local support_notification = [[This version of {software} is no longer supported. For +more information please see: {url} +]] + +local software_name = module:get_option_string("software_name"); +local version_url = module:get_option_string("update_notify_version_url"); +local support_url = module:get_option_string("update_notify_support_url"); +local message_url = module:get_option_string("update_notify_message_url"); + +if not (software_name and version_url and support_url and message_url) then + return error("Requires software name, version, support and message URLs to be set"); +end + +local admin_notify = module:depends("admin_notify").notify; + +local notified_store = module:open_store("update_notifications", "map"); + +local function have_notified(branch, field, value) + local notified_value = notified_store:get(branch, field); + if notified_value then + if type(value) == "number" and notified_value >= value then + return true; + elseif notified_value == value then + return true; + end + end + + notified_store:set(branch, field, value); + return false; +end + +module:hook("update-check/result", function (event) + local branch = event.current.branch; + local ver_secure = tonumber(event.latest.secure); + local ver_latest = tonumber(event.latest.latest); + local ver_installed = tonumber(event.current.level); + local msg_latest = tonumber(event.latest.msg); + + if not ver_installed then + module:log_status("error", "Unable to determine local version number"); + return; + end + + if ver_secure and ver_installed < ver_secure + and not have_notified(branch, "secure", ver_secure) then + module:log_status("warn", "Security update available!"); + admin_notify(render_text(security_notification, { + software = software_name; + current = event.current; + latest = event.latest; + url = render_url(version_url, { branch = branch, version = event.latest.secure }); + })); + return; + end + + if ver_latest and ver_installed < ver_latest + and not have_notified(branch, "latest", ver_latest) then + module:log_status("info", "Update available!"); + admin_notify(render_text(version_notification, { + software = software_name; + current = event.current; + latest = event.latest; + url = render_url(version_url, { branch = branch, version = event.latest.latest }); + })); + return; + end + + if msg_latest and not have_notified(branch, "msg", msg_latest) then + module:log_status("info", "New announcement"); + admin_notify(render_text(message_notification, { + software = software_name; + current = event.current; + latest = event.latest; + url = render_url(message_url, { branch = branch, message = msg_latest }); + })); + return; + end + + if not have_notified(branch, "support_status", event.latest.support_status) then + if event.latest.support_status == "unsupported" then + module:log_status("warn", "%s is no longer supported", branch); + admin_notify(render_text(support_notification, { + software = software_name; + current = event.current; + latest = event.latest; + url = render_url(support_url, { branch = branch }); + })); + return; + end + end +end);