integrate webserver into cli
All checks were successful
build / test (pull_request) Successful in 19s
All checks were successful
build / test (pull_request) Successful in 19s
This commit is contained in:
parent
79c61f61c7
commit
d60548dfc4
@ -3,9 +3,9 @@ import sys
|
|||||||
from types import ModuleType
|
from types import ModuleType
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from . import admin, secrets, update
|
from . import admin, secrets, update, webui
|
||||||
|
|
||||||
# from . import admin, config, secrets, update
|
# from . import admin, config, secrets, update, webui
|
||||||
from .errors import ClanError
|
from .errors import ClanError
|
||||||
from .ssh import cli as ssh_cli
|
from .ssh import cli as ssh_cli
|
||||||
|
|
||||||
@ -39,6 +39,9 @@ def main() -> None:
|
|||||||
)
|
)
|
||||||
update.register_parser(parser_update)
|
update.register_parser(parser_update)
|
||||||
|
|
||||||
|
parser_webui = subparsers.add_parser("webui", help="start webui")
|
||||||
|
webui.register_parser(parser_webui)
|
||||||
|
|
||||||
if argcomplete:
|
if argcomplete:
|
||||||
argcomplete.autocomplete(parser)
|
argcomplete.autocomplete(parser)
|
||||||
|
|
||||||
|
39
pkgs/clan-cli/clan_cli/webui/__init__.py
Normal file
39
pkgs/clan-cli/clan_cli/webui/__init__.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import argparse
|
||||||
|
from typing import Callable, NoReturn, Optional
|
||||||
|
|
||||||
|
start_server: Optional[Callable] = None
|
||||||
|
ServerImportError: Optional[ImportError] = None
|
||||||
|
try:
|
||||||
|
from .server import start_server
|
||||||
|
except ImportError as e:
|
||||||
|
ServerImportError = e
|
||||||
|
|
||||||
|
|
||||||
|
def fastapi_is_not_installed(_: argparse.Namespace) -> NoReturn:
|
||||||
|
assert ServerImportError is not None
|
||||||
|
print(
|
||||||
|
f"Dependencies for the webserver is not installed. The webui command has been disabled ({ServerImportError})"
|
||||||
|
)
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def register_parser(parser: argparse.ArgumentParser) -> None:
|
||||||
|
parser.add_argument("--port", type=int, default=2979, help="Port to listen on")
|
||||||
|
parser.add_argument("--host", type=str, default="::1", help="Host to listen on")
|
||||||
|
parser.add_argument(
|
||||||
|
"--no-open", action="store_true", help="Don't open the browser", default=False
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--reload", action="store_true", help="Don't reload on changes", default=False
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--log-level",
|
||||||
|
type=str,
|
||||||
|
default="info",
|
||||||
|
help="Log level",
|
||||||
|
choices=["critical", "error", "warning", "info", "debug", "trace"],
|
||||||
|
)
|
||||||
|
if start_server is None:
|
||||||
|
parser.set_defaults(func=fastapi_is_not_installed)
|
||||||
|
else:
|
||||||
|
parser.set_defaults(func=start_server)
|
41
pkgs/clan-cli/clan_cli/webui/server.py
Normal file
41
pkgs/clan-cli/clan_cli/webui/server.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import argparse
|
||||||
|
import time
|
||||||
|
import urllib.request
|
||||||
|
import webbrowser
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
|
from fastapi import FastAPI
|
||||||
|
|
||||||
|
# XXX: can we dynamically load this using nix develop?
|
||||||
|
from uvicorn import run
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/health")
|
||||||
|
async def read_root() -> str:
|
||||||
|
return "OK"
|
||||||
|
|
||||||
|
|
||||||
|
def defer_open_browser(base_url: str) -> None:
|
||||||
|
for i in range(5):
|
||||||
|
try:
|
||||||
|
urllib.request.urlopen(base_url + "/health")
|
||||||
|
break
|
||||||
|
except OSError:
|
||||||
|
time.sleep(i)
|
||||||
|
webbrowser.open(base_url)
|
||||||
|
|
||||||
|
|
||||||
|
def start_server(args: argparse.Namespace) -> None:
|
||||||
|
if not args.no_open:
|
||||||
|
Thread(
|
||||||
|
target=defer_open_browser, args=(f"http://[{args.host}]:{args.port}",)
|
||||||
|
).start()
|
||||||
|
run(
|
||||||
|
"clan_cli.webui.server:app",
|
||||||
|
host=args.host,
|
||||||
|
port=args.port,
|
||||||
|
log_level=args.log_level,
|
||||||
|
reload=args.reload,
|
||||||
|
)
|
@ -1,5 +1,7 @@
|
|||||||
{ age
|
{ age
|
||||||
, argcomplete
|
, argcomplete
|
||||||
|
, fastapi
|
||||||
|
, uvicorn
|
||||||
, bubblewrap
|
, bubblewrap
|
||||||
, installShellFiles
|
, installShellFiles
|
||||||
, nix
|
, nix
|
||||||
@ -22,7 +24,11 @@ let
|
|||||||
# evaluating the flake .#
|
# evaluating the flake .#
|
||||||
CLAN_OPTIONS_FILE = ./clan_cli/config/jsonschema/options.json;
|
CLAN_OPTIONS_FILE = ./clan_cli/config/jsonschema/options.json;
|
||||||
|
|
||||||
dependencies = [ argcomplete ];
|
dependencies = [
|
||||||
|
argcomplete # optional dependency: if not enabled, shell completion will not work
|
||||||
|
fastapi
|
||||||
|
uvicorn # optional dependencies: if not enabled, webui subcommand will not work
|
||||||
|
];
|
||||||
|
|
||||||
testDependencies = [
|
testDependencies = [
|
||||||
pytest
|
pytest
|
||||||
@ -73,7 +79,7 @@ python3.pkgs.buildPythonPackage {
|
|||||||
wheel
|
wheel
|
||||||
] ++ testDependencies;
|
] ++ testDependencies;
|
||||||
|
|
||||||
passthru.testDependencies = testDependencies;
|
passthru.testDependencies = dependencies ++ testDependencies;
|
||||||
|
|
||||||
makeWrapperArgs = [
|
makeWrapperArgs = [
|
||||||
"--set CLAN_FLAKE ${self}"
|
"--set CLAN_FLAKE ${self}"
|
||||||
|
Loading…
Reference in New Issue
Block a user