Skip to content

Commit 0918194

Browse files
authored
Initial backend (#1)
* Update vite to address high severity vulnerability * Add support for a backend server that optionally serves the frontend if it is already built
1 parent e92a32c commit 0918194

5 files changed

Lines changed: 140 additions & 113 deletions

File tree

layout/carthage_plugin.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
1-
# Copyright (C) 2026, Hadron Industries.
2-
# Carthage is free software; you can redistribute it and/or modify
3-
# it under the terms of the GNU Lesser General Public License version 3
4-
# as published by the Free Software Foundation. It is distributed
5-
# WITHOUT ANY WARRANTY; without even the implied warranty of
6-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file
7-
# LICENSE for details.
81

92
from carthage import inject, Injector
103
from . import layout
4+
from .web_backend import start_web_server, web_server_key
115

126
@inject(injector=Injector)
137
def carthage_plugin(injector):
148
injector.add_provider(layout.layout)
9+
injector.add_provider(web_server_key, start_web_server)
10+

layout/carthage_plugin.yml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
1-
# Copyright (C) 2026, Hadron Industries.
2-
# Carthage is free software; you can redistribute it and/or modify
3-
# it under the terms of the GNU Lesser General Public License version 3
4-
# as published by the Free Software Foundation. It is distributed
5-
# WITHOUT ANY WARRANTY; without even the implied warranty of
6-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file
7-
# LICENSE for details.
8-
91
name: viper-whs
2+
dependencies:
3+
- deb: python3-fastapi
104
config:
115
authorized_keys: authorized_keys
126
base_dir: /srv/viper-whs

layout/python/layout.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,3 @@
1-
# Copyright (C) 2026, Hadron Industries.
2-
# Carthage is free software; you can redistribute it and/or modify
3-
# it under the terms of the GNU Lesser General Public License version 3
4-
# as published by the Free Software Foundation. It is distributed
5-
# WITHOUT ANY WARRANTY; without even the implied warranty of
6-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file
7-
# LICENSE for details.
8-
91

102
from carthage import *
113
import carthage.libvirt
@@ -15,13 +7,17 @@
157
from carthage.network import V4Config
168
from carthage_base import *
179
from .images import WhsBaseImage, whs_vm_image
10+
from .web_backend import web_server_key
1811

1912

2013
class layout(CarthageLayout):
2114
layout_name = 'viper-whs'
2215
domain = 'whs.local'
2316
from .images import WhsBaseImage, whs_vm_image
2417

18+
async def async_ready(self):
19+
await self.ainjector.get_instance_async(web_server_key)
20+
await super().async_ready()
2521
@provides('bridge_net')
2622
class net(NetworkModel):
2723
bridge_name = 'whs-lab'

layout/python/web_backend.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import asyncio
2+
import os
3+
from typing import Annotated
4+
import uvicorn
5+
from fastapi import FastAPI, APIRouter, Depends, Request
6+
from fastapi.staticfiles import StaticFiles
7+
from carthage import AsyncInjector, inject, InjectionKey, CarthagePlugin
8+
from carthage.modeling import CarthageLayout
9+
10+
def get_ainjector(request:Request)->AsyncInjector:
11+
return request.app.state.ainjector
12+
13+
ainjector_dependency = Annotated[AsyncInjector, Depends(get_ainjector)]
14+
15+
16+
api_v1 = APIRouter(prefix="/api/v1")
17+
18+
@api_v1.get("/devices")
19+
async def get_devices(ainjector:ainjector_dependency):
20+
raise NotImplementedError
21+
22+
@inject(
23+
layout=InjectionKey(CarthageLayout, _ready=False),
24+
plugin=InjectionKey(CarthagePlugin, name='viper-whs'))
25+
async def start_web_server(layout, plugin):
26+
app = FastAPI()
27+
app.state.ainjector = layout.ainjector
28+
app.include_router(api_v1)
29+
if (plugin.resource_dir/'../dist').exists():
30+
breakpoint()
31+
app.mount('/', StaticFiles(directory=plugin.resource_dir/'../dist', html=True), name='frontend')
32+
config = uvicorn.Config(app,
33+
port=int(os.environ.get('PORT', 8080)),
34+
host='0.0.0.0',
35+
)
36+
server = uvicorn.Server(config)
37+
asyncio.get_event_loop().create_task(server.serve())
38+
39+
web_server_key = InjectionKey('viper_whs.webserver')

0 commit comments

Comments
 (0)