/api/clan_modules: init
- add GET /api/clan_modules entry point returning a list of modules available for import
This commit is contained in:
39
pkgs/clan-cli/clan_cli/clan_modules.py
Normal file
39
pkgs/clan-cli/clan_cli/clan_modules.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import json
|
||||||
|
import subprocess
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from clan_cli.dirs import get_clan_flake_toplevel
|
||||||
|
from clan_cli.nix import nix_eval
|
||||||
|
|
||||||
|
|
||||||
|
def get_clan_module_names(
|
||||||
|
flake: Optional[Path] = None,
|
||||||
|
) -> tuple[list[str], Optional[str]]:
|
||||||
|
"""
|
||||||
|
Get the list of clan modules from the clan-core flake input
|
||||||
|
"""
|
||||||
|
if flake is None:
|
||||||
|
flake = get_clan_flake_toplevel()
|
||||||
|
proc = subprocess.run(
|
||||||
|
nix_eval(
|
||||||
|
[
|
||||||
|
"--impure",
|
||||||
|
"--show-trace",
|
||||||
|
"--expr",
|
||||||
|
f"""
|
||||||
|
let
|
||||||
|
flake = builtins.getFlake (toString {flake});
|
||||||
|
in
|
||||||
|
builtins.attrNames flake.inputs.clan-core.clanModules
|
||||||
|
""",
|
||||||
|
],
|
||||||
|
),
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
cwd=flake,
|
||||||
|
)
|
||||||
|
if proc.returncode != 0:
|
||||||
|
return [], proc.stderr
|
||||||
|
module_names = json.loads(proc.stdout)
|
||||||
|
return module_names, None
|
||||||
@@ -8,7 +8,7 @@ from fastapi.staticfiles import StaticFiles
|
|||||||
from ..errors import ClanError
|
from ..errors import ClanError
|
||||||
from .assets import asset_path
|
from .assets import asset_path
|
||||||
from .error_handlers import clan_error_handler
|
from .error_handlers import clan_error_handler
|
||||||
from .routers import flake, health, machines, root, vms
|
from .routers import clan_modules, flake, health, machines, root, vms
|
||||||
|
|
||||||
origins = [
|
origins = [
|
||||||
"http://localhost:3000",
|
"http://localhost:3000",
|
||||||
@@ -26,6 +26,7 @@ def setup_app() -> FastAPI:
|
|||||||
allow_methods=["*"],
|
allow_methods=["*"],
|
||||||
allow_headers=["*"],
|
allow_headers=["*"],
|
||||||
)
|
)
|
||||||
|
app.include_router(clan_modules.router)
|
||||||
app.include_router(flake.router)
|
app.include_router(flake.router)
|
||||||
app.include_router(health.router)
|
app.include_router(health.router)
|
||||||
app.include_router(machines.router)
|
app.include_router(machines.router)
|
||||||
|
|||||||
21
pkgs/clan-cli/clan_cli/webui/routers/clan_modules.py
Normal file
21
pkgs/clan-cli/clan_cli/webui/routers/clan_modules.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Logging setup
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from fastapi import APIRouter, HTTPException
|
||||||
|
|
||||||
|
from clan_cli.clan_modules import get_clan_module_names
|
||||||
|
|
||||||
|
from ..schemas import (
|
||||||
|
ClanModulesResponse,
|
||||||
|
)
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/api/clan_modules")
|
||||||
|
async def list_clan_modules() -> ClanModulesResponse:
|
||||||
|
module_names, error = get_clan_module_names()
|
||||||
|
if error is not None:
|
||||||
|
raise HTTPException(status_code=400, detail=error)
|
||||||
|
return ClanModulesResponse(clan_modules=module_names)
|
||||||
@@ -13,6 +13,10 @@ class Status(Enum):
|
|||||||
UNKNOWN = "unknown"
|
UNKNOWN = "unknown"
|
||||||
|
|
||||||
|
|
||||||
|
class ClanModulesResponse(BaseModel):
|
||||||
|
clan_modules: list[str]
|
||||||
|
|
||||||
|
|
||||||
class Machine(BaseModel):
|
class Machine(BaseModel):
|
||||||
name: str
|
name: str
|
||||||
status: Status
|
status: Status
|
||||||
|
|||||||
17
pkgs/clan-cli/tests/test_clan_modules.py
Normal file
17
pkgs/clan-cli/tests/test_clan_modules.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from api import TestClient
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.impure()
|
||||||
|
def test_configure_machine(api: TestClient, test_flake_with_core: Path) -> None:
|
||||||
|
# retrieve the list of available clanModules
|
||||||
|
response = api.get("/api/clan_modules")
|
||||||
|
response_json = response.json()
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert isinstance(response_json, dict)
|
||||||
|
assert "clan_modules" in response_json
|
||||||
|
assert len(response_json["clan_modules"]) > 0
|
||||||
|
# ensure all entries are a string
|
||||||
|
assert all(isinstance(x, str) for x in response_json["clan_modules"])
|
||||||
Reference in New Issue
Block a user