feat: add crowsnest update

Signed-off-by: Dominik Willner <th33xitus@gmail.com>
This commit is contained in:
dw-0
2024-05-01 18:42:36 +02:00
parent 2d858cf241
commit a089d34f8c
4 changed files with 102 additions and 8 deletions

View File

@@ -12,16 +12,28 @@ import shutil
import textwrap import textwrap
from pathlib import Path from pathlib import Path
from subprocess import run, CalledProcessError from subprocess import run, CalledProcessError
from typing import List from typing import List, Dict, Literal, Union
from components.crowsnest import CROWSNEST_REPO, CROWSNEST_DIR from components.crowsnest import CROWSNEST_REPO, CROWSNEST_DIR
from components.klipper.klipper import Klipper from components.klipper.klipper import Klipper
from core.instance_manager.instance_manager import InstanceManager from core.instance_manager.instance_manager import InstanceManager
from utils.common import get_install_status
from utils.constants import COLOR_CYAN, RESET_FORMAT, CURRENT_USER from utils.constants import COLOR_CYAN, RESET_FORMAT, CURRENT_USER
from utils.git_utils import git_clone_wrapper from utils.git_utils import (
git_clone_wrapper,
get_repo_name,
get_local_commit,
get_remote_commit,
git_pull_wrapper,
)
from utils.input_utils import get_confirm from utils.input_utils import get_confirm
from utils.logger import Logger from utils.logger import Logger
from utils.system_utils import check_package_install, install_system_packages from utils.system_utils import (
check_package_install,
install_system_packages,
parse_packages_from_file,
update_system_package_lists,
)
def install_crowsnest() -> None: def install_crowsnest() -> None:
@@ -89,7 +101,54 @@ def install_crowsnest() -> None:
def update_crowsnest() -> None: def update_crowsnest() -> None:
pass try:
stop_cn = "sudo systemctl stop crowsnest"
restart_cn = "sudo systemctl restart crowsnest"
Logger.print_status("Stopping Crowsnest service ...")
run(stop_cn, shell=True, check=True)
if not CROWSNEST_DIR.exists():
git_clone_wrapper(CROWSNEST_REPO, "master", CROWSNEST_DIR)
else:
Logger.print_status("Updating Crowsnest ...")
git_pull_wrapper(CROWSNEST_REPO, CROWSNEST_DIR)
script = CROWSNEST_DIR.joinpath("tools/install.sh")
deps = parse_packages_from_file(script)
packages = check_package_install(deps)
update_system_package_lists(silent=False)
install_system_packages(packages)
Logger.print_status("Restarting Crowsnest service ...")
run(restart_cn, shell=True, check=True)
Logger.print_ok("Crowsnest updated successfully.", end="\n\n")
except CalledProcessError as e:
Logger.print_error(f"Something went wrong! Please try again...\n{e}")
return
def get_crowsnest_status() -> (
Dict[
Literal["status", "status_code", "repo", "local", "remote"],
Union[str, int],
]
):
files = [
Path("/usr/local/bin/crowsnest"),
Path("/etc/logrotate.d/crowsnest"),
Path("/etc/systemd/system/crowsnest.service"),
]
status = get_install_status(CROWSNEST_DIR, files)
return {
"status": status.get("status"),
"status_code": status.get("status_code"),
"repo": get_repo_name(CROWSNEST_DIR),
"local": get_local_commit(CROWSNEST_DIR),
"remote": get_remote_commit(CROWSNEST_DIR),
}
def remove_crowsnest() -> None: def remove_crowsnest() -> None:

View File

