diff --git a/README.md b/README.md index e2888984..8a83bb12 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,18 @@ A simplistic, opinionated remote update server implementing hawkBit™'s [DDI AP ### Installation 1. Install dependencies using [Poetry](https://python-poetry.org/): + ```bash poetry install ``` -2. Launch gooseBit: + +2. Create the database: + + ```bash + poetry run aerich upgrade + ``` + +3. Launch gooseBit: ```bash python main.py ``` diff --git a/goosebit/__init__.py b/goosebit/__init__.py index bc04a887..1c72e5a9 100644 --- a/goosebit/__init__.py +++ b/goosebit/__init__.py @@ -1,5 +1,6 @@ import importlib.metadata from contextlib import asynccontextmanager +from logging import getLogger from typing import Annotated from fastapi import Depends, FastAPI @@ -16,12 +17,17 @@ from goosebit.ui.static import static from goosebit.ui.templates import templates +logger = getLogger(__name__) + @asynccontextmanager async def lifespan(_: FastAPI): - await db.init() + db_ready = await db.init() + if not db_ready: + logger.exception("DB does not exist, try running `poetry run aerich upgrade`.") await metrics.init() - yield + if db_ready: + yield await db.close() diff --git a/goosebit/db/__init__.py b/goosebit/db/__init__.py index f5f0cc9b..e187f781 100644 --- a/goosebit/db/__init__.py +++ b/goosebit/db/__init__.py @@ -1,10 +1,21 @@ +from logging import getLogger + from tortoise import Tortoise +from tortoise.exceptions import OperationalError from goosebit.db.config import TORTOISE_CONF +from goosebit.db.models import Device + +logger = getLogger(__name__) -async def init(): +async def init() -> bool: await Tortoise.init(config=TORTOISE_CONF) + try: + await Device.first() + except OperationalError: + return False + return True async def close(): diff --git a/goosebit/updates/__init__.py b/goosebit/updates/__init__.py index b2c08d1e..51c1c6dd 100644 --- a/goosebit/updates/__init__.py +++ b/goosebit/updates/__init__.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import shutil from pathlib import Path from urllib.parse import unquote, urlparse @@ -10,6 +12,7 @@ from goosebit.db.models import Hardware, Software from goosebit.updater.manager import UpdateManager +from ..settings import config from . import swdesc @@ -42,7 +45,8 @@ async def create_software_update(uri: str, temp_file: Path | None) -> Software: # for local file: rename temp file to final name if parsed_uri.scheme == "file": - path = _unique_path(parsed_uri) + filename = Path(url2pathname(unquote(parsed_uri.path))).name + path = config.artifacts_dir.joinpath(update_info["hash"], filename) path.parent.mkdir(parents=True, exist_ok=True) shutil.copy(temp_file, path) uri = path.absolute().as_uri() @@ -85,20 +89,6 @@ async def _is_software_colliding(update_info): return is_colliding -def _unique_path(uri): - path = Path(url2pathname(unquote(uri.path))) - if not path.exists(): - return path - - counter = 1 - new_path = path.with_name(f"{path.stem}-{counter}{path.suffix}") - while new_path.exists(): - counter += 1 - new_path = path.with_name(f"{path.stem}-{counter}{path.suffix}") - - return new_path - - async def generate_chunk(request: Request, updater: UpdateManager) -> list: _, software = await updater.get_update() if software is None: