From 269c7df40a5b0a3313a68796cdfd142753a80f1d Mon Sep 17 00:00:00 2001 From: Luke Granger-Brown Date: Sun, 6 Oct 2024 19:35:35 +0100 Subject: [PATCH] feat: allow configuring settings This allows setting a settings attrset in the module, which will then change that setting to the specified value. This is particularly useful for e.g. the `entryPage` setting, which you can then make set to a particular value. There's an escape hatch for string-valued secrets which live in the settings, like the Steam API key: string-valued settings can be specified by using the __FILE suffix on the setting name (e.g. steamAPIKey__FILE) and then specifying the path to a file instead. The content of that file will be used as the setting instead. --- nixos/module.nix | 4 ++++ stateless_uptime_kuma/tree_gen.py | 14 +++++++++++++- stateless_uptime_kuma/uptime_kuma.py | 29 ++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/nixos/module.nix b/nixos/module.nix index f83fa4d..efc0436 100644 --- a/nixos/module.nix +++ b/nixos/module.nix @@ -52,6 +52,10 @@ in type = with lib.types; attrsOf probesFormat.type; default = { }; }; + settings = lib.mkOption { + type = with lib.types; probesFormat.type; + default = { }; + }; }; }; config = { diff --git a/stateless_uptime_kuma/tree_gen.py b/stateless_uptime_kuma/tree_gen.py index b32ec98..a00ade3 100644 --- a/stateless_uptime_kuma/tree_gen.py +++ b/stateless_uptime_kuma/tree_gen.py @@ -5,7 +5,7 @@ Classes to generate the item tree from json spec import logging import sys -from .uptime_kuma import Monitor, Notification, StatusPage, Tag # type: ignore +from .uptime_kuma import Monitor, Notification, Settings, StatusPage, Tag # type: ignore logger = logging.getLogger(__name__) @@ -59,10 +59,22 @@ def from_dict(api, tree, autocreate_tags=True): monitorList.append(indexed_monitors[monitor]) group["monitorList"] = monitorList indexed_status_pages[slug] = StatusPage(api, slug, **kwargs) + settings = [] + if "settings" in tree: + parsed_settings = {} + for k, v in tree["settings"].items(): + if k.endswith("__FILE"): + with open(v, "rt") as f: + parsed_settings[k[:-len("__FILE")]] = f.read().strip() + else: + parsed_settings[k] = v + settings = [Settings(api, **parsed_settings)] + return { "monitors": indexed_monitors.values(), "tags": indexed_tags.values(), "notifications": indexed_notifications.values(), "status_pages": indexed_status_pages.values(), + "settings": settings, } diff --git a/stateless_uptime_kuma/uptime_kuma.py b/stateless_uptime_kuma/uptime_kuma.py index 10f1f0f..7208ba3 100644 --- a/stateless_uptime_kuma/uptime_kuma.py +++ b/stateless_uptime_kuma/uptime_kuma.py @@ -19,6 +19,7 @@ class Manager: self.sync_notifications() self.sync_monitors() self.sync_status_pages() + self.sync_settings() self.save() def save(self): @@ -46,6 +47,17 @@ class Manager: new = self.target_tree.get("status_pages", []) self.sync(new, old, "slug") + def sync_settings(self): + if "settings" not in self.target_tree: + return + old = self.api.get_settings() + new = self.target_tree["settings"][0] + # We need all of the arguments; settings are saved all at once. + # We take any settings that are not explicitly set back from the server. + for k, v in old.items(): + if k not in new.kwargs: + new.kwargs[k] = v + def sync(self, new, old, pk): indexed_old = {elem[pk]: elem for elem in old} for k in new: @@ -235,3 +247,20 @@ class StatusPage(Item): def __repr__(self): return f"StatusPage({str(self)})" + + +class Settings(Item): + def __init__(self, api, **kwargs): + super().__init__(api, "settings", None, None) + self.kwargs = kwargs + + def save(self): + if self.saved: + return + logger.debug(f"Saving {repr(self)}") + self.api.set_settings(**self.kwargs) + self.saved = True + + def __repr__(self): + return f"Settings({str(self.kwargs)})" +