Implement /install

This commit is contained in:
Kai Vogelgesang 2022-09-22 21:01:40 +02:00
parent 7fa635170a
commit 226aba437a
Signed by: kai
GPG Key ID: 0A95D3B6E62C0879
7 changed files with 91 additions and 15 deletions

1
lua/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
out

19
lua/justfile Normal file
View File

@ -0,0 +1,19 @@
default:
@just --list
teal_files := "main.tl framebuffer.tl ringbuffer.tl"
build:
mkdir -p out
cp json.lua out
for file in {{teal_files}}; do \
tl gen $file; \
mv ${file%.tl}.lua out; \
done
alias b := build
clean:
rm -r out
alias c := clean

View File

@ -8,17 +8,40 @@ print("[MAIN] Init")
local enum SocketState local enum SocketState
"reset" "reset"
"connecting" -- currently unused "error"
"ok" "ok"
"viewer_connected"
end end
local BAD_STATES <const> : {SocketState: boolean} = {
["reset"] = true,
["error"] = true,
}
local type SocketStateCallback = function(new_state: SocketState)
local record Socket local record Socket
state: SocketState state: SocketState
bad_state: function(self: Socket): boolean
set_state: function(self: Socket, state: SocketState)
on_state_change: function(self: Socket, cb: SocketStateCallback)
_callback: SocketStateCallback
ws: http.Websocket ws: http.Websocket
end end
local socket: Socket = { local socket: Socket = {
state = "reset", state = "reset",
bad_state = function(self: Socket): boolean
return BAD_STATES[self.state] ~= nil
end,
set_state = function(self: Socket, state: SocketState)
self.state = state
self._callback(state)
end,
on_state_change = function(self: Socket, cb: SocketStateCallback)
self._callback = cb
end,
_callback = function(_: SocketState) end,
ws = nil, ws = nil,
} }
@ -26,13 +49,13 @@ local function send(message: string)
-- "message" needs to be valid JSON -- "message" needs to be valid JSON
-- otherwise the server will not accept it -- otherwise the server will not accept it
if socket.state ~= "ok" then return end if socket:bad_state() then return end
local r = { pcall(socket.ws.send, message) } local r = { pcall(socket.ws.send, message) }
if r[1] == false then if r[1] == false then
if (r[2] as string):sub(-11) == "closed file" then if (r[2] as string):sub(-11) == "closed file" then
socket.state = "reset" socket:set_state("reset")
elseif (r[2] as string):sub(-9) == "too large" then elseif (r[2] as string):sub(-9) == "too large" then
-- TODO handle -- TODO handle
-- the connection stays open though -- the connection stays open though
@ -66,22 +89,32 @@ end
-- Create tasks -- Create tasks
local bar_codes: { SocketState: {string} } = {
["reset"] = {"[WS] RST", "78870111"},
["error"] = {"[WS] ERR", "78870EEE"},
["ok"] = {"[WS] OK\x03", "78870DD5"},
["viewer_connected"] = {"[WS] CON", "78870999"},
}
socket:on_state_change(function(new_state: SocketState)
set_bar(table.unpack(bar_codes[new_state]))
end)
local ws_task = coroutine.create(function() local ws_task = coroutine.create(function()
while true do while true do
if socket.state == "reset" then if socket:bad_state() then
set_bar("[WS] RST", "78870111") --set_bar("[WS] RST", "78870111")
local r = http.websocket(ENDPOINT) local r = http.websocket(ENDPOINT)
if r ~= false then if r ~= false then
socket.ws = r as http.Websocket socket.ws = r as http.Websocket
set_bar("[WS] OK\x03", "78870DD5") --set_bar("[WS] OK\x03", "78870DD5")
socket.state = "ok" socket:set_state("ok")
else else
set_bar("[WS] ERR", "78870EEE") socket:set_state("error")
--set_bar("[WS] ERR", "78870EEE")
end end
end end
repeat sleep(1)
sleep(1)
until socket.state ~= "ok"
end end
end) end)
@ -89,7 +122,8 @@ local report_task = coroutine.create(function()
local last_report = -1.0 local last_report = -1.0
while true do while true do
local now = os.clock() local now = os.clock()
if now - last_report >= 0.05 then local interval = (socket.state == "viewer_connected") and 0.05 or 1
if now - last_report >= interval then
local message = json.encode({ local message = json.encode({
screen = buffer.serialize() screen = buffer.serialize()
}) })
@ -151,6 +185,9 @@ while shell_running do
end end
end end
if socket.state == "ok" then
socket.ws.close()
end
term.native = orig_native term.native = orig_native
term.redirect(term.native()) term.redirect(term.native())

1
server/lua Symbolic link
View File

@ -0,0 +1 @@
../lua/out

View File

@ -1,7 +1,8 @@
import asyncio import asyncio
import json import json
from fastapi import FastAPI, Request from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse from fastapi.staticfiles import StaticFiles
from fastapi.responses import HTMLResponse, PlainTextResponse
from .settings import settings from .settings import settings
from .user import user_auth from .user import user_auth
@ -16,6 +17,16 @@ app.mount("/map/", map_meta)
app.mount("/tiles/", map_tiles) app.mount("/tiles/", map_tiles)
app.mount("/ipmi/", monitoring) app.mount("/ipmi/", monitoring)
installer = j2env.get_template("install.lua").render(deploy_path=settings.deploy_path)
@app.get("/install")
async def get_installer():
return PlainTextResponse(installer)
app.mount("/lua/", StaticFiles(directory=settings.lua_out_path))
@app.on_event("startup") @app.on_event("startup")
async def on_startup(): async def on_startup():
@ -26,8 +37,6 @@ frontend = FastAPI()
manifest = dict() manifest = dict()
if not settings.dev_mode: if not settings.dev_mode:
from fastapi.staticfiles import StaticFiles
with open(f"{settings.frontend_path}/manifest.json", "r") as f: with open(f"{settings.frontend_path}/manifest.json", "r") as f:
manifest = json.load(f) manifest = json.load(f)

View File

@ -7,6 +7,9 @@ class Settings(BaseSettings):
frontend_path: str = "frontend" frontend_path: str = "frontend"
unmined_out_path: str = "unmined-out" unmined_out_path: str = "unmined-out"
lua_out_path: str = "lua"
deploy_path: str = "http://localhost:8000"
settings = Settings() settings = Settings()

View File

@ -0,0 +1,6 @@
local path = "{{ deploy_path }}"
files = { "main.lua", "json.lua", "framebuffer.lua", "ringbuffer.lua" }
for _, file in ipairs(files) do
fs.delete(file)
shell.run(("wget %s/lua/%s"):format(path, file))
end