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.
This commit is contained in:
Luke Granger-Brown 2024-10-06 19:35:35 +01:00
parent 390363e6a9
commit 269c7df40a
3 changed files with 46 additions and 1 deletions

View file

@ -52,6 +52,10 @@ in
type = with lib.types; attrsOf probesFormat.type;
default = { };
};
settings = lib.mkOption {
type = with lib.types; probesFormat.type;
default = { };
};
};
};
config = {

View file

@ -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,
}

View file

@ -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)})"