mirror of
https://github.com/ublue-os/forge.git
synced 2025-04-08 07:53:43 +03:00
122 lines
4.5 KiB
Python
122 lines
4.5 KiB
Python
import ansible_runner
|
|
import re
|
|
import asyncio
|
|
import os
|
|
from nicegui import ui
|
|
from theme import GuiProgressSpinner
|
|
from utils import local_file_picker
|
|
|
|
ANSIBLE_EXTRA_VARS = None
|
|
|
|
|
|
# Ansible integration
|
|
@ui.refreshable # https://www.reddit.com/r/nicegui/comments/1bphjk5/comment/kx7l5kj/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button
|
|
async def load_configuration_file() -> None:
|
|
global ANSIBLE_EXTRA_VARS
|
|
result = await local_file_picker(
|
|
directory="/data", multiple=False, file_name_filter=".yml"
|
|
)
|
|
file_path = result[0]
|
|
with open(file_path, "r") as file:
|
|
data = file.read()
|
|
## Give feedback to user
|
|
ui.notify(f"You chose {file_path}")
|
|
## Display content
|
|
ui.code(content=data, language="yaml")
|
|
## Preserve configuration file path for ansible-playbook --extra-vars
|
|
ANSIBLE_EXTRA_VARS = f"@{file_path}"
|
|
|
|
|
|
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 = os.environ["ANSIBLE_DIR"]
|
|
playbook_path = f"{project_root}/playbooks/"
|
|
extra_vars_file = ANSIBLE_EXTRA_VARS
|
|
thread, runner = ansible_runner.interface.run_command_async(
|
|
executable_cmd="ansible-playbook",
|
|
cmdline_args=[
|
|
f"{playbook_path}/{playbook_name}",
|
|
# playbook_path + playbook_name,
|
|
"--extra-vars",
|
|
extra_vars_file,
|
|
],
|
|
)
|
|
# 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:
|
|
# 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
|
|
def content() -> None:
|
|
with ui.row().classes("w-full"):
|
|
with ui.row().classes("w-full"):
|
|
with ui.card().classes("h-full"):
|
|
ui.button(
|
|
text="Load configuration file",
|
|
on_click=lambda: load_configuration_file.refresh(),
|
|
icon="folder",
|
|
)
|
|
## show configuration file with ui.code
|
|
load_configuration_file()
|
|
with ui.row().classes("w-full"):
|
|
# First Row
|
|
with ui.card().classes("h-full"):
|
|
with ui.row().classes("no-wrap"):
|
|
ui.label("Build").classes("text-h5")
|
|
gui_build_progress = GuiProgressSpinner()
|
|
ui.button(
|
|
text="Clone project",
|
|
on_click=lambda: run_ansible_playbook(
|
|
playbook_name="project_clone.yml",
|
|
gui_log=gui_playbook_log,
|
|
gui_spinner=gui_build_progress,
|
|
),
|
|
)
|
|
ui.button(
|
|
text="Build project",
|
|
on_click=lambda: run_ansible_playbook(
|
|
"project_build.yml",
|
|
gui_log=gui_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")
|
|
gui_deploy_progress = GuiProgressSpinner
|
|
ui.button(
|
|
"Deploy VM",
|
|
on_click=lambda: ui.notify("This playbook is not implemented yet"),
|
|
)
|
|
|
|
with ui.row().classes("w-full"):
|
|
with ui.card().classes("w-full"):
|
|
ui.label("Playbook Log").classes("text-h6")
|
|
ui.button("Clear Log", on_click=lambda: gui_playbook_log.clear())
|
|
|
|
gui_playbook_log = ui.log().classes("w-full h-full")
|