feat(ansible): scope picker in run form + create_run() DB inventory generation

This commit is contained in:
2026-06-05 18:49:02 -04:00
parent d906232eb2
commit 2c991eabd2
3 changed files with 70 additions and 20 deletions
+39 -5
View File
@@ -37,6 +37,8 @@ async def index():
@ansible_bp.get("/browse")
@require_role(UserRole.viewer)
async def browse():
from steward.models.ansible_inventory import AnsibleTarget, AnsibleGroup
all_sources = _get_sources()
source_data = []
for source in all_sources:
@@ -47,7 +49,21 @@ async def browse():
"playbooks": playbooks,
"inventories": inventories,
})
return await render_template("ansible/browse.html", source_data=source_data)
async with current_app.db_sessionmaker() as db:
targets = (await db.execute(
select(AnsibleTarget).order_by(AnsibleTarget.name)
)).scalars().all()
groups = (await db.execute(
select(AnsibleGroup).order_by(AnsibleGroup.name)
)).scalars().all()
return await render_template(
"ansible/browse.html",
source_data=source_data,
targets=targets,
groups=groups,
)
@ansible_bp.get("/browse/<source_name>/<path:playbook_path>")
@@ -72,19 +88,35 @@ async def view_playbook(source_name: str, playbook_path: str):
@ansible_bp.post("/runs")
@require_role(UserRole.operator)
async def create_run():
import json as _json
from steward.ansible.inventory_gen import fetch_scope_targets, generate_inventory
form = await request.form
playbook_path = form.get("playbook_path", "").strip()
source_name = form.get("source_name", "").strip()
inventory_path = form.get("inventory_path", "").strip()
inventory_scope = form.get("inventory_scope", "steward:all").strip()
if not playbook_path or not inventory_path:
return "playbook_path and inventory_path are required", 400
if not playbook_path:
return "playbook_path is required", 400
all_sources = _get_sources()
source = next((s for s in all_sources if s["name"] == source_name), None)
if source is None:
return "Source not found", 404
# Resolve inventory for this scope.
inventory_content: str | None = None
inventory_path: str | None = None
if inventory_scope.startswith("steward:"):
async with current_app.db_sessionmaker() as db:
targets = await fetch_scope_targets(db, inventory_scope)
inventory_content = _json.dumps(generate_inventory(targets))
elif inventory_scope.startswith("repo:"):
parts = inventory_scope.split(":", 2)
inventory_path = parts[2] if len(parts) == 3 else ""
else:
return "Invalid inventory_scope", 400
# Optional run parameters (all passed as argv by the executor — no shell).
extra_vars: list[str] = []
for line in (form.get("extra_vars", "") or "").splitlines():
@@ -116,6 +148,7 @@ async def create_run():
id=run_id,
playbook_path=playbook_path,
inventory_path=inventory_path,
inventory_scope=inventory_scope,
source_name=source_name,
triggered_by=session["user_id"],
status=AnsibleRunStatus.running,
@@ -131,9 +164,10 @@ async def create_run():
current_app._get_current_object(), # type: ignore[attr-defined]
run_id,
playbook_path,
inventory_path,
inventory_path or "",
source["path"],
params_or_none,
inventory_content,
)
)
task.add_done_callback(