Skip to content

api_module_classes has no fleet-aggregating counterpart (external callers only see one host) #68

Description

@thusser

Summary

api_module_classes (GET /api/modules/classes/, modules/views.py:752-762) has no fleet-aggregating counterpart, unlike every other cross-host-consumed endpoint in this app. External callers (currently: pyobs-portal, for its script-builder module dropdown) only ever see the one host they're configured against — modules on other hub clients are invisible, with no config knob on either side to fix it.

Found while investigating a "web-admin only shows modules on itself, not hub clients" question, which turned out to be user error about which page (Dashboard is single-active-host by design; Fleet Overview already aggregates) — but surfaced this separate, real gap.

Current state

Three hub-interaction patterns already coexist here:

  1. Single active-host, session-driven proxying (dashboard, module_detail, api_config, start/stop/restart). _active_host() (views.py:95) + _proxy() (views.py:99) forward to session["active_host"] via proxy.call() (modules/proxy.py:20-25). Fine for a human clicking around; useless for a caller with no session.
  2. Fleet-wide aggregating pages (fleet_overview, ACL Matrix, All Logs, Users). Loop over [localhost] + settings.HUB_HOSTS, call each host's own raw endpoint, merge server-side (services.merge_acl_matrices, services.py:2444, is the pattern to copy).
  3. Raw, always-local, hub-facing endpoints, meant to be queried by another instance doing pattern 2's merge (api_acl_matrix, api_module_classes, the comm-user-map endpoint). api_acl_matrix and the comm-user-map endpoint both have a pattern-2 page built on top of them (ACL Matrix, Users). api_module_classes does not — nothing in this app ever asks "what module classes exist across the whole fleet."

Confirmed live: our two-instance pair (south/monet acting as hub, south/frontend as client) already has matching HUB_HOSTS/HUB_TOKEN/HUB_CLIENTS secrets — the hub wiring itself isn't broken. Portal just has one WEBADMIN_URL and calls api_module_classes directly, so it only ever gets south/monet's own modules.

Proposed fix

  • Add services.merge_module_classes(per_host: list[tuple[str, dict]]), mirroring merge_acl_matrices, and either a new endpoint (GET /api/modules/classes/fleet/) or an opt-in query param (?fleet=1) on the existing one that loops [localhost] + HUB_HOSTS like fleet_overview does. Default behavior for existing callers stays local-only.
  • Decide collision handling (same module name, different class, on two hosts): error vs. last-host-wins-with-a-warning vs. namespaced by host. Check whether ACL Matrix/Users already made an equivalent call and follow precedent.
  • Update pyobs-portal (pyobs_portal/api/webadmin.py:28-59) to call the new fleet endpoint once it exists, pointed at the hub instance (south/monet) — confirm its existing "portal" HUB_CLIENTS token already authorizes the new endpoint (should be free, same middleware).

Open questions

Work plan

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions