refactor: full refactor of how webclient data is handled
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
This commit is contained in:
@@ -30,7 +30,7 @@ from components.klipper.klipper_dialogs import (
|
|||||||
)
|
)
|
||||||
from components.moonraker.moonraker import Moonraker
|
from components.moonraker.moonraker import Moonraker
|
||||||
from components.moonraker.moonraker_utils import moonraker_to_multi_conversion
|
from components.moonraker.moonraker_utils import moonraker_to_multi_conversion
|
||||||
from components.webui_client import ClientData
|
from components.webui_client.base_data import BaseWebClient
|
||||||
from components.webui_client.client_config.client_config_setup import (
|
from components.webui_client.client_config.client_config_setup import (
|
||||||
create_client_config_symlink,
|
create_client_config_symlink,
|
||||||
)
|
)
|
||||||
@@ -288,7 +288,7 @@ def get_highest_index(instance_list: List[Klipper]) -> int:
|
|||||||
|
|
||||||
|
|
||||||
def create_example_printer_cfg(
|
def create_example_printer_cfg(
|
||||||
instance: Klipper, clients: Optional[List[ClientData]] = None
|
instance: Klipper, clients: Optional[List[BaseWebClient]] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
Logger.print_status(f"Creating example printer.cfg in '{instance.cfg_dir}'")
|
Logger.print_status(f"Creating example printer.cfg in '{instance.cfg_dir}'")
|
||||||
if instance.cfg_file.is_file():
|
if instance.cfg_file.is_file():
|
||||||
@@ -309,8 +309,8 @@ def create_example_printer_cfg(
|
|||||||
# include existing client configs in the example config
|
# include existing client configs in the example config
|
||||||
if clients is not None and len(clients) > 0:
|
if clients is not None and len(clients) > 0:
|
||||||
for c in clients:
|
for c in clients:
|
||||||
client_config = c.get("client_config")
|
client_config = c.client_config
|
||||||
section = client_config.get("printer_cfg_section")
|
section = client_config.config_section
|
||||||
cm.config.add_section(section=section)
|
cm.config.add_section(section=section)
|
||||||
create_client_config_symlink(client_config, [instance])
|
create_client_config_symlink(client_config, [instance])
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from components.webui_client import MAINSAIL_DIR
|
|
||||||
from components.webui_client.client_utils import (
|
from components.webui_client.client_utils import (
|
||||||
enable_mainsail_remotemode,
|
enable_mainsail_remotemode,
|
||||||
get_existing_clients,
|
get_existing_clients,
|
||||||
)
|
)
|
||||||
|
from components.webui_client.mainsail_data import MainsailData
|
||||||
from kiauh import KIAUH_CFG
|
from kiauh import KIAUH_CFG
|
||||||
from components.klipper.klipper import Klipper
|
from components.klipper.klipper import Klipper
|
||||||
from components.moonraker import (
|
from components.moonraker import (
|
||||||
@@ -113,7 +113,7 @@ def install_moonraker() -> None:
|
|||||||
|
|
||||||
# if mainsail is installed, and we installed
|
# if mainsail is installed, and we installed
|
||||||
# multiple moonraker instances, we enable mainsails remote mode
|
# multiple moonraker instances, we enable mainsails remote mode
|
||||||
if MAINSAIL_DIR.exists() and len(mr_im.instances) > 1:
|
if MainsailData().client_dir.exists() and len(mr_im.instances) > 1:
|
||||||
enable_mainsail_remotemode()
|
enable_mainsail_remotemode()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,9 @@ from components.moonraker import (
|
|||||||
MOONRAKER_DB_BACKUP_DIR,
|
MOONRAKER_DB_BACKUP_DIR,
|
||||||
)
|
)
|
||||||
from components.moonraker.moonraker import Moonraker
|
from components.moonraker.moonraker import Moonraker
|
||||||
from components.webui_client import MAINSAIL_DIR, ClientData
|
from components.webui_client.base_data import BaseWebClient
|
||||||
from components.webui_client.client_utils import enable_mainsail_remotemode
|
from components.webui_client.client_utils import enable_mainsail_remotemode
|
||||||
|
from components.webui_client.mainsail_data import MainsailData
|
||||||
from core.backup_manager.backup_manager import BackupManager
|
from core.backup_manager.backup_manager import BackupManager
|
||||||
from core.config_manager.config_manager import ConfigManager
|
from core.config_manager.config_manager import ConfigManager
|
||||||
from core.instance_manager.instance_manager import InstanceManager
|
from core.instance_manager.instance_manager import InstanceManager
|
||||||
@@ -52,7 +53,7 @@ def get_moonraker_status() -> (
|
|||||||
def create_example_moonraker_conf(
|
def create_example_moonraker_conf(
|
||||||
instance: Moonraker,
|
instance: Moonraker,
|
||||||
ports_map: Dict[str, int],
|
ports_map: Dict[str, int],
|
||||||
clients: Optional[List[ClientData]] = None,
|
clients: Optional[List[BaseWebClient]] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
Logger.print_status(f"Creating example moonraker.conf in '{instance.cfg_dir}'")
|
Logger.print_status(f"Creating example moonraker.conf in '{instance.cfg_dir}'")
|
||||||
if instance.cfg_file.is_file():
|
if instance.cfg_file.is_file():
|
||||||
@@ -100,26 +101,26 @@ def create_example_moonraker_conf(
|
|||||||
if clients is not None and len(clients) > 0:
|
if clients is not None and len(clients) > 0:
|
||||||
for c in clients:
|
for c in clients:
|
||||||
# client part
|
# client part
|
||||||
c_section = f"update_manager {c.get('name')}"
|
c_section = f"update_manager {c.name}"
|
||||||
c_options = [
|
c_options = [
|
||||||
("type", "web"),
|
("type", "web"),
|
||||||
("channel", "stable"),
|
("channel", "stable"),
|
||||||
("repo", c.get("mr_conf_repo")),
|
("repo", c.repo_path),
|
||||||
("path", c.get("mr_conf_path")),
|
("path", c.client_dir),
|
||||||
]
|
]
|
||||||
cm.config.add_section(section=c_section)
|
cm.config.add_section(section=c_section)
|
||||||
for option in c_options:
|
for option in c_options:
|
||||||
cm.config.set(c_section, option[0], option[1])
|
cm.config.set(c_section, option[0], option[1])
|
||||||
|
|
||||||
# client config part
|
# client config part
|
||||||
c_config = c.get("client_config")
|
c_config = c.client_config
|
||||||
if c_config.get("dir").exists():
|
if c_config.config_dir.exists():
|
||||||
c_config_section = f"update_manager {c_config.get('name')}"
|
c_config_section = f"update_manager {c_config.name}"
|
||||||
c_config_options = [
|
c_config_options = [
|
||||||
("type", "git_repo"),
|
("type", "git_repo"),
|
||||||
("primary_branch", "master"),
|
("primary_branch", "master"),
|
||||||
("path", c_config.get("mr_conf_path")),
|
("path", c_config.config_dir),
|
||||||
("origin", c_config.get("mr_conf_origin")),
|
("origin", c_config.repo_url),
|
||||||
("managed_services", "klipper"),
|
("managed_services", "klipper"),
|
||||||
]
|
]
|
||||||
cm.config.add_section(section=c_config_section)
|
cm.config.add_section(section=c_config_section)
|
||||||
@@ -177,7 +178,7 @@ def moonraker_to_multi_conversion(new_name: str) -> None:
|
|||||||
im.start_instance()
|
im.start_instance()
|
||||||
|
|
||||||
# if mainsail is installed, we enable mainsails remote mode
|
# if mainsail is installed, we enable mainsails remote mode
|
||||||
if MAINSAIL_DIR.exists() and len(im.instances) > 1:
|
if MainsailData().client_dir.exists() and len(im.instances) > 1:
|
||||||
enable_mainsail_remotemode()
|
enable_mainsail_remotemode()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
# ======================================================================= #
|
|
||||||
# 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 #
|
|
||||||
# ======================================================================= #
|
|
||||||
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import Literal, TypedDict
|
|
||||||
|
|
||||||
from core.backup_manager import BACKUP_ROOT_DIR
|
|
||||||
|
|
||||||
MODULE_PATH = Path(__file__).resolve().parent
|
|
||||||
|
|
||||||
###########
|
|
||||||
# MAINSAIL
|
|
||||||
###########
|
|
||||||
MAINSAIL_DIR = Path.home().joinpath("mainsail")
|
|
||||||
MAINSAIL_BACKUP_DIR = BACKUP_ROOT_DIR.joinpath("mainsail-backups")
|
|
||||||
MAINSAIL_CONFIG_DIR = Path.home().joinpath("mainsail-config")
|
|
||||||
MAINSAIL_CONFIG_BACKUP_DIR = BACKUP_ROOT_DIR.joinpath("mainsail-config-backups")
|
|
||||||
MAINSAIL_CONFIG_REPO_URL = "https://github.com/mainsail-crew/mainsail-config.git"
|
|
||||||
MAINSAIL_CONFIG_JSON = MAINSAIL_DIR.joinpath("config.json")
|
|
||||||
MAINSAIL_URL = (
|
|
||||||
"https://github.com/mainsail-crew/mainsail/releases/latest/download/mainsail.zip"
|
|
||||||
)
|
|
||||||
MAINSAIL_PRE_RLS_URL = (
|
|
||||||
"https://github.com/mainsail-crew/mainsail/releases/download/%TAG%/mainsail.zip"
|
|
||||||
)
|
|
||||||
MAINSAIL_TAGS_URL = "https://api.github.com/repos/mainsail-crew/mainsail/tags"
|
|
||||||
|
|
||||||
#########
|
|
||||||
# FLUIDD
|
|
||||||
#########
|
|
||||||
FLUIDD_DIR = Path.home().joinpath("fluidd")
|
|
||||||
FLUIDD_BACKUP_DIR = BACKUP_ROOT_DIR.joinpath("fluidd-backups")
|
|
||||||
FLUIDD_CONFIG_DIR = Path.home().joinpath("fluidd-config")
|
|
||||||
FLUIDD_CONFIG_BACKUP_DIR = BACKUP_ROOT_DIR.joinpath("fluidd-config-backups")
|
|
||||||
FLUIDD_CONFIG_REPO_URL = "https://github.com/fluidd-core/fluidd-config.git"
|
|
||||||
FLUIDD_URL = "https://github.com/fluidd-core/fluidd/releases/latest/download/fluidd.zip"
|
|
||||||
FLUIDD_PRE_RLS_URL = (
|
|
||||||
"https://github.com/fluidd-core/fluidd/releases/download/%TAG%/fluidd.zip"
|
|
||||||
)
|
|
||||||
FLUIDD_TAGS_URL = "https://api.github.com/repos/fluidd-core/fluidd/tags"
|
|
||||||
|
|
||||||
ClientName = Literal["mainsail", "fluidd"]
|
|
||||||
ClientConfigName = Literal["mainsail-config", "fluidd-config"]
|
|
||||||
|
|
||||||
|
|
||||||
class ClientData(TypedDict):
|
|
||||||
name: ClientName
|
|
||||||
display_name: str
|
|
||||||
dir: Path
|
|
||||||
backup_dir: Path
|
|
||||||
url: str
|
|
||||||
pre_release_url: str
|
|
||||||
tags_url: str
|
|
||||||
remote_mode: bool # required only for Mainsail
|
|
||||||
mr_conf_repo: str
|
|
||||||
mr_conf_path: str
|
|
||||||
client_config: "ClientConfigData"
|
|
||||||
|
|
||||||
|
|
||||||
class ClientConfigData(TypedDict):
|
|
||||||
name: ClientConfigName
|
|
||||||
display_name: str
|
|
||||||
cfg_filename: str
|
|
||||||
dir: Path
|
|
||||||
backup_dir: Path
|
|
||||||
url: str
|
|
||||||
printer_cfg_section: str
|
|
||||||
mr_conf_path: str
|
|
||||||
mr_conf_origin: str
|
|
||||||
|
|||||||
117
kiauh/components/webui_client/base_data.py
Normal file
117
kiauh/components/webui_client/base_data.py
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
# ======================================================================= #
|
||||||
|
# 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 #
|
||||||
|
# ======================================================================= #
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from enum import Enum
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
class WebClientType(Enum):
|
||||||
|
MAINSAIL: str = "mainsail"
|
||||||
|
FLUIDD: str = "fluidd"
|
||||||
|
|
||||||
|
|
||||||
|
class WebClientConfigType(Enum):
|
||||||
|
MAINSAIL: str = "mainsail-config"
|
||||||
|
FLUIDD: str = "fluidd-config"
|
||||||
|
|
||||||
|
|
||||||
|
class BaseWebClient(ABC):
|
||||||
|
"""Base class for webclient data"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def client(self) -> WebClientType:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def name(self) -> str:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def display_name(self) -> str:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def client_dir(self) -> Path:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def backup_dir(self) -> Path:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def repo_path(self) -> str:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def stable_url(self) -> str:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def unstable_url(self) -> str:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def client_config(self) -> BaseWebClientConfig:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
class BaseWebClientConfig(ABC):
|
||||||
|
"""Base class for webclient config data"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def client_config(self) -> WebClientConfigType:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def name(self) -> str:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def display_name(self) -> str:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def config_filename(self) -> str:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def config_dir(self) -> Path:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def backup_dir(self) -> Path:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def repo_url(self) -> str:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def config_section(self) -> str:
|
||||||
|
raise NotImplementedError
|
||||||
@@ -14,26 +14,26 @@ from typing import List
|
|||||||
|
|
||||||
from components.klipper.klipper import Klipper
|
from components.klipper.klipper import Klipper
|
||||||
from components.moonraker.moonraker import Moonraker
|
from components.moonraker.moonraker import Moonraker
|
||||||
from components.webui_client import ClientConfigData
|
from components.webui_client.base_data import BaseWebClientConfig
|
||||||
from core.instance_manager.instance_manager import InstanceManager
|
from core.instance_manager.instance_manager import InstanceManager
|
||||||
from utils.filesystem_utils import remove_file, remove_config_section
|
from utils.filesystem_utils import remove_file, remove_config_section
|
||||||
from utils.logger import Logger
|
from utils.logger import Logger
|
||||||
|
|
||||||
|
|
||||||
def run_client_config_removal(
|
def run_client_config_removal(
|
||||||
client_config: ClientConfigData,
|
client_config: BaseWebClientConfig,
|
||||||
kl_instances: List[Klipper],
|
kl_instances: List[Klipper],
|
||||||
mr_instances: List[Moonraker],
|
mr_instances: List[Moonraker],
|
||||||
) -> None:
|
) -> None:
|
||||||
remove_client_config_dir(client_config)
|
remove_client_config_dir(client_config)
|
||||||
remove_client_config_symlink(client_config)
|
remove_client_config_symlink(client_config)
|
||||||
remove_config_section(f"update_manager {client_config.get('name')}", mr_instances)
|
remove_config_section(f"update_manager {client_config.name}", mr_instances)
|
||||||
remove_config_section(client_config.get("printer_cfg_section"), kl_instances)
|
remove_config_section(client_config.config_section, kl_instances)
|
||||||
|
|
||||||
|
|
||||||
def remove_client_config_dir(client_config: ClientConfigData) -> None:
|
def remove_client_config_dir(client_config: BaseWebClientConfig) -> None:
|
||||||
Logger.print_status(f"Removing {client_config.get('name')} ...")
|
Logger.print_status(f"Removing {client_config.name} ...")
|
||||||
client_config_dir = client_config.get("dir")
|
client_config_dir = client_config.config_dir
|
||||||
if not client_config_dir.exists():
|
if not client_config_dir.exists():
|
||||||
Logger.print_info(f"'{client_config_dir}' does not exist. Skipping ...")
|
Logger.print_info(f"'{client_config_dir}' does not exist. Skipping ...")
|
||||||
return
|
return
|
||||||
@@ -44,12 +44,12 @@ def remove_client_config_dir(client_config: ClientConfigData) -> None:
|
|||||||
Logger.print_error(f"Unable to delete '{client_config_dir}':\n{e}")
|
Logger.print_error(f"Unable to delete '{client_config_dir}':\n{e}")
|
||||||
|
|
||||||
|
|
||||||
def remove_client_config_symlink(client_config: ClientConfigData) -> None:
|
def remove_client_config_symlink(client_config: BaseWebClientConfig) -> None:
|
||||||
im = InstanceManager(Klipper)
|
im = InstanceManager(Klipper)
|
||||||
instances: List[Klipper] = im.instances
|
instances: List[Klipper] = im.instances
|
||||||
for instance in instances:
|
for instance in instances:
|
||||||
Logger.print_status(f"Removing symlink from '{instance.cfg_dir}' ...")
|
Logger.print_status(f"Removing symlink from '{instance.cfg_dir}' ...")
|
||||||
symlink = instance.cfg_dir.joinpath(client_config.get("cfg_filename"))
|
symlink = instance.cfg_dir.joinpath(client_config.config_filename)
|
||||||
if not symlink.is_symlink():
|
if not symlink.is_symlink():
|
||||||
Logger.print_info(f"'{symlink}' does not exist. Skipping ...")
|
Logger.print_info(f"'{symlink}' does not exist. Skipping ...")
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -12,15 +12,14 @@ import subprocess
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
from components.webui_client.base_data import BaseWebClient, BaseWebClientConfig
|
||||||
from kiauh import KIAUH_CFG
|
from kiauh import KIAUH_CFG
|
||||||
from components.klipper.klipper import Klipper
|
from components.klipper.klipper import Klipper
|
||||||
from components.moonraker.moonraker import Moonraker
|
from components.moonraker.moonraker import Moonraker
|
||||||
from components.webui_client import ClientConfigData, ClientName, ClientData
|
|
||||||
from components.webui_client.client_dialogs import (
|
from components.webui_client.client_dialogs import (
|
||||||
print_client_already_installed_dialog,
|
print_client_already_installed_dialog,
|
||||||
)
|
)
|
||||||
from components.webui_client.client_utils import (
|
from components.webui_client.client_utils import (
|
||||||
load_client_data,
|
|
||||||
backup_client_config_data,
|
backup_client_config_data,
|
||||||
config_for_other_client_exist,
|
config_for_other_client_exist,
|
||||||
)
|
)
|
||||||
@@ -38,19 +37,18 @@ from utils.input_utils import get_confirm
|
|||||||
from utils.logger import Logger
|
from utils.logger import Logger
|
||||||
|
|
||||||
|
|
||||||
def install_client_config(client_name: ClientName) -> None:
|
def install_client_config(client_data: BaseWebClient) -> None:
|
||||||
client: ClientData = load_client_data(client_name)
|
client_config: BaseWebClientConfig = client_data.client_config
|
||||||
client_config: ClientConfigData = client.get("client_config")
|
display_name = client_config.display_name
|
||||||
d_name = client_config.get("display_name")
|
|
||||||
|
|
||||||
if config_for_other_client_exist(client_name):
|
if config_for_other_client_exist(client_data.client):
|
||||||
Logger.print_info("Another Client-Config is already installed! Skipped ...")
|
Logger.print_info("Another Client-Config is already installed! Skipped ...")
|
||||||
return
|
return
|
||||||
|
|
||||||
if client_config.get("dir").exists():
|
if client_config.config_dir.exists():
|
||||||
print_client_already_installed_dialog(d_name)
|
print_client_already_installed_dialog(display_name)
|
||||||
if get_confirm(f"Re-install {d_name}?", allow_go_back=True):
|
if get_confirm(f"Re-install {display_name}?", allow_go_back=True):
|
||||||
shutil.rmtree(client_config.get("dir"))
|
shutil.rmtree(client_config.config_dir)
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -66,69 +64,74 @@ def install_client_config(client_name: ClientName) -> None:
|
|||||||
backup_printer_config_dir()
|
backup_printer_config_dir()
|
||||||
|
|
||||||
add_config_section(
|
add_config_section(
|
||||||
section=f"update_manager {client_config.get('name')}",
|
section=f"update_manager {client_config.name}",
|
||||||
instances=mr_instances,
|
instances=mr_instances,
|
||||||
options=[
|
options=[
|
||||||
("type", "git_repo"),
|
("type", "git_repo"),
|
||||||
("primary_branch", "master"),
|
("primary_branch", "master"),
|
||||||
("path", client_config.get("mr_conf_path")),
|
("path", str(client_config.config_dir)),
|
||||||
("origin", client_config.get("mr_conf_origin")),
|
("origin", str(client_config.repo_url)),
|
||||||
("managed_services", "klipper"),
|
("managed_services", "klipper"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
add_config_section_at_top(
|
add_config_section_at_top(client_config.config_section, kl_instances)
|
||||||
client_config.get("printer_cfg_section"), kl_instances
|
|
||||||
)
|
|
||||||
kl_im.restart_all_instance()
|
kl_im.restart_all_instance()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
Logger.print_error(f"{d_name} installation failed!\n{e}")
|
Logger.print_error(f"{display_name} installation failed!\n{e}")
|
||||||
return
|
return
|
||||||
|
|
||||||
Logger.print_ok(f"{d_name} installation complete!", start="\n")
|
Logger.print_ok(f"{display_name} installation complete!", start="\n")
|
||||||
|
|
||||||
|
|
||||||
def download_client_config(client_config: ClientConfigData) -> None:
|
def download_client_config(client_config: BaseWebClientConfig) -> None:
|
||||||
try:
|
try:
|
||||||
Logger.print_status(f"Downloading {client_config.get('display_name')} ...")
|
Logger.print_status(f"Downloading {client_config.display_name} ...")
|
||||||
rm = RepoManager(
|
rm = RepoManager(
|
||||||
client_config.get("url"), target_dir=str(client_config.get("dir"))
|
client_config.repo_url,
|
||||||
|
target_dir=str(client_config.config_dir),
|
||||||
)
|
)
|
||||||
rm.clone_repo()
|
rm.clone_repo()
|
||||||
except Exception:
|
except Exception:
|
||||||
Logger.print_error(f"Downloading {client_config.get('display_name')} failed!")
|
Logger.print_error(f"Downloading {client_config.display_name} failed!")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
def update_client_config(client: ClientData) -> None:
|
def update_client_config(client: BaseWebClient) -> None:
|
||||||
client_config: ClientConfigData = client.get("client_config")
|
client_config: BaseWebClientConfig = client.client_config
|
||||||
|
|
||||||
Logger.print_status(f"Updating {client_config.get('display_name')} ...")
|
Logger.print_status(f"Updating {client_config.display_name} ...")
|
||||||
|
|
||||||
|
if not client_config.config_dir.exists():
|
||||||
|
Logger.print_info(
|
||||||
|
f"Unable to update {client_config.display_name}. Directory does not exist! Skipping ..."
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
cm = ConfigManager(cfg_file=KIAUH_CFG)
|
cm = ConfigManager(cfg_file=KIAUH_CFG)
|
||||||
if cm.get_value("kiauh", "backup_before_update"):
|
if cm.get_value("kiauh", "backup_before_update"):
|
||||||
backup_client_config_data(client)
|
backup_client_config_data(client)
|
||||||
|
|
||||||
repo_manager = RepoManager(
|
repo_manager = RepoManager(
|
||||||
repo=client_config.get("url"),
|
repo=client_config.repo_url,
|
||||||
branch="master",
|
branch="master",
|
||||||
target_dir=str(client_config.get("dir")),
|
target_dir=str(client_config.config_dir),
|
||||||
)
|
)
|
||||||
repo_manager.pull_repo()
|
repo_manager.pull_repo()
|
||||||
|
|
||||||
Logger.print_ok(f"Successfully updated {client_config.get('display_name')}.")
|
Logger.print_ok(f"Successfully updated {client_config.display_name}.")
|
||||||
Logger.print_warn("Remember to restart Klipper to reload the configurations!")
|
Logger.print_info("Restart Klipper to reload the configuration!")
|
||||||
|
|
||||||
|
|
||||||
def create_client_config_symlink(
|
def create_client_config_symlink(
|
||||||
client_config: ClientConfigData, klipper_instances: List[Klipper] = None
|
client_config: BaseWebClientConfig, klipper_instances: List[Klipper] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
if klipper_instances is None:
|
if klipper_instances is None:
|
||||||
kl_im = InstanceManager(Klipper)
|
kl_im = InstanceManager(Klipper)
|
||||||
klipper_instances = kl_im.instances
|
klipper_instances = kl_im.instances
|
||||||
|
|
||||||
Logger.print_status(f"Create symlink for {client_config.get('cfg_filename')} ...")
|
Logger.print_status(f"Create symlink for {client_config.config_filename} ...")
|
||||||
source = Path(client_config.get("dir"), client_config.get("cfg_filename"))
|
source = Path(client_config.config_dir, client_config.config_filename)
|
||||||
for instance in klipper_instances:
|
for instance in klipper_instances:
|
||||||
target = instance.cfg_dir
|
target = instance.cfg_dir
|
||||||
Logger.print_status(f"Linking {source} to {target}")
|
Logger.print_status(f"Linking {source} to {target}")
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
import textwrap
|
import textwrap
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from components.webui_client import ClientData
|
from components.webui_client.base_data import BaseWebClient
|
||||||
from core.menus.base_menu import print_back_footer
|
from core.menus.base_menu import print_back_footer
|
||||||
from utils.constants import RESET_FORMAT, COLOR_YELLOW, COLOR_CYAN
|
from utils.constants import RESET_FORMAT, COLOR_YELLOW, COLOR_CYAN
|
||||||
|
|
||||||
@@ -84,9 +84,9 @@ def print_client_port_select_dialog(name: str, port: str, ports_in_use: List[str
|
|||||||
print(dialog, end="")
|
print(dialog, end="")
|
||||||
|
|
||||||
|
|
||||||
def print_install_client_config_dialog(client: ClientData):
|
def print_install_client_config_dialog(client: BaseWebClient):
|
||||||
name = client.get("display_name")
|
name = client.display_name
|
||||||
url = client.get("client_config").get("url").replace(".git", "")
|
url = client.client_config.repo_url.replace(".git", "")
|
||||||
line1 = f"have {name} fully functional and working."
|
line1 = f"have {name} fully functional and working."
|
||||||
line2 = f"The recommended macros for {name} can be seen here:"
|
line2 = f"The recommended macros for {name} can be seen here:"
|
||||||
dialog = textwrap.dedent(
|
dialog = textwrap.dedent(
|
||||||
|
|||||||
@@ -13,7 +13,10 @@ from typing import List
|
|||||||
|
|
||||||
from components.klipper.klipper import Klipper
|
from components.klipper.klipper import Klipper
|
||||||
from components.moonraker.moonraker import Moonraker
|
from components.moonraker.moonraker import Moonraker
|
||||||
from components.webui_client import ClientData
|
from components.webui_client.base_data import (
|
||||||
|
BaseWebClient,
|
||||||
|
WebClientType,
|
||||||
|
)
|
||||||
from components.webui_client.client_config.client_config_remove import (
|
from components.webui_client.client_config.client_config_remove import (
|
||||||
run_client_config_removal,
|
run_client_config_removal,
|
||||||
)
|
)
|
||||||
@@ -29,7 +32,7 @@ from utils.logger import Logger
|
|||||||
|
|
||||||
|
|
||||||
def run_client_removal(
|
def run_client_removal(
|
||||||
client: ClientData,
|
client: BaseWebClient,
|
||||||
rm_client: bool,
|
rm_client: bool,
|
||||||
rm_client_config: bool,
|
rm_client_config: bool,
|
||||||
backup_ms_config_json: bool,
|
backup_ms_config_json: bool,
|
||||||
@@ -39,11 +42,11 @@ def run_client_removal(
|
|||||||
kl_im = InstanceManager(Klipper)
|
kl_im = InstanceManager(Klipper)
|
||||||
kl_instances: List[Klipper] = kl_im.instances
|
kl_instances: List[Klipper] = kl_im.instances
|
||||||
|
|
||||||
if backup_ms_config_json and client.get("name") == "mainsail":
|
if backup_ms_config_json and client.client == WebClientType.MAINSAIL:
|
||||||
backup_mainsail_config_json()
|
backup_mainsail_config_json()
|
||||||
|
|
||||||
if rm_client:
|
if rm_client:
|
||||||
client_name = client.get("name")
|
client_name = client.name
|
||||||
remove_client_dir(client)
|
remove_client_dir(client)
|
||||||
remove_nginx_config(client_name)
|
remove_nginx_config(client_name)
|
||||||
remove_nginx_logs(client_name)
|
remove_nginx_logs(client_name)
|
||||||
@@ -53,16 +56,16 @@ def run_client_removal(
|
|||||||
|
|
||||||
if rm_client_config:
|
if rm_client_config:
|
||||||
run_client_config_removal(
|
run_client_config_removal(
|
||||||
client.get("client_config"),
|
client.client_config,
|
||||||
kl_instances,
|
kl_instances,
|
||||||
mr_instances,
|
mr_instances,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def remove_client_dir(client: ClientData) -> None:
|
def remove_client_dir(client: BaseWebClient) -> None:
|
||||||
Logger.print_status(f"Removing {client.get('display_name')} ...")
|
Logger.print_status(f"Removing {client.display_name} ...")
|
||||||
client_dir = client.get("dir")
|
client_dir = client.client_dir
|
||||||
if not client.get("dir").exists():
|
if not client.client_dir.exists():
|
||||||
Logger.print_info(f"'{client_dir}' does not exist. Skipping ...")
|
Logger.print_info(f"'{client_dir}' does not exist. Skipping ...")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -11,12 +11,13 @@ from pathlib import Path
|
|||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from components.klipper.klipper import Klipper
|
from components.klipper.klipper import Klipper
|
||||||
from components.webui_client import (
|
|
||||||
ClientName,
|
|
||||||
ClientData,
|
|
||||||
)
|
|
||||||
|
|
||||||
from components.moonraker.moonraker import Moonraker
|
from components.moonraker.moonraker import Moonraker
|
||||||
|
from components.webui_client.base_data import (
|
||||||
|
WebClientType,
|
||||||
|
BaseWebClient,
|
||||||
|
BaseWebClientConfig,
|
||||||
|
)
|
||||||
from components.webui_client.client_config.client_config_setup import (
|
from components.webui_client.client_config.client_config_setup import (
|
||||||
install_client_config,
|
install_client_config,
|
||||||
)
|
)
|
||||||
@@ -30,7 +31,6 @@ from components.webui_client.client_utils import (
|
|||||||
restore_mainsail_config_json,
|
restore_mainsail_config_json,
|
||||||
enable_mainsail_remotemode,
|
enable_mainsail_remotemode,
|
||||||
symlink_webui_nginx_log,
|
symlink_webui_nginx_log,
|
||||||
load_client_data,
|
|
||||||
config_for_other_client_exist,
|
config_for_other_client_exist,
|
||||||
)
|
)
|
||||||
from core.config_manager.config_manager import ConfigManager
|
from core.config_manager.config_manager import ConfigManager
|
||||||
@@ -60,17 +60,13 @@ from utils.system_utils import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def install_client(client_name: ClientName) -> None:
|
def install_client(client: BaseWebClient) -> None:
|
||||||
client: ClientData = load_client_data(client_name)
|
|
||||||
d_name = client.get("display_name")
|
|
||||||
|
|
||||||
if client is None:
|
if client is None:
|
||||||
Logger.print_error("Missing parameter client_name!")
|
raise ValueError("Missing parameter client_data!")
|
||||||
return
|
|
||||||
|
|
||||||
if client.get("dir").exists():
|
if client.client_dir.exists():
|
||||||
Logger.print_info(
|
Logger.print_info(
|
||||||
f"{client.get('display_name')} seems to be already installed! Skipped ..."
|
f"{client.display_name} seems to be already installed! Skipped ..."
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -81,31 +77,35 @@ def install_client(client_name: ClientName) -> None:
|
|||||||
if not mr_instances:
|
if not mr_instances:
|
||||||
print_moonraker_not_found_dialog()
|
print_moonraker_not_found_dialog()
|
||||||
if not get_confirm(
|
if not get_confirm(
|
||||||
f"Continue {d_name} installation?",
|
f"Continue {client.display_name} installation?",
|
||||||
allow_go_back=True,
|
allow_go_back=True,
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
# if moonraker is not installed or multiple instances
|
# if moonraker is not installed or multiple instances
|
||||||
# are installed we enable mainsails remote mode
|
# are installed we enable mainsails remote mode
|
||||||
if client.get("remote_mode") and not mr_instances or len(mr_instances) > 1:
|
if (
|
||||||
|
client.client == WebClientType.MAINSAIL
|
||||||
|
and not mr_instances
|
||||||
|
or len(mr_instances) > 1
|
||||||
|
):
|
||||||
enable_remotemode = True
|
enable_remotemode = True
|
||||||
|
|
||||||
kl_im = InstanceManager(Klipper)
|
kl_im = InstanceManager(Klipper)
|
||||||
kl_instances = kl_im.instances
|
kl_instances = kl_im.instances
|
||||||
install_client_cfg = False
|
install_client_cfg = False
|
||||||
client_config = client.get("client_config")
|
client_config: BaseWebClientConfig = client.client_config
|
||||||
if (
|
if (
|
||||||
kl_instances
|
kl_instances
|
||||||
and not client_config.get("dir").exists()
|
and not client_config.config_dir.exists()
|
||||||
and not config_for_other_client_exist(client_to_ignore=client.get("name"))
|
and not config_for_other_client_exist(client_to_ignore=client.client)
|
||||||
):
|
):
|
||||||
print_install_client_config_dialog(client)
|
print_install_client_config_dialog(client)
|
||||||
question = f"Download the recommended {client_config.get('display_name')}?"
|
question = f"Download the recommended {client_config.display_name}?"
|
||||||
install_client_cfg = get_confirm(question, allow_go_back=False)
|
install_client_cfg = get_confirm(question, allow_go_back=False)
|
||||||
|
|
||||||
cm = ConfigManager(cfg_file=KIAUH_CFG)
|
cm = ConfigManager(cfg_file=KIAUH_CFG)
|
||||||
default_port = cm.get_value(client.get("name"), "port")
|
default_port = cm.get_value(client.name, "port")
|
||||||
client_port = default_port if default_port and default_port.isdigit() else "80"
|
client_port = default_port if default_port and default_port.isdigit() else "80"
|
||||||
ports_in_use = read_ports_from_nginx_configs()
|
ports_in_use = read_ports_from_nginx_configs()
|
||||||
|
|
||||||
@@ -113,10 +113,10 @@ def install_client(client_name: ClientName) -> None:
|
|||||||
valid_port = is_valid_port(client_port, ports_in_use)
|
valid_port = is_valid_port(client_port, ports_in_use)
|
||||||
while not valid_port:
|
while not valid_port:
|
||||||
next_port = get_next_free_port(ports_in_use)
|
next_port = get_next_free_port(ports_in_use)
|
||||||
print_client_port_select_dialog(d_name, next_port, ports_in_use)
|
print_client_port_select_dialog(client.display_name, next_port, ports_in_use)
|
||||||
client_port = str(
|
client_port = str(
|
||||||
get_number_input(
|
get_number_input(
|
||||||
f"Configure {d_name} for port",
|
f"Configure {client.display_name} for port",
|
||||||
min_count=int(next_port),
|
min_count=int(next_port),
|
||||||
default=next_port,
|
default=next_port,
|
||||||
)
|
)
|
||||||
@@ -127,22 +127,22 @@ def install_client(client_name: ClientName) -> None:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
download_client(client)
|
download_client(client)
|
||||||
if enable_remotemode and client.get("name") == "mainsail":
|
if enable_remotemode and client.client == WebClientType.MAINSAIL:
|
||||||
enable_mainsail_remotemode()
|
enable_mainsail_remotemode()
|
||||||
if mr_instances:
|
if mr_instances:
|
||||||
add_config_section(
|
add_config_section(
|
||||||
section=f"update_manager {client.get('name')}",
|
section=f"update_manager {client.name}",
|
||||||
instances=mr_instances,
|
instances=mr_instances,
|
||||||
options=[
|
options=[
|
||||||
("type", "web"),
|
("type", "web"),
|
||||||
("channel", "stable"),
|
("channel", "stable"),
|
||||||
("repo", client.get("mr_conf_repo")),
|
("repo", str(client.repo_path)),
|
||||||
("path", client.get("mr_conf_path")),
|
("path", str(client.client_dir)),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
mr_im.restart_all_instance()
|
mr_im.restart_all_instance()
|
||||||
if install_client_cfg and kl_instances:
|
if install_client_cfg and kl_instances:
|
||||||
install_client_config(client.get("name"))
|
install_client_config(client)
|
||||||
|
|
||||||
copy_upstream_nginx_cfg()
|
copy_upstream_nginx_cfg()
|
||||||
copy_common_vars_nginx_cfg()
|
copy_common_vars_nginx_cfg()
|
||||||
@@ -152,24 +152,24 @@ def install_client(client_name: ClientName) -> None:
|
|||||||
control_systemd_service("nginx", "restart")
|
control_systemd_service("nginx", "restart")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
Logger.print_error(f"{d_name} installation failed!\n{e}")
|
Logger.print_error(f"{client.display_name} installation failed!\n{e}")
|
||||||
return
|
return
|
||||||
|
|
||||||
log = f"Open {d_name} now on: http://{get_ipv4_addr()}:{client_port}"
|
log = f"Open {client.display_name} now on: http://{get_ipv4_addr()}:{client_port}"
|
||||||
Logger.print_ok(f"{d_name} installation complete!", start="\n")
|
Logger.print_ok(f"{client.display_name} installation complete!", start="\n")
|
||||||
Logger.print_ok(log, prefix=False, end="\n\n")
|
Logger.print_ok(log, prefix=False, end="\n\n")
|
||||||
|
|
||||||
|
|
||||||
def download_client(client: ClientData) -> None:
|
def download_client(client: BaseWebClient) -> None:
|
||||||
zipfile = f"{client.get('name').lower()}.zip"
|
zipfile = f"{client.name.lower()}.zip"
|
||||||
target = Path().home().joinpath(zipfile)
|
target = Path().home().joinpath(zipfile)
|
||||||
try:
|
try:
|
||||||
Logger.print_status(f"Downloading {zipfile} ...")
|
Logger.print_status(f"Downloading {zipfile} ...")
|
||||||
download_file(client.get("url"), target, True)
|
download_file(client.stable_url, target, True)
|
||||||
Logger.print_ok("Download complete!")
|
Logger.print_ok("Download complete!")
|
||||||
|
|
||||||
Logger.print_status(f"Extracting {zipfile} ...")
|
Logger.print_status(f"Extracting {zipfile} ...")
|
||||||
unzip(target, client.get("dir"))
|
unzip(target, client.client_dir)
|
||||||
target.unlink(missing_ok=True)
|
target.unlink(missing_ok=True)
|
||||||
Logger.print_ok("OK!")
|
Logger.print_ok("OK!")
|
||||||
|
|
||||||
@@ -178,29 +178,35 @@ def download_client(client: ClientData) -> None:
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
def update_client(client: ClientData) -> None:
|
def update_client(client: BaseWebClient) -> None:
|
||||||
Logger.print_status(f"Updating {client.get('display_name')} ...")
|
Logger.print_status(f"Updating {client.display_name} ...")
|
||||||
if client.get("name") == "mainsail":
|
if not client.client_dir.exists():
|
||||||
|
Logger.print_info(
|
||||||
|
f"Unable to update {client.display_name}. Directory does not exist! Skipping ..."
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
if client.client == WebClientType.MAINSAIL:
|
||||||
backup_mainsail_config_json(is_temp=True)
|
backup_mainsail_config_json(is_temp=True)
|
||||||
|
|
||||||
download_client(client)
|
download_client(client)
|
||||||
|
|
||||||
if client.get("name") == "mainsail":
|
if client.client == WebClientType.MAINSAIL:
|
||||||
restore_mainsail_config_json()
|
restore_mainsail_config_json()
|
||||||
|
|
||||||
|
|
||||||
def create_client_nginx_cfg(client: ClientData, port: int) -> None:
|
def create_client_nginx_cfg(client: BaseWebClient, port: int) -> None:
|
||||||
d_name = client.get("display_name")
|
display_name = client.display_name
|
||||||
root_dir = client.get("dir")
|
root_dir = client.client_dir
|
||||||
source = NGINX_SITES_AVAILABLE.joinpath(client.get("name"))
|
source = NGINX_SITES_AVAILABLE.joinpath(client.name)
|
||||||
target = NGINX_SITES_ENABLED.joinpath(client.get("name"))
|
target = NGINX_SITES_ENABLED.joinpath(client.name)
|
||||||
try:
|
try:
|
||||||
Logger.print_status(f"Creating NGINX config for {d_name} ...")
|
Logger.print_status(f"Creating NGINX config for {display_name} ...")
|
||||||
remove_file(Path("/etc/nginx/sites-enabled/default"), True)
|
remove_file(Path("/etc/nginx/sites-enabled/default"), True)
|
||||||
create_nginx_cfg(client.get("name"), port, root_dir)
|
create_nginx_cfg(client.name, port, root_dir)
|
||||||
create_symlink(source, target, True)
|
create_symlink(source, target, True)
|
||||||
set_nginx_permissions()
|
set_nginx_permissions()
|
||||||
Logger.print_ok(f"NGINX config for {d_name} successfully created.")
|
Logger.print_ok(f"NGINX config for {display_name} successfully created.")
|
||||||
except Exception:
|
except Exception:
|
||||||
Logger.print_error(f"Creating NGINX config for {d_name} failed!")
|
Logger.print_error(f"Creating NGINX config for {display_name} failed!")
|
||||||
raise
|
raise
|
||||||
|
|||||||
@@ -9,117 +9,43 @@
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
import shutil
|
import shutil
|
||||||
from json import JSONDecodeError
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Optional, Dict, Literal, Union, get_args
|
from typing import List, Dict, Literal, Union, get_args
|
||||||
|
|
||||||
import urllib.request
|
|
||||||
|
|
||||||
from components.klipper.klipper import Klipper
|
from components.klipper.klipper import Klipper
|
||||||
from components.webui_client import (
|
from components.webui_client.base_data import (
|
||||||
MAINSAIL_CONFIG_JSON,
|
WebClientType,
|
||||||
MAINSAIL_DIR,
|
BaseWebClient,
|
||||||
MAINSAIL_BACKUP_DIR,
|
BaseWebClientConfig,
|
||||||
FLUIDD_PRE_RLS_URL,
|
|
||||||
FLUIDD_BACKUP_DIR,
|
|
||||||
FLUIDD_URL,
|
|
||||||
FLUIDD_DIR,
|
|
||||||
ClientData,
|
|
||||||
FLUIDD_CONFIG_REPO_URL,
|
|
||||||
FLUIDD_CONFIG_DIR,
|
|
||||||
ClientConfigData,
|
|
||||||
MAINSAIL_PRE_RLS_URL,
|
|
||||||
MAINSAIL_URL,
|
|
||||||
MAINSAIL_CONFIG_REPO_URL,
|
|
||||||
MAINSAIL_CONFIG_DIR,
|
|
||||||
ClientName,
|
|
||||||
MAINSAIL_TAGS_URL,
|
|
||||||
FLUIDD_TAGS_URL,
|
|
||||||
FLUIDD_CONFIG_BACKUP_DIR,
|
|
||||||
MAINSAIL_CONFIG_BACKUP_DIR,
|
|
||||||
)
|
)
|
||||||
|
from components.webui_client.mainsail_data import MainsailData
|
||||||
from core.backup_manager.backup_manager import BackupManager
|
from core.backup_manager.backup_manager import BackupManager
|
||||||
from core.repo_manager.repo_manager import RepoManager
|
from core.repo_manager.repo_manager import RepoManager
|
||||||
from utils import NGINX_SITES_AVAILABLE, NGINX_CONFD
|
from utils import NGINX_SITES_AVAILABLE, NGINX_CONFD
|
||||||
from utils.common import get_install_status_webui
|
from utils.common import get_install_status_webui
|
||||||
from utils.constants import COLOR_CYAN, RESET_FORMAT, COLOR_YELLOW
|
from utils.constants import COLOR_CYAN, RESET_FORMAT, COLOR_YELLOW
|
||||||
|
from utils.git_utils import get_latest_tag
|
||||||
from utils.logger import Logger
|
from utils.logger import Logger
|
||||||
|
|
||||||
|
|
||||||
def load_client_data(client_name: ClientName) -> Optional[ClientData]:
|
def get_client_status(client: BaseWebClient) -> str:
|
||||||
client_data = None
|
|
||||||
|
|
||||||
if client_name == "mainsail":
|
|
||||||
client_config_data = ClientConfigData(
|
|
||||||
name="mainsail-config",
|
|
||||||
display_name="Mainsail-Config",
|
|
||||||
cfg_filename="mainsail.cfg",
|
|
||||||
dir=MAINSAIL_CONFIG_DIR,
|
|
||||||
backup_dir=MAINSAIL_CONFIG_BACKUP_DIR,
|
|
||||||
url=MAINSAIL_CONFIG_REPO_URL,
|
|
||||||
printer_cfg_section="include mainsail.cfg",
|
|
||||||
mr_conf_path="~/mainsail-config",
|
|
||||||
mr_conf_origin=MAINSAIL_CONFIG_REPO_URL,
|
|
||||||
)
|
|
||||||
client_data = ClientData(
|
|
||||||
name=client_name,
|
|
||||||
display_name=client_name.capitalize(),
|
|
||||||
dir=MAINSAIL_DIR,
|
|
||||||
backup_dir=MAINSAIL_BACKUP_DIR,
|
|
||||||
url=MAINSAIL_URL,
|
|
||||||
pre_release_url=MAINSAIL_PRE_RLS_URL,
|
|
||||||
tags_url=MAINSAIL_TAGS_URL,
|
|
||||||
remote_mode=True,
|
|
||||||
mr_conf_repo="mainsail-crew/mainsail",
|
|
||||||
mr_conf_path="~/mainsail",
|
|
||||||
client_config=client_config_data,
|
|
||||||
)
|
|
||||||
elif client_name == "fluidd":
|
|
||||||
client_config_data = ClientConfigData(
|
|
||||||
name="fluidd-config",
|
|
||||||
display_name="Fluidd-Config",
|
|
||||||
cfg_filename="fluidd.cfg",
|
|
||||||
dir=FLUIDD_CONFIG_DIR,
|
|
||||||
backup_dir=FLUIDD_CONFIG_BACKUP_DIR,
|
|
||||||
url=FLUIDD_CONFIG_REPO_URL,
|
|
||||||
printer_cfg_section="include fluidd.cfg",
|
|
||||||
mr_conf_path="~/fluidd-config",
|
|
||||||
mr_conf_origin=FLUIDD_CONFIG_REPO_URL,
|
|
||||||
)
|
|
||||||
client_data = ClientData(
|
|
||||||
name=client_name,
|
|
||||||
display_name=client_name.capitalize(),
|
|
||||||
dir=FLUIDD_DIR,
|
|
||||||
backup_dir=FLUIDD_BACKUP_DIR,
|
|
||||||
url=FLUIDD_URL,
|
|
||||||
pre_release_url=FLUIDD_PRE_RLS_URL,
|
|
||||||
tags_url=FLUIDD_TAGS_URL,
|
|
||||||
remote_mode=False,
|
|
||||||
mr_conf_repo="fluidd-core/fluidd",
|
|
||||||
mr_conf_path="~/fluidd",
|
|
||||||
client_config=client_config_data,
|
|
||||||
)
|
|
||||||
|
|
||||||
return client_data
|
|
||||||
|
|
||||||
|
|
||||||
def get_client_status(client: ClientData) -> str:
|
|
||||||
return get_install_status_webui(
|
return get_install_status_webui(
|
||||||
client.get("dir"),
|
client.client_dir,
|
||||||
NGINX_SITES_AVAILABLE.joinpath(client.get("name")),
|
NGINX_SITES_AVAILABLE.joinpath(client.name),
|
||||||
NGINX_CONFD.joinpath("upstreams.conf"),
|
NGINX_CONFD.joinpath("upstreams.conf"),
|
||||||
NGINX_CONFD.joinpath("common_vars.conf"),
|
NGINX_CONFD.joinpath("common_vars.conf"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_client_config_status(
|
def get_client_config_status(
|
||||||
client: ClientData,
|
client: BaseWebClient,
|
||||||
) -> Dict[
|
) -> Dict[
|
||||||
Literal["repo", "local", "remote"],
|
Literal["repo", "local", "remote"],
|
||||||
Union[str, int],
|
Union[str, int],
|
||||||
]:
|
]:
|
||||||
client_config = client.get("client_config")
|
client_config = client.client_config
|
||||||
client_config = client_config.get("dir")
|
client_config = client_config.config_dir
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"repo": RepoManager.get_repo_name(client_config),
|
"repo": RepoManager.get_repo_name(client_config),
|
||||||
@@ -128,44 +54,47 @@ def get_client_config_status(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_current_client_config(clients: List[ClientData]) -> str:
|
def get_current_client_config(clients: List[BaseWebClient]) -> str:
|
||||||
installed = []
|
installed = []
|
||||||
for client in clients:
|
for client in clients:
|
||||||
client_config = client.get("client_config")
|
client_config = client.client_config
|
||||||
if client_config.get("dir").exists():
|
if client_config.config_dir.exists():
|
||||||
installed.append(client)
|
installed.append(client)
|
||||||
|
|
||||||
if len(installed) > 1:
|
if len(installed) > 1:
|
||||||
return f"{COLOR_YELLOW}Conflict!{RESET_FORMAT}"
|
return f"{COLOR_YELLOW}Conflict!{RESET_FORMAT}"
|
||||||
elif len(installed) == 1:
|
elif len(installed) == 1:
|
||||||
cfg = installed[0].get("client_config")
|
cfg = installed[0].client_config
|
||||||
return f"{COLOR_CYAN}{cfg.get('display_name')}{RESET_FORMAT}"
|
return f"{COLOR_CYAN}{cfg.display_name}{RESET_FORMAT}"
|
||||||
|
|
||||||
return f"{COLOR_CYAN}-{RESET_FORMAT}"
|
return f"{COLOR_CYAN}-{RESET_FORMAT}"
|
||||||
|
|
||||||
|
|
||||||
def backup_mainsail_config_json(is_temp=False) -> None:
|
def backup_mainsail_config_json(is_temp=False) -> None:
|
||||||
Logger.print_status(f"Backup '{MAINSAIL_CONFIG_JSON}' ...")
|
c_json = MainsailData().client_dir.joinpath("config.json")
|
||||||
|
Logger.print_status(f"Backup '{c_json}' ...")
|
||||||
bm = BackupManager()
|
bm = BackupManager()
|
||||||
if is_temp:
|
if is_temp:
|
||||||
fn = Path.home().joinpath("config.json.kiauh.bak")
|
fn = Path.home().joinpath("config.json.kiauh.bak")
|
||||||
bm.backup_file(MAINSAIL_CONFIG_JSON, custom_filename=fn)
|
bm.backup_file(c_json, custom_filename=fn)
|
||||||
else:
|
else:
|
||||||
bm.backup_file(MAINSAIL_CONFIG_JSON)
|
bm.backup_file(c_json)
|
||||||
|
|
||||||
|
|
||||||
def restore_mainsail_config_json() -> None:
|
def restore_mainsail_config_json() -> None:
|
||||||
try:
|
try:
|
||||||
Logger.print_status(f"Restore '{MAINSAIL_CONFIG_JSON}' ...")
|
c_json = MainsailData().client_dir.joinpath("config.json")
|
||||||
|
Logger.print_status(f"Restore '{c_json}' ...")
|
||||||
source = Path.home().joinpath("config.json.kiauh.bak")
|
source = Path.home().joinpath("config.json.kiauh.bak")
|
||||||
shutil.copy(source, MAINSAIL_CONFIG_JSON)
|
shutil.copy(source, c_json)
|
||||||
except OSError:
|
except OSError:
|
||||||
Logger.print_info("Unable to restore config.json. Skipped ...")
|
Logger.print_info("Unable to restore config.json. Skipped ...")
|
||||||
|
|
||||||
|
|
||||||
def enable_mainsail_remotemode() -> None:
|
def enable_mainsail_remotemode() -> None:
|
||||||
Logger.print_status("Enable Mainsails remote mode ...")
|
Logger.print_status("Enable Mainsails remote mode ...")
|
||||||
with open(MAINSAIL_CONFIG_JSON, "r") as f:
|
c_json = MainsailData().client_dir.joinpath("config.json")
|
||||||
|
with open(c_json, "r") as f:
|
||||||
config_data = json.load(f)
|
config_data = json.load(f)
|
||||||
|
|
||||||
if config_data["instancesDB"] == "browser":
|
if config_data["instancesDB"] == "browser":
|
||||||
@@ -175,7 +104,7 @@ def enable_mainsail_remotemode() -> None:
|
|||||||
Logger.print_status("Setting instance storage location to 'browser' ...")
|
Logger.print_status("Setting instance storage location to 'browser' ...")
|
||||||
config_data["instancesDB"] = "browser"
|
config_data["instancesDB"] = "browser"
|
||||||
|
|
||||||
with open(MAINSAIL_CONFIG_JSON, "w") as f:
|
with open(c_json, "w") as f:
|
||||||
json.dump(config_data, f, indent=4)
|
json.dump(config_data, f, indent=4)
|
||||||
Logger.print_ok("Mainsails remote mode enabled!")
|
Logger.print_ok("Mainsails remote mode enabled!")
|
||||||
|
|
||||||
@@ -195,8 +124,8 @@ def symlink_webui_nginx_log(klipper_instances: List[Klipper]) -> None:
|
|||||||
desti_error.symlink_to(error_log)
|
desti_error.symlink_to(error_log)
|
||||||
|
|
||||||
|
|
||||||
def get_local_client_version(client: ClientData) -> str:
|
def get_local_client_version(client: BaseWebClient) -> str:
|
||||||
relinfo_file = client.get("dir").joinpath("release_info.json")
|
relinfo_file = client.client_dir.joinpath("release_info.json")
|
||||||
if not relinfo_file.is_file():
|
if not relinfo_file.is_file():
|
||||||
return "-"
|
return "-"
|
||||||
|
|
||||||
@@ -204,19 +133,19 @@ def get_local_client_version(client: ClientData) -> str:
|
|||||||
return json.load(f)["version"]
|
return json.load(f)["version"]
|
||||||
|
|
||||||
|
|
||||||
def get_remote_client_version(client: ClientData) -> str:
|
def get_remote_client_version(client: BaseWebClient) -> str:
|
||||||
try:
|
try:
|
||||||
with urllib.request.urlopen(client.get("tags_url")) as response:
|
if (tag := get_latest_tag(client.repo_path)) != "":
|
||||||
data = json.loads(response.read())
|
return tag
|
||||||
return data[0]["name"]
|
return "ERROR"
|
||||||
except (JSONDecodeError, TypeError):
|
except Exception:
|
||||||
return "ERROR"
|
return "ERROR"
|
||||||
|
|
||||||
|
|
||||||
def backup_client_data(client: ClientData) -> None:
|
def backup_client_data(client: BaseWebClient) -> None:
|
||||||
name = client.get("name")
|
name = client.name
|
||||||
src = client.get("dir")
|
src = client.client_dir
|
||||||
dest = client.get("backup_dir")
|
dest = client.backup_dir
|
||||||
|
|
||||||
with open(src.joinpath(".version"), "r") as v:
|
with open(src.joinpath(".version"), "r") as v:
|
||||||
version = v.readlines()[0]
|
version = v.readlines()[0]
|
||||||
@@ -224,43 +153,42 @@ def backup_client_data(client: ClientData) -> None:
|
|||||||
bm = BackupManager()
|
bm = BackupManager()
|
||||||
bm.backup_directory(f"{name}-{version}", src, dest)
|
bm.backup_directory(f"{name}-{version}", src, dest)
|
||||||
if name == "mainsail":
|
if name == "mainsail":
|
||||||
bm.backup_file(MAINSAIL_CONFIG_JSON, dest)
|
c_json = MainsailData().client_dir.joinpath("config.json")
|
||||||
|
bm.backup_file(c_json, dest)
|
||||||
bm.backup_file(NGINX_SITES_AVAILABLE.joinpath(name), dest)
|
bm.backup_file(NGINX_SITES_AVAILABLE.joinpath(name), dest)
|
||||||
|
|
||||||
|
|
||||||
def backup_client_config_data(client: ClientData) -> None:
|
def backup_client_config_data(client: BaseWebClient) -> None:
|
||||||
client_config = client.get("client_config")
|
client_config = client.client_config
|
||||||
name = client_config.get("name")
|
name = client_config.name
|
||||||
source = client_config.get("dir")
|
source = client_config.config_dir
|
||||||
target = client_config.get("backup_dir")
|
target = client_config.backup_dir
|
||||||
bm = BackupManager()
|
bm = BackupManager()
|
||||||
bm.backup_directory(name, source, target)
|
bm.backup_directory(name, source, target)
|
||||||
|
|
||||||
|
|
||||||
def get_existing_clients() -> List[ClientData]:
|
def get_existing_clients() -> List[BaseWebClient]:
|
||||||
clients = list(get_args(ClientName))
|
clients = list(get_args(WebClientType))
|
||||||
installed_clients: List[ClientData] = []
|
installed_clients: List[BaseWebClient] = []
|
||||||
for c in clients:
|
for client in clients:
|
||||||
c_data: ClientData = load_client_data(c)
|
if client.client_dir.exists():
|
||||||
if c_data.get("dir").exists():
|
installed_clients.append(client)
|
||||||
installed_clients.append(c_data)
|
|
||||||
|
|
||||||
return installed_clients
|
return installed_clients
|
||||||
|
|
||||||
|
|
||||||
def get_existing_client_config() -> List[ClientData]:
|
def get_existing_client_config() -> List[BaseWebClient]:
|
||||||
clients = list(get_args(ClientName))
|
clients = list(get_args(WebClientType))
|
||||||
installed_client_configs: List[ClientData] = []
|
installed_client_configs: List[BaseWebClient] = []
|
||||||
for c in clients:
|
for client in clients:
|
||||||
c_data: ClientData = load_client_data(c)
|
c_config_data: BaseWebClientConfig = client.client_config
|
||||||
c_config_data: ClientConfigData = c_data.get("client_config")
|
if c_config_data.config_dir.exists():
|
||||||
if c_config_data.get("dir").exists():
|
installed_client_configs.append(client)
|
||||||
installed_client_configs.append(c_data)
|
|
||||||
|
|
||||||
return installed_client_configs
|
return installed_client_configs
|
||||||
|
|
||||||
|
|
||||||
def config_for_other_client_exist(client_to_ignore: ClientName) -> bool:
|
def config_for_other_client_exist(client_to_ignore: WebClientType) -> bool:
|
||||||
"""
|
"""
|
||||||
Check if any other client configs are present on the system.
|
Check if any other client configs are present on the system.
|
||||||
It is usually not harmful, but chances are they can conflict each other.
|
It is usually not harmful, but chances are they can conflict each other.
|
||||||
@@ -269,7 +197,7 @@ def config_for_other_client_exist(client_to_ignore: ClientName) -> bool:
|
|||||||
:return: True, if other client configs were found, else False
|
:return: True, if other client configs were found, else False
|
||||||
"""
|
"""
|
||||||
|
|
||||||
clients = set([c["name"] for c in get_existing_client_config()])
|
clients = set([c.name for c in get_existing_client_config()])
|
||||||
clients = clients - {client_to_ignore}
|
clients = clients - {client_to_ignore.value}
|
||||||
|
|
||||||
return True if len(clients) > 0 else False
|
return True if len(clients) > 0 else False
|
||||||
|
|||||||
65
kiauh/components/webui_client/fluidd_data.py
Normal file
65
kiauh/components/webui_client/fluidd_data.py
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# ======================================================================= #
|
||||||
|
# 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 #
|
||||||
|
# ======================================================================= #
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from components.webui_client.base_data import (
|
||||||
|
BaseWebClientConfig,
|
||||||
|
WebClientConfigType,
|
||||||
|
WebClientType,
|
||||||
|
BaseWebClient,
|
||||||
|
)
|
||||||
|
from core.backup_manager import BACKUP_ROOT_DIR
|
||||||
|
from utils.git_utils import get_latest_unstable_tag
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class FluiddConfigWeb(BaseWebClientConfig):
|
||||||
|
client_config: WebClientConfigType = WebClientConfigType.FLUIDD
|
||||||
|
name: str = client_config.value
|
||||||
|
display_name: str = name.title()
|
||||||
|
config_dir: Path = Path.home().joinpath("fluidd-config")
|
||||||
|
config_filename: str = "fluidd.cfg"
|
||||||
|
config_section: str = f"include {config_filename}"
|
||||||
|
backup_dir: Path = BACKUP_ROOT_DIR.joinpath("fluidd-config-backups")
|
||||||
|
repo_url: str = "https://github.com/fluidd-core/fluidd-config.git"
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class FluiddData(BaseWebClient):
|
||||||
|
BASE_DL_URL = "https://github.com/fluidd-core/fluidd/releases"
|
||||||
|
|
||||||
|
client: WebClientType = WebClientType.FLUIDD
|
||||||
|
name: str = client.value
|
||||||
|
display_name: str = name.capitalize()
|
||||||
|
client_dir: Path = Path.home().joinpath("fluidd")
|
||||||
|
backup_dir: Path = BACKUP_ROOT_DIR.joinpath("fluidd-backups")
|
||||||
|
repo_path: str = "fluidd-core/fluidd"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def stable_url(self) -> str:
|
||||||
|
return f"{self.BASE_DL_URL}/latest/download/fluidd.zip"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unstable_url(self) -> str:
|
||||||
|
try:
|
||||||
|
unstable_tag = get_latest_unstable_tag(self.repo_path)
|
||||||
|
if unstable_tag != "":
|
||||||
|
return f"{self.BASE_DL_URL}/download/{unstable_tag}/fluidd.zip"
|
||||||
|
else:
|
||||||
|
raise Exception
|
||||||
|
except Exception:
|
||||||
|
return self.stable_url
|
||||||
|
|
||||||
|
@property
|
||||||
|
def client_config(self) -> BaseWebClientConfig:
|
||||||
|
return FluiddConfigWeb()
|
||||||
65
kiauh/components/webui_client/mainsail_data.py
Normal file
65
kiauh/components/webui_client/mainsail_data.py
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# ======================================================================= #
|
||||||
|
# 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 #
|
||||||
|
# ======================================================================= #
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from components.webui_client.base_data import (
|
||||||
|
BaseWebClientConfig,
|
||||||
|
WebClientConfigType,
|
||||||
|
WebClientType,
|
||||||
|
BaseWebClient,
|
||||||
|
)
|
||||||
|
from core.backup_manager import BACKUP_ROOT_DIR
|
||||||
|
from utils.git_utils import get_latest_unstable_tag
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class MainsailConfigWeb(BaseWebClientConfig):
|
||||||
|
client_config: WebClientConfigType = WebClientConfigType.MAINSAIL
|
||||||
|
name: str = client_config.value
|
||||||
|
display_name: str = name.title()
|
||||||
|
config_dir: Path = Path.home().joinpath("mainsail-config")
|
||||||
|
config_filename: str = "mainsail.cfg"
|
||||||
|
config_section: str = f"include {config_filename}"
|
||||||
|
backup_dir: Path = BACKUP_ROOT_DIR.joinpath("mainsail-config-backups")
|
||||||
|
repo_url: str = "https://github.com/mainsail-crew/mainsail-config.git"
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class MainsailData(BaseWebClient):
|
||||||
|
BASE_DL_URL: str = "https://github.com/mainsail-crew/mainsail/releases"
|
||||||
|
|
||||||
|
client: WebClientType = WebClientType.MAINSAIL
|
||||||
|
name: str = WebClientType.MAINSAIL.value
|
||||||
|
display_name: str = name.capitalize()
|
||||||
|
client_dir: Path = Path.home().joinpath("mainsail")
|
||||||
|
backup_dir: Path = BACKUP_ROOT_DIR.joinpath("mainsail-backups")
|
||||||
|
repo_path: str = "mainsail-crew/mainsail"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def stable_url(self) -> str:
|
||||||
|
return f"{self.BASE_DL_URL}/latest/download/mainsail.zip"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unstable_url(self) -> str:
|
||||||
|
try:
|
||||||
|
unstable_tag = get_latest_unstable_tag(self.repo_path)
|
||||||
|
if unstable_tag != "":
|
||||||
|
return f"{self.BASE_DL_URL}/download/{unstable_tag}/mainsail.zip"
|
||||||
|
else:
|
||||||
|
raise Exception
|
||||||
|
except Exception:
|
||||||
|
return self.stable_url
|
||||||
|
|
||||||
|
@property
|
||||||
|
def client_config(self) -> BaseWebClientConfig:
|
||||||
|
return MainsailConfigWeb()
|
||||||
@@ -10,14 +10,15 @@
|
|||||||
import textwrap
|
import textwrap
|
||||||
from typing import Callable, Dict
|
from typing import Callable, Dict
|
||||||
|
|
||||||
from components.webui_client import client_remove, ClientData
|
from components.webui_client import client_remove
|
||||||
|
from components.webui_client.base_data import BaseWebClient, WebClientType
|
||||||
from core.menus.base_menu import BaseMenu
|
from core.menus.base_menu import BaseMenu
|
||||||
from utils.constants import RESET_FORMAT, COLOR_RED, COLOR_CYAN
|
from utils.constants import RESET_FORMAT, COLOR_RED, COLOR_CYAN
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyUnusedLocal
|
# noinspection PyUnusedLocal
|
||||||
class ClientRemoveMenu(BaseMenu):
|
class ClientRemoveMenu(BaseMenu):
|
||||||
def __init__(self, previous_menu: BaseMenu, client: ClientData):
|
def __init__(self, previous_menu: BaseMenu, client: BaseWebClient):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.previous_menu = previous_menu
|
self.previous_menu = previous_menu
|
||||||
self.options = self.get_options(client)
|
self.options = self.get_options(client)
|
||||||
@@ -27,22 +28,22 @@ class ClientRemoveMenu(BaseMenu):
|
|||||||
self.rm_client_config = False
|
self.rm_client_config = False
|
||||||
self.backup_mainsail_config_json = False
|
self.backup_mainsail_config_json = False
|
||||||
|
|
||||||
def get_options(self, client: ClientData) -> Dict[str, Callable]:
|
def get_options(self, client: BaseWebClient) -> Dict[str, Callable]:
|
||||||
options = {
|
options = {
|
||||||
"0": self.toggle_all,
|
"0": self.toggle_all,
|
||||||
"1": self.toggle_rm_client,
|
"1": self.toggle_rm_client,
|
||||||
"2": self.toggle_rm_client_config,
|
"2": self.toggle_rm_client_config,
|
||||||
"c": self.run_removal_process,
|
"c": self.run_removal_process,
|
||||||
}
|
}
|
||||||
if client.get("name") == "mainsail":
|
if client.client == WebClientType.MAINSAIL:
|
||||||
options["3"] = self.toggle_backup_mainsail_config_json
|
options["3"] = self.toggle_backup_mainsail_config_json
|
||||||
|
|
||||||
return options
|
return options
|
||||||
|
|
||||||
def print_menu(self) -> None:
|
def print_menu(self) -> None:
|
||||||
client_name = self.client.get("display_name")
|
client_name = self.client.display_name
|
||||||
client_config = self.client.get("client_config")
|
client_config = self.client.client_config
|
||||||
client_config_name = client_config.get("display_name")
|
client_config_name = client_config.display_name
|
||||||
|
|
||||||
header = f" [ Remove {client_name} ] "
|
header = f" [ Remove {client_name} ] "
|
||||||
color = COLOR_RED
|
color = COLOR_RED
|
||||||
@@ -66,7 +67,7 @@ class ClientRemoveMenu(BaseMenu):
|
|||||||
"""
|
"""
|
||||||
)[1:]
|
)[1:]
|
||||||
|
|
||||||
if self.client.get("name") == "mainsail":
|
if self.client.client == WebClientType.MAINSAIL:
|
||||||
o3 = checked if self.backup_mainsail_config_json else unchecked
|
o3 = checked if self.backup_mainsail_config_json else unchecked
|
||||||
menu += textwrap.dedent(
|
menu += textwrap.dedent(
|
||||||
f"""
|
f"""
|
||||||
|
|||||||
@@ -16,9 +16,10 @@ from components.moonraker.moonraker_utils import (
|
|||||||
)
|
)
|
||||||
from components.webui_client.client_utils import (
|
from components.webui_client.client_utils import (
|
||||||
backup_client_data,
|
backup_client_data,
|
||||||
load_client_data,
|
|
||||||
backup_client_config_data,
|
backup_client_config_data,
|
||||||
)
|
)
|
||||||
|
from components.webui_client.fluidd_data import FluiddData
|
||||||
|
from components.webui_client.mainsail_data import MainsailData
|
||||||
from core.menus.base_menu import BaseMenu
|
from core.menus.base_menu import BaseMenu
|
||||||
from utils.common import backup_printer_config_dir
|
from utils.common import backup_printer_config_dir
|
||||||
from utils.constants import COLOR_CYAN, RESET_FORMAT, COLOR_YELLOW
|
from utils.constants import COLOR_CYAN, RESET_FORMAT, COLOR_YELLOW
|
||||||
@@ -81,16 +82,16 @@ class BackupMenu(BaseMenu):
|
|||||||
backup_moonraker_db_dir()
|
backup_moonraker_db_dir()
|
||||||
|
|
||||||
def backup_mainsail(self, **kwargs):
|
def backup_mainsail(self, **kwargs):
|
||||||
backup_client_data(load_client_data("mainsail"))
|
backup_client_data(MainsailData().get())
|
||||||
|
|
||||||
def backup_fluidd(self, **kwargs):
|
def backup_fluidd(self, **kwargs):
|
||||||
backup_client_data(load_client_data("fluidd"))
|
backup_client_data(FluiddData().get())
|
||||||
|
|
||||||
def backup_mainsail_config(self, **kwargs):
|
def backup_mainsail_config(self, **kwargs):
|
||||||
backup_client_config_data(load_client_data("mainsail"))
|
backup_client_config_data(MainsailData().get())
|
||||||
|
|
||||||
def backup_fluidd_config(self, **kwargs):
|
def backup_fluidd_config(self, **kwargs):
|
||||||
backup_client_config_data(load_client_data("fluidd"))
|
backup_client_config_data(FluiddData().get())
|
||||||
|
|
||||||
def backup_klipperscreen(self, **kwargs):
|
def backup_klipperscreen(self, **kwargs):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ from components.klipper import klipper_setup
|
|||||||
from components.moonraker import moonraker_setup
|
from components.moonraker import moonraker_setup
|
||||||
from components.webui_client import client_setup
|
from components.webui_client import client_setup
|
||||||
from components.webui_client.client_config import client_config_setup
|
from components.webui_client.client_config import client_config_setup
|
||||||
|
from components.webui_client.fluidd_data import FluiddData
|
||||||
|
from components.webui_client.mainsail_data import MainsailData
|
||||||
|
|
||||||
from core.menus.base_menu import BaseMenu
|
from core.menus.base_menu import BaseMenu
|
||||||
from utils.constants import COLOR_GREEN, RESET_FORMAT
|
from utils.constants import COLOR_GREEN, RESET_FORMAT
|
||||||
@@ -69,13 +71,13 @@ class InstallMenu(BaseMenu):
|
|||||||
moonraker_setup.install_moonraker()
|
moonraker_setup.install_moonraker()
|
||||||
|
|
||||||
def install_mainsail(self, **kwargs):
|
def install_mainsail(self, **kwargs):
|
||||||
client_setup.install_client(client_name="mainsail")
|
client_setup.install_client(MainsailData())
|
||||||
|
|
||||||
def install_mainsail_config(self, **kwargs):
|
def install_mainsail_config(self, **kwargs):
|
||||||
client_config_setup.install_client_config(client_name="mainsail")
|
client_config_setup.install_client_config(MainsailData())
|
||||||
|
|
||||||
def install_fluidd(self, **kwargs):
|
def install_fluidd(self, **kwargs):
|
||||||
client_setup.install_client(client_name="fluidd")
|
client_setup.install_client(FluiddData())
|
||||||
|
|
||||||
def install_fluidd_config(self, **kwargs):
|
def install_fluidd_config(self, **kwargs):
|
||||||
client_config_setup.install_client_config(client_name="fluidd")
|
client_config_setup.install_client_config(FluiddData())
|
||||||
|
|||||||
@@ -14,9 +14,10 @@ from components.log_uploads.menus.log_upload_menu import LogUploadMenu
|
|||||||
from components.moonraker.moonraker_utils import get_moonraker_status
|
from components.moonraker.moonraker_utils import get_moonraker_status
|
||||||
from components.webui_client.client_utils import (
|
from components.webui_client.client_utils import (
|
||||||
get_client_status,
|
get_client_status,
|
||||||
load_client_data,
|
|
||||||
get_current_client_config,
|
get_current_client_config,
|
||||||
)
|
)
|
||||||
|
from components.webui_client.fluidd_data import FluiddData
|
||||||
|
from components.webui_client.mainsail_data import MainsailData
|
||||||
from core.menus import FooterType
|
from core.menus import FooterType
|
||||||
from core.menus.advanced_menu import AdvancedMenu
|
from core.menus.advanced_menu import AdvancedMenu
|
||||||
from core.menus.backup_menu import BackupMenu
|
from core.menus.backup_menu import BackupMenu
|
||||||
@@ -92,15 +93,11 @@ class MainMenu(BaseMenu):
|
|||||||
self.mr_status = self.format_status_by_code(mr_code, mr_status, mr_instances)
|
self.mr_status = self.format_status_by_code(mr_code, mr_status, mr_instances)
|
||||||
self.mr_repo = f"{COLOR_CYAN}{moonraker_status.get('repo')}{RESET_FORMAT}"
|
self.mr_repo = f"{COLOR_CYAN}{moonraker_status.get('repo')}{RESET_FORMAT}"
|
||||||
# mainsail
|
# mainsail
|
||||||
mainsail_client_data = load_client_data("mainsail")
|
self.ms_status = get_client_status(MainsailData())
|
||||||
self.ms_status = get_client_status(mainsail_client_data)
|
|
||||||
# fluidd
|
# fluidd
|
||||||
fluidd_client_data = load_client_data("fluidd")
|
self.fl_status = get_client_status(FluiddData())
|
||||||
self.fl_status = get_client_status(fluidd_client_data)
|
|
||||||
# client-config
|
# client-config
|
||||||
self.cc_status = get_current_client_config(
|
self.cc_status = get_current_client_config([MainsailData(), FluiddData()])
|
||||||
[mainsail_client_data, fluidd_client_data]
|
|
||||||
)
|
|
||||||
|
|
||||||
def format_status_by_code(self, code: int, status: str, count: str) -> str:
|
def format_status_by_code(self, code: int, status: str, count: str) -> str:
|
||||||
if code == 1:
|
if code == 1:
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ from components.klipper.menus.klipper_remove_menu import KlipperRemoveMenu
|
|||||||
from components.moonraker.menus.moonraker_remove_menu import (
|
from components.moonraker.menus.moonraker_remove_menu import (
|
||||||
MoonrakerRemoveMenu,
|
MoonrakerRemoveMenu,
|
||||||
)
|
)
|
||||||
from components.webui_client.client_utils import load_client_data
|
from components.webui_client.fluidd_data import FluiddData
|
||||||
|
from components.webui_client.mainsail_data import MainsailData
|
||||||
from components.webui_client.menus.client_remove_menu import ClientRemoveMenu
|
from components.webui_client.menus.client_remove_menu import ClientRemoveMenu
|
||||||
from core.menus.base_menu import BaseMenu
|
from core.menus.base_menu import BaseMenu
|
||||||
from utils.constants import COLOR_RED, RESET_FORMAT
|
from utils.constants import COLOR_RED, RESET_FORMAT
|
||||||
@@ -76,7 +77,7 @@ class RemoveMenu(BaseMenu):
|
|||||||
MoonrakerRemoveMenu(previous_menu=self).run()
|
MoonrakerRemoveMenu(previous_menu=self).run()
|
||||||
|
|
||||||
def remove_mainsail(self, **kwargs):
|
def remove_mainsail(self, **kwargs):
|
||||||
ClientRemoveMenu(previous_menu=self, client=load_client_data("mainsail")).run()
|
ClientRemoveMenu(previous_menu=self, client=MainsailData()).run()
|
||||||
|
|
||||||
def remove_fluidd(self, **kwargs):
|
def remove_fluidd(self, **kwargs):
|
||||||
ClientRemoveMenu(previous_menu=self, client=load_client_data("fluidd")).run()
|
ClientRemoveMenu(previous_menu=self, client=FluiddData()).run()
|
||||||
|
|||||||
@@ -22,9 +22,10 @@ from components.webui_client.client_setup import update_client
|
|||||||
from components.webui_client.client_utils import (
|
from components.webui_client.client_utils import (
|
||||||
get_local_client_version,
|
get_local_client_version,
|
||||||
get_remote_client_version,
|
get_remote_client_version,
|
||||||
load_client_data,
|
|
||||||
get_client_config_status,
|
get_client_config_status,
|
||||||
)
|
)
|
||||||
|
from components.webui_client.fluidd_data import FluiddData
|
||||||
|
from components.webui_client.mainsail_data import MainsailData
|
||||||
from core.menus.base_menu import BaseMenu
|
from core.menus.base_menu import BaseMenu
|
||||||
from utils.constants import (
|
from utils.constants import (
|
||||||
COLOR_GREEN,
|
COLOR_GREEN,
|
||||||
@@ -69,6 +70,9 @@ class UpdateMenu(BaseMenu):
|
|||||||
self.fc_local = f"{COLOR_WHITE}{RESET_FORMAT}"
|
self.fc_local = f"{COLOR_WHITE}{RESET_FORMAT}"
|
||||||
self.fc_remote = f"{COLOR_WHITE}{RESET_FORMAT}"
|
self.fc_remote = f"{COLOR_WHITE}{RESET_FORMAT}"
|
||||||
|
|
||||||
|
self.mainsail_cient = MainsailData()
|
||||||
|
self.fluidd_client = FluiddData()
|
||||||
|
|
||||||
def print_menu(self):
|
def print_menu(self):
|
||||||
self.fetch_update_status()
|
self.fetch_update_status()
|
||||||
|
|
||||||
@@ -114,16 +118,16 @@ class UpdateMenu(BaseMenu):
|
|||||||
update_moonraker()
|
update_moonraker()
|
||||||
|
|
||||||
def update_mainsail(self, **kwargs):
|
def update_mainsail(self, **kwargs):
|
||||||
update_client(load_client_data("mainsail"))
|
update_client(self.mainsail_cient)
|
||||||
|
|
||||||
def update_mainsail_config(self, **kwargs):
|
def update_mainsail_config(self, **kwargs):
|
||||||
update_client_config(load_client_data("mainsail"))
|
update_client_config(self.mainsail_cient)
|
||||||
|
|
||||||
def update_fluidd(self, **kwargs):
|
def update_fluidd(self, **kwargs):
|
||||||
update_client(load_client_data("fluidd"))
|
update_client(self.fluidd_client)
|
||||||
|
|
||||||
def update_fluidd_config(self, **kwargs):
|
def update_fluidd_config(self, **kwargs):
|
||||||
update_client_config(load_client_data("fluidd"))
|
update_client_config(self.fluidd_client)
|
||||||
|
|
||||||
def update_klipperscreen(self, **kwargs): ...
|
def update_klipperscreen(self, **kwargs): ...
|
||||||
|
|
||||||
@@ -153,25 +157,23 @@ class UpdateMenu(BaseMenu):
|
|||||||
self.mr_local = f"{COLOR_YELLOW}{self.mr_local}{RESET_FORMAT}"
|
self.mr_local = f"{COLOR_YELLOW}{self.mr_local}{RESET_FORMAT}"
|
||||||
self.mr_remote = f"{COLOR_GREEN}{self.mr_remote}{RESET_FORMAT}"
|
self.mr_remote = f"{COLOR_GREEN}{self.mr_remote}{RESET_FORMAT}"
|
||||||
# mainsail
|
# mainsail
|
||||||
mainsail_client_data = load_client_data("mainsail")
|
self.ms_local = get_local_client_version(self.mainsail_cient)
|
||||||
self.ms_local = get_local_client_version(mainsail_client_data)
|
self.ms_remote = get_remote_client_version(self.mainsail_cient)
|
||||||
self.ms_remote = get_remote_client_version(mainsail_client_data)
|
|
||||||
if self.ms_local == self.ms_remote:
|
if self.ms_local == self.ms_remote:
|
||||||
self.ms_local = f"{COLOR_GREEN}{self.ms_local}{RESET_FORMAT}"
|
self.ms_local = f"{COLOR_GREEN}{self.ms_local}{RESET_FORMAT}"
|
||||||
else:
|
else:
|
||||||
self.ms_local = f"{COLOR_YELLOW}{self.ms_local}{RESET_FORMAT}"
|
self.ms_local = f"{COLOR_YELLOW}{self.ms_local}{RESET_FORMAT}"
|
||||||
self.ms_remote = f"{COLOR_GREEN if self.ms_remote != 'ERROR' else COLOR_RED}{self.ms_remote}{RESET_FORMAT}"
|
self.ms_remote = f"{COLOR_GREEN if self.ms_remote != 'ERROR' else COLOR_RED}{self.ms_remote}{RESET_FORMAT}"
|
||||||
# fluidd
|
# fluidd
|
||||||
fluidd_client_data = load_client_data("fluidd")
|
self.fl_local = get_local_client_version(self.fluidd_client)
|
||||||
self.fl_local = get_local_client_version(fluidd_client_data)
|
self.fl_remote = get_remote_client_version(self.fluidd_client)
|
||||||
self.fl_remote = get_remote_client_version(fluidd_client_data)
|
|
||||||
if self.fl_local == self.fl_remote:
|
if self.fl_local == self.fl_remote:
|
||||||
self.fl_local = f"{COLOR_GREEN}{self.fl_local}{RESET_FORMAT}"
|
self.fl_local = f"{COLOR_GREEN}{self.fl_local}{RESET_FORMAT}"
|
||||||
else:
|
else:
|
||||||
self.fl_local = f"{COLOR_YELLOW}{self.fl_local}{RESET_FORMAT}"
|
self.fl_local = f"{COLOR_YELLOW}{self.fl_local}{RESET_FORMAT}"
|
||||||
self.fl_remote = f"{COLOR_GREEN if self.fl_remote != 'ERROR' else COLOR_RED}{self.fl_remote}{RESET_FORMAT}"
|
self.fl_remote = f"{COLOR_GREEN if self.fl_remote != 'ERROR' else COLOR_RED}{self.fl_remote}{RESET_FORMAT}"
|
||||||
# mainsail-config
|
# mainsail-config
|
||||||
mc_status = get_client_config_status(load_client_data("mainsail"))
|
mc_status = get_client_config_status(self.mainsail_cient)
|
||||||
self.mc_local = mc_status.get("local")
|
self.mc_local = mc_status.get("local")
|
||||||
self.mc_remote = mc_status.get("remote")
|
self.mc_remote = mc_status.get("remote")
|
||||||
if self.mc_local == self.mc_remote:
|
if self.mc_local == self.mc_remote:
|
||||||
@@ -180,7 +182,7 @@ class UpdateMenu(BaseMenu):
|
|||||||
self.mc_local = f"{COLOR_YELLOW}{self.mc_local}{RESET_FORMAT}"
|
self.mc_local = f"{COLOR_YELLOW}{self.mc_local}{RESET_FORMAT}"
|
||||||
self.mc_remote = f"{COLOR_GREEN}{self.mc_remote}{RESET_FORMAT}"
|
self.mc_remote = f"{COLOR_GREEN}{self.mc_remote}{RESET_FORMAT}"
|
||||||
# fluidd-config
|
# fluidd-config
|
||||||
fc_status = get_client_config_status(load_client_data("fluidd"))
|
fc_status = get_client_config_status(self.fluidd_client)
|
||||||
self.fc_local = fc_status.get("local")
|
self.fc_local = fc_status.get("local")
|
||||||
self.fc_remote = fc_status.get("remote")
|
self.fc_remote = fc_status.get("remote")
|
||||||
if self.fc_local == self.mc_remote:
|
if self.fc_local == self.mc_remote:
|
||||||
|
|||||||
57
kiauh/utils/git_utils.py
Normal file
57
kiauh/utils/git_utils.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import json
|
||||||
|
import urllib.request
|
||||||
|
from http.client import HTTPResponse
|
||||||
|
from json import JSONDecodeError
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from utils.logger import Logger
|
||||||
|
|
||||||
|
|
||||||
|
def get_tags(repo_path: str) -> List[str]:
|
||||||
|
try:
|
||||||
|
url = f"https://api.github.com/repos/{repo_path}/tags"
|
||||||
|
with urllib.request.urlopen(url) as r:
|
||||||
|
response: HTTPResponse = r
|
||||||
|
if response.getcode() != 200:
|
||||||
|
Logger.print_error(
|
||||||
|
f"Error retrieving tags: HTTP status code {response.getcode()}"
|
||||||
|
)
|
||||||
|
return []
|
||||||
|
|
||||||
|
data = json.loads(response.read())
|
||||||
|
return [item["name"] for item in data]
|
||||||
|
except (JSONDecodeError, TypeError) as e:
|
||||||
|
Logger.print_error(f"Error while processing the response: {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def get_latest_tag(repo_path: str) -> str:
|
||||||
|
"""
|
||||||
|
Gets the latest stable tag of a GitHub repostiory
|
||||||
|
:param repo_path: path of the GitHub repository - e.g. `<owner>/<name>`
|
||||||
|
:return: tag or empty string
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if len(latest_tag := get_tags(repo_path)) > 0:
|
||||||
|
return latest_tag[0]
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
except Exception:
|
||||||
|
Logger.print_error("Error while getting the latest tag")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def get_latest_unstable_tag(repo_path: str) -> str:
|
||||||
|
"""
|
||||||
|
Gets the latest unstable (alpha, beta, rc) tag of a GitHub repository
|
||||||
|
:param repo_path: path of the GitHub repository - e.g. `<owner>/<name>`
|
||||||
|
:return: tag or empty string
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if len(unstable_tags := [t for t in get_tags(repo_path) if "-" in t]) > 0:
|
||||||
|
return unstable_tags[0]
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
except Exception:
|
||||||
|
Logger.print_error("Error while getting the latest unstable tag")
|
||||||
|
raise
|
||||||
Reference in New Issue
Block a user