From aa14e7ddc7f5214df8d337e31766a1b2406855e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Fri, 25 Aug 2023 11:39:46 +0200 Subject: [PATCH] generate openapi --- pkgs/clan-cli/bin/gen-openapi | 37 +++++++++++++++++++ pkgs/clan-cli/clan_cli/webui/app.py | 19 ++++++++-- .../clan-cli/clan_cli/webui/routers/health.py | 2 +- pkgs/clan-cli/default.nix | 7 ++++ pkgs/clan-cli/flake-module.nix | 1 + 5 files changed, 61 insertions(+), 5 deletions(-) create mode 100755 pkgs/clan-cli/bin/gen-openapi diff --git a/pkgs/clan-cli/bin/gen-openapi b/pkgs/clan-cli/bin/gen-openapi new file mode 100755 index 00000000..76b5a2e5 --- /dev/null +++ b/pkgs/clan-cli/bin/gen-openapi @@ -0,0 +1,37 @@ +#!/usr/bin/env python +import argparse +import json +import sys +from pathlib import Path + +from uvicorn.importer import import_from_string + + +def main() -> None: + parser = argparse.ArgumentParser(prog="gen-openapi") + parser.add_argument( + "app", help='App import string. Eg. "main:app"', default="main:app" + ) + parser.add_argument("--app-dir", help="Directory containing the app", default=None) + parser.add_argument( + "--out", help="Output file ending in .json", default="openapi.json" + ) + args = parser.parse_args() + + if args.app_dir is not None: + print(f"adding {args.app_dir} to sys.path") + sys.path.insert(0, args.app_dir) + + print(f"importing app from {args.app}") + app = import_from_string(args.app) + openapi = app.openapi() + version = openapi.get("openapi", "unknown version") + + print(f"writing openapi spec v{version}") + out = Path(args.out) + out.parent.mkdir(parents=True, exist_ok=True) + out.write_text(json.dumps(openapi, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/pkgs/clan-cli/clan_cli/webui/app.py b/pkgs/clan-cli/clan_cli/webui/app.py index 7ad39bbb..09b1741e 100644 --- a/pkgs/clan-cli/clan_cli/webui/app.py +++ b/pkgs/clan-cli/clan_cli/webui/app.py @@ -1,8 +1,19 @@ from fastapi import FastAPI +from fastapi.routing import APIRoute from .routers import health, machines, root -app = FastAPI() -app.include_router(health.router) -app.include_router(machines.router) -app.include_router(root.router) + +def setup_app() -> FastAPI: + app = FastAPI() + app.include_router(health.router) + app.include_router(machines.router) + app.include_router(root.router) + + for route in app.routes: + if isinstance(route, APIRoute): + route.operation_id = route.name # in this case, 'read_items' + return app + + +app = setup_app() diff --git a/pkgs/clan-cli/clan_cli/webui/routers/health.py b/pkgs/clan-cli/clan_cli/webui/routers/health.py index d734e121..5c521f59 100644 --- a/pkgs/clan-cli/clan_cli/webui/routers/health.py +++ b/pkgs/clan-cli/clan_cli/webui/routers/health.py @@ -3,6 +3,6 @@ from fastapi import APIRouter router = APIRouter() -@router.get("/health") +@router.get("/health", include_in_schema=False) async def health() -> str: return "OK" diff --git a/pkgs/clan-cli/default.nix b/pkgs/clan-cli/default.nix index de9dfb29..f6e63d75 100644 --- a/pkgs/clan-cli/default.nix +++ b/pkgs/clan-cli/default.nix @@ -73,6 +73,13 @@ python3.pkgs.buildPythonPackage { NIX_STATE_DIR=$TMPDIR/nix ${checkPython}/bin/python -m pytest -s ./tests touch $out ''; + passthru.clan-openapi = runCommand "clan-openapi" { } '' + cp -r ${source} ./src + chmod +w -R ./src + cd ./src + ${checkPython}/bin/python ./bin/gen-openapi --out $out/openapi.json --app-dir . clan_cli.webui.app:app + touch $out + ''; passthru.devDependencies = [ setuptools diff --git a/pkgs/clan-cli/flake-module.nix b/pkgs/clan-cli/flake-module.nix index c4a9c1f8..2ffba47d 100644 --- a/pkgs/clan-cli/flake-module.nix +++ b/pkgs/clan-cli/flake-module.nix @@ -9,6 +9,7 @@ inherit self; zerotierone = self'.packages.zerotierone; }; + clan-openapi = self'.packages.clan-cli.clan-openapi; default = self'.packages.clan-cli; ## Optional dependencies for clan cli, we re-expose them here to make sure they all build.