Files
kiauh/kiauh/components/webui_client/client_utils.py
dw-0 ac0478b062 refactor: more robust type hinting
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-05-19 18:41:29 +02:00

231 lines
7.9 KiB
Python

# ======================================================================= #
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
# #
# This file is part of KIAUH - Klipper Installation And Update Helper #
# https://github.com/dw-0/kiauh #
# #
# This file may be distributed under the terms of the GNU GPLv3 license #
# ======================================================================= #
import json # noqa: I001
import shutil
from pathlib import Path
from typing import List, get_args
from components.klipper.klipper import Klipper
from components.webui_client.base_data import (
BaseWebClient,
BaseWebClientConfig,
WebClientType,
)
from components.webui_client.mainsail_data import MainsailData
from core.backup_manager.backup_manager import BackupManager
from core.settings.kiauh_settings import KiauhSettings
from utils import NGINX_CONFD, NGINX_SITES_AVAILABLE
from utils.common import get_install_status
from utils.constants import COLOR_CYAN, COLOR_YELLOW, RESET_FORMAT
from utils.git_utils import (
get_latest_tag,
get_latest_unstable_tag,
)
from utils.logger import Logger
from utils.types import ComponentStatus, InstallStatus
def get_client_status(
client: BaseWebClient, fetch_remote: bool = False
) -> ComponentStatus:
files = [
NGINX_SITES_AVAILABLE.joinpath(client.name),
NGINX_CONFD.joinpath("upstreams.conf"),
NGINX_CONFD.joinpath("common_vars.conf"),
]
status = get_install_status(client.client_dir, files=files)
# if the client dir does not exist, set the status to not
# installed even if the other files are present
if not client.client_dir.exists():
status["status"] = InstallStatus.NOT_INSTALLED
status["local"] = get_local_client_version(client)
status["remote"] = get_remote_client_version(client) if fetch_remote else None
return status
def get_client_config_status(client: BaseWebClient) -> ComponentStatus:
return get_install_status(client.client_config.config_dir)
def get_current_client_config(clients: List[BaseWebClient]) -> str:
installed = []
for client in clients:
client_config = client.client_config
if client_config.config_dir.exists():
installed.append(client)
if len(installed) > 1:
return f"{COLOR_YELLOW}Conflict!{RESET_FORMAT}"
elif len(installed) == 1:
cfg = installed[0].client_config
return f"{COLOR_CYAN}{cfg.display_name}{RESET_FORMAT}"
return f"{COLOR_CYAN}-{RESET_FORMAT}"
def backup_mainsail_config_json(is_temp=False) -> None:
c_json = MainsailData().client_dir.joinpath("config.json")
Logger.print_status(f"Backup '{c_json}' ...")
bm = BackupManager()
if is_temp:
fn = Path.home().joinpath("config.json.kiauh.bak")
bm.backup_file(c_json, custom_filename=fn)
else:
bm.backup_file(c_json)
def restore_mainsail_config_json() -> None:
try:
c_json = MainsailData().client_dir.joinpath("config.json")
Logger.print_status(f"Restore '{c_json}' ...")
source = Path.home().joinpath("config.json.kiauh.bak")
shutil.copy(source, c_json)
except OSError:
Logger.print_info("Unable to restore config.json. Skipped ...")
def enable_mainsail_remotemode() -> None:
Logger.print_status("Enable Mainsails remote mode ...")
c_json = MainsailData().client_dir.joinpath("config.json")
with open(c_json, "r") as f:
config_data = json.load(f)
if config_data["instancesDB"] == "browser":
Logger.print_info("Remote mode already configured. Skipped ...")
return
Logger.print_status("Setting instance storage location to 'browser' ...")
config_data["instancesDB"] = "browser"
with open(c_json, "w") as f:
json.dump(config_data, f, indent=4)
Logger.print_ok("Mainsails remote mode enabled!")
def symlink_webui_nginx_log(klipper_instances: List[Klipper]) -> None:
Logger.print_status("Link NGINX logs into log directory ...")
access_log = Path("/var/log/nginx/mainsail-access.log")
error_log = Path("/var/log/nginx/mainsail-error.log")
for instance in klipper_instances:
desti_access = instance.log_dir.joinpath("mainsail-access.log")
if not desti_access.exists():
desti_access.symlink_to(access_log)
desti_error = instance.log_dir.joinpath("mainsail-error.log")
if not desti_error.exists():
desti_error.symlink_to(error_log)
def get_local_client_version(client: BaseWebClient) -> str:
relinfo_file = client.client_dir.joinpath("release_info.json")
version_file = client.client_dir.joinpath(".version")
if not client.client_dir.exists():
return "-"
if not relinfo_file.is_file() and not version_file.is_file():
return "n/a"
if relinfo_file.is_file():
with open(relinfo_file, "r") as f:
return json.load(f)["version"]
else:
with open(version_file, "r") as f:
return f.readlines()[0]
def get_remote_client_version(client: BaseWebClient) -> str:
try:
if (tag := get_latest_tag(client.repo_path)) != "":
return tag
return "ERROR"
except Exception:
return "ERROR"
def backup_client_data(client: BaseWebClient) -> None:
name = client.name
src = client.client_dir
dest = client.backup_dir
with open(src.joinpath(".version"), "r") as v:
version = v.readlines()[0]
bm = BackupManager()
bm.backup_directory(f"{name}-{version}", src, dest)
if name == "mainsail":
c_json = MainsailData().client_dir.joinpath("config.json")
bm.backup_file(c_json, dest)
bm.backup_file(NGINX_SITES_AVAILABLE.joinpath(name), dest)
def backup_client_config_data(client: BaseWebClient) -> None:
client_config = client.client_config
name = client_config.name
source = client_config.config_dir
target = client_config.backup_dir
bm = BackupManager()
bm.backup_directory(name, source, target)
def get_existing_clients() -> List[BaseWebClient]:
clients = list(get_args(WebClientType))
installed_clients: List[BaseWebClient] = []
for client in clients:
if client.client_dir.exists():
installed_clients.append(client)
return installed_clients
def get_existing_client_config() -> List[BaseWebClient]:
clients = list(get_args(WebClientType))
installed_client_configs: List[BaseWebClient] = []
for client in clients:
c_config_data: BaseWebClientConfig = client.client_config
if c_config_data.config_dir.exists():
installed_client_configs.append(client)
return installed_client_configs
def config_for_other_client_exist(client_to_ignore: WebClientType) -> bool:
"""
Check if any other client configs are present on the system.
It is usually not harmful, but chances are they can conflict each other.
Multiple client configs are, at least, redundant to have them installed
:param client_to_ignore: The client name to ignore for the check
:return: True, if other client configs were found, else False
"""
clients = set([c.name for c in get_existing_client_config()])
clients = clients - {client_to_ignore.value}
return True if len(clients) > 0 else False
def get_download_url(base_url: str, client: BaseWebClient) -> str:
settings = KiauhSettings()
use_unstable = settings.get(client.name, "unstable_releases")
stable_url = f"{base_url}/latest/download/{client.name}.zip"
if not use_unstable:
return stable_url
try:
unstable_tag = get_latest_unstable_tag(client.repo_path)
if unstable_tag == "":
raise Exception
return f"{base_url}/download/{unstable_tag}/{client.name}.zip"
except Exception:
return stable_url