@@ -10,6 +10,7 @@
import textwrap import textwrap
from typing import Type, Optional from typing import Type, Optional
from components.crowsnest.crowsnest import get_crowsnest_status
from components.klipper.klipper_utils import get_klipper_status from components.klipper.klipper_utils import get_klipper_status
from components.log_uploads.menus.log_upload_menu import LogUploadMenu 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
@@ -90,16 +91,23 @@ class MainMenu(BaseMenu):
self.ms_status = get_client_status(MainsailData()) self.ms_status = get_client_status(MainsailData())
self.fl_status = get_client_status(FluiddData()) self.fl_status = get_client_status(FluiddData())
self.cc_status = get_current_client_config([MainsailData(), FluiddData()]) self.cc_status = get_current_client_config([MainsailData(), FluiddData()])
self._update_status("cn", get_crowsnest_status)
def _update_status(self, status_name: str, status_fn: callable) -> None: def _update_status(self, status_name: str, status_fn: callable) -> None:
status_data = status_fn() status_data = status_fn()
status = status_data.get("status") status = status_data.get("status")
code = status_data.get("status_code") code = status_data.get("status_code")
instances = f" {status_data.get('instances')}" if code == 1 else ""
instance_count = status_data.get("instances")
count: str = ""
if instance_count and code == 1:
count = f" {instance_count}"
setattr( setattr(
self, self,
f"{status_name}_status", f"{status_name}_status",
self._format_status_by_code(code, status, instances), self._format_status_by_code(code, status, count),
) )
setattr( setattr(
self, self,

View File

@@ -10,6 +10,7 @@
import textwrap import textwrap
from typing import Type, Optional from typing import Type, Optional
from components.crowsnest.crowsnest import get_crowsnest_status, update_crowsnest
from components.klipper.klipper_setup import update_klipper from components.klipper.klipper_setup import update_klipper
from components.klipper.klipper_utils import ( from components.klipper.klipper_utils import (
get_klipper_status, get_klipper_status,
@@ -57,6 +58,8 @@ class UpdateMenu(BaseMenu):
self.mc_remote = f"{COLOR_WHITE}{RESET_FORMAT}" self.mc_remote = f"{COLOR_WHITE}{RESET_FORMAT}"
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.cn_local = f"{COLOR_WHITE}{RESET_FORMAT}"
self.cn_remote = f"{COLOR_WHITE}{RESET_FORMAT}"
self.mainsail_client = MainsailData() self.mainsail_client = MainsailData()
self.fluidd_client = FluiddData() self.fluidd_client = FluiddData()
@@ -111,7 +114,7 @@ class UpdateMenu(BaseMenu):
| Other: |---------------|---------------| | Other: |---------------|---------------|
| 7) KlipperScreen | | | | 7) KlipperScreen | | |
| 8) Mobileraker | | | | 8) Mobileraker | | |
| 9) Crowsnest | | | | 9) Crowsnest | {self.cn_local:<22} | {self.cn_remote:<22} |
| |-------------------------------| | |-------------------------------|
| 10) System | | | 10) System | |
""" """
@@ -143,7 +146,8 @@ class UpdateMenu(BaseMenu):
def update_mobileraker(self, **kwargs): ... def update_mobileraker(self, **kwargs): ...
def update_crowsnest(self, **kwargs): ... def update_crowsnest(self, **kwargs):
update_crowsnest()
def upgrade_system_packages(self, **kwargs): ... def upgrade_system_packages(self, **kwargs): ...
@@ -189,6 +193,13 @@ class UpdateMenu(BaseMenu):
) )
self.fc_remote = f"{COLOR_GREEN}{fc_status.get('remote')}{RESET_FORMAT}" self.fc_remote = f"{COLOR_GREEN}{fc_status.get('remote')}{RESET_FORMAT}"
# crowsnest
cn_status = get_crowsnest_status()
self.cn_local = self.format_local_status(
cn_status.get("local"), cn_status.get("remote")
)
self.cn_remote = f"{COLOR_GREEN}{cn_status.get('remote')}{RESET_FORMAT}"
def format_local_status(self, local_version, remote_version) -> str: def format_local_status(self, local_version, remote_version) -> str:
if local_version == remote_version: if local_version == remote_version:
return f"{COLOR_GREEN}{local_version}{RESET_FORMAT}" return f"{COLOR_GREEN}{local_version}{RESET_FORMAT}"

View File

@@ -55,6 +55,22 @@ def check_install_dependencies(deps: List[str]) -> None:
install_system_packages(requirements) install_system_packages(requirements)
def get_install_status(
repo_dir: Path, opt_files: List[Path]
) -> Dict[Literal["status", "status_code", "instances"], Union[str, int]]:
status = [repo_dir.exists()]
for f in opt_files:
status.append(f.exists())
if all(status):
return {"status": "Installed!", "status_code": 1}
elif not any(status):
return {"status": "Not installed!", "status_code": 2}
else:
return {"status": "Incomplete!", "status_code": 3}
def get_install_status_common( def get_install_status_common(
instance_type: Type[BaseInstance], repo_dir: Path, env_dir: Path instance_type: Type[BaseInstance], repo_dir: Path, env_dir: Path
) -> Dict[Literal["status", "status_code", "instances"], Union[str, int]]: ) -> Dict[Literal["status", "status_code", "instances"], Union[str, int]]: