mirror of
https://github.com/ublue-os/forge.git
synced 2025-04-21 05:53:45 +03:00
wip - refactoring and implementing 'real-time' log output
This commit is contained in:
parent
dd001f4fe5
commit
50395caec7
|
@ -1,9 +1,9 @@
|
|||
import ansible_runner
|
||||
import re
|
||||
import asyncio
|
||||
import time
|
||||
from nicegui import ui
|
||||
from utils import get_project_root, local_file_picker, progress_spinner
|
||||
from theme import GuiProgressSpinner
|
||||
from utils import get_project_root, local_file_picker
|
||||
|
||||
ANSIBLE_EXTRA_VARS = None
|
||||
|
||||
|
@ -25,14 +25,12 @@ async def load_configuration_file() -> None:
|
|||
ANSIBLE_EXTRA_VARS = f'"@{file_path}"'
|
||||
|
||||
|
||||
async def run_ansible_playbook(
|
||||
playbook_name: str,
|
||||
ngui_log: ui.log,
|
||||
ngui_spinner: progress_spinner,
|
||||
) -> None:
|
||||
ngui_spinner.enable_progress()
|
||||
# make sure spinner is displayed
|
||||
await asyncio.sleep(1)
|
||||
async def run_ansible_playbook(playbook_name: str, gui_log: ui.log, gui_spinner: GuiProgressSpinner) -> None:
|
||||
# Clear log console
|
||||
gui_log.clear()
|
||||
# Enable spinner
|
||||
gui_spinner.enable()
|
||||
# Run ansible playbook
|
||||
project_root = str(get_project_root())
|
||||
playbook_path = project_root + "/ansible/playbooks/"
|
||||
inventory_path = project_root + "/ansible/inventory.yml"
|
||||
|
@ -47,16 +45,26 @@ async def run_ansible_playbook(
|
|||
extra_vars_file,
|
||||
],
|
||||
)
|
||||
# clear log
|
||||
ngui_log.clear()
|
||||
# regex to remove color characters from response until clear how to display them in a log
|
||||
ansi_escape = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-9;#]+[mGK]?)")
|
||||
# Parse and display output from ansible playbook
|
||||
## Remove color characters from response until clear how to display them in a log
|
||||
output_parser = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-9;#]+[mGK]?)")
|
||||
# show log from asynchronous job
|
||||
processed_events = set() # Set to store processed events
|
||||
while runner.rc is None:
|
||||
for event in runner.events:
|
||||
ansible_log = format(ansi_escape.sub("", event["stdout"]))
|
||||
ngui_log.push(ansible_log)
|
||||
ngui_spinner.disable_progress()
|
||||
# Make sure log is displayed during playbook run
|
||||
await asyncio.sleep(0.1)
|
||||
# Check if event has been processed already
|
||||
event_key = (event['uuid'], event['counter'])
|
||||
if event_key not in processed_events:
|
||||
# Add event to processed set
|
||||
processed_events.add(event_key)
|
||||
# Process event
|
||||
ansible_log = format(output_parser.sub("", event["stdout"]))
|
||||
# Push log to ui
|
||||
gui_log.push(ansible_log)
|
||||
# Disable spinner
|
||||
gui_spinner.disable()
|
||||
|
||||
|
||||
# Page content
|
||||
|
@ -76,28 +84,28 @@ def content() -> None:
|
|||
with ui.card().classes("h-full"):
|
||||
with ui.row().classes("no-wrap"):
|
||||
ui.label("Build").classes("text-h5")
|
||||
build_progress = progress_spinner()
|
||||
gui_build_progress = GuiProgressSpinner()
|
||||
ui.button(
|
||||
text="Clone project",
|
||||
on_click=lambda: run_ansible_playbook(
|
||||
playbook_name="project_clone.yml",
|
||||
ngui_log=playbook_log,
|
||||
ngui_spinner=build_progress,
|
||||
gui_log=playbook_log,
|
||||
gui_spinner=gui_build_progress,
|
||||
),
|
||||
)
|
||||
ui.button(
|
||||
text="Build project",
|
||||
on_click=lambda: run_ansible_playbook(
|
||||
"project_build.yml",
|
||||
ngui_log=playbook_log,
|
||||
ngui_spinner=build_progress,
|
||||
gui_log=playbook_log,
|
||||
gui_spinner=gui_build_progress,
|
||||
),
|
||||
)
|
||||
# Second Row
|
||||
with ui.card().classes("h-full"):
|
||||
with ui.row().classes("no-wrap"):
|
||||
ui.label("Deploy").classes("text-h6")
|
||||
deploy_progress = progress_spinner()
|
||||
gui_deploy_progress = GuiProgressSpinner
|
||||
ui.button(
|
||||
"Deploy VM",
|
||||
on_click=lambda: ui.notify("This playbook is not implemented yet"),
|
||||
|
|
|
@ -1,10 +1,28 @@
|
|||
from contextlib import contextmanager
|
||||
|
||||
from menu import menu
|
||||
|
||||
from nicegui import ui
|
||||
|
||||
|
||||
class GuiProgressSpinner(ui.spinner):
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
type: str = "dots",
|
||||
size: str = "lg",
|
||||
color: str | None = "red",
|
||||
thickness: float = 5
|
||||
) -> None:
|
||||
super().__init__(type, size=size, color=color, thickness=thickness)
|
||||
with self, ui.spinner():
|
||||
self.visible = False
|
||||
|
||||
def enable(self) -> None:
|
||||
self.set_visibility(True)
|
||||
|
||||
def disable(self) -> None:
|
||||
self.set_visibility(False)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def frame(navigation_title: str, enable_right_drawer: bool = False):
|
||||
"""Custom page frame to share the same styling and behavior across all pages"""
|
||||
|
|
|
@ -116,25 +116,5 @@ class local_file_picker(ui.dialog):
|
|||
self.submit([r["path"] for r in rows])
|
||||
|
||||
|
||||
class progress_spinner(ui.spinner):
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
type: str = "dots",
|
||||
size: str = "lg",
|
||||
color: str | None = "red",
|
||||
thickness: float = 5,
|
||||
) -> None:
|
||||
super().__init__(type, size=size, color=color, thickness=thickness)
|
||||
with self, ui.spinner():
|
||||
self.visible = False
|
||||
|
||||
def enable_progress(self) -> None:
|
||||
self.set_visibility(True)
|
||||
|
||||
def disable_progress(self) -> None:
|
||||
self.set_visibility(False)
|
||||
|
||||
|
||||
def get_project_root() -> Path:
|
||||
return Path(__file__).parent.parent
|
||||
|
|
Loading…
Reference in a new issue