mirror of
https://github.com/open-webui/terminals.git
synced 2026-11-05 01:37:21 +00:00
[PR #6] [CLOSED] feat: enable Terminals K8s Orchestrator policy management in Open WebUI #39
Labels
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
open-webui/terminals#39
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/open-webui/terminals/pull/6
Author: @james-westbrook
Created: 3/25/2026
Status: ❌ Closed
Base:
main← Head:feat-operator-ui-integration📝 Commits (1)
605338efeat: enable Terminals K8s Orchestrator policy management in Open WebUI📊 Changes
5 files changed (+168 additions, -0 deletions)
View changed files
📝
pyproject.toml(+3 -0)📝
terminals/backends/base.py(+26 -0)📝
terminals/backends/kubernetes_operator.py(+49 -0)📝
terminals/main.py(+2 -0)➕
terminals/routers/instances.py(+88 -0)📄 Description
Description
Summary
Adds three new API endpoints to the Terminals orchestrator that enable Open WebUI admins to manage terminal instances and inspect server configuration through the UI. This is the Terminals-side half of a two-PR effort. The companion Open WebUI PR adds the admin proxy routes and frontend UI that consume these endpoints.
Motivation
Why this is needed
The Kubernetes Operator backend (
kubernetes-operator) creates and manages Terminal CRDs, but until now there was no way for administrators to:These capabilities are prerequisites for the admin UI integration in Open WebUI, where admins need visibility into deployed terminals and the ability to act on them.
Why it lives in the Terminals service
Policy CRUD already exists in
terminals/routers/policy.py. Instance listing and server info are the natural complement — they let the admin see "what's configured" (policies) alongside "what's running" (instances) and "what's allowed" (server info / resource caps). Keeping these in the orchestrator means Open WebUI simply proxies to them, staying decoupled from Kubernetes details.Changes
New file:
terminals/routers/instances.py(+88 lines)Three new endpoints, all behind
verify_api_keyauthentication:/api/v1/instances/api/v1/instances/{instance_id}/api/v1/infoResponse schemas:
InstanceResponse—user_id,policy_id,instance_id,instance_name,status,host,port,image,cpu_limit,memory_limit,storage,idle_timeout_minutes,last_activity,created_at,messageInfoResponse—backend,version,max_cpu,max_memory,max_storage,allowed_images,idle_timeout_minutesModified:
terminals/backends/base.py(+26 lines)Added a default
list_instances()method to theBackendABC that returns instance info from the in-memory_instancestracking dict. This provides a working implementation for all backends (Docker, Local, Static) without requiring backend-specific overrides.Each returned dict includes:
user_id,policy_id,instance_id,instance_name,status,host,port. Status is fetched live viaself.status().Modified:
terminals/backends/kubernetes_operator.py(+49 lines)Overrides
list_instances()to query Kubernetes directly rather than relying on in-memory tracking. This is important because:The implementation:
list_namespaced_custom_object()with label selectorapp.kubernetes.io/managed-by=terminalsInstanceResponseschemauserId,image,cpuLimit,memoryLimit,storage,idleTimeoutMinutesfrom specphase,serviceName,lastActivityAt,messagefrom statusopenwebui.com/user-idandopenwebui.com/policyfrom labelsModified:
terminals/main.py(+2 lines)Registers the new
instances_routeralongside the existingpolicy_router, both before the catch-all proxy router.Modified:
pyproject.toml(+3 lines)Added
sqlalchemy[asyncio]>=2.0.0,aiosqlite>=0.20.0,alembic>=1.13.0to dependencies. These are required by the existing DB layer (terminals/db/session.py) but were previously missing from the declared dependencies.Design decisions
Why a default implementation on the base class?
The base
Backenduses in-memory_instancestracking (self._instancesdict populated by_track/_untrackcalls). Addinglist_instances()there means Docker, Local, and Static backends get instance listing for free. The Kubernetes Operator backend overrides it because CRDs are the authoritative source, and in-memory tracking is best-effort for that backend.Why
/api/v1/inforather than extending/health?/healthis unauthenticated (used by load balancers and readiness probes). Server info includes configuration details that should only be visible to authenticated administrators, so it lives behindverify_api_keyon a separate endpoint.Why does the teardown endpoint accept
instance_id(UID), not instance name?The backend
teardown()method already operates on instance IDs (Kubernetes UIDs for the operator backend). Using the UID avoids ambiguity if names are reused and aligns with the existingteardown()contract.Testing
Tested end-to-end on a local
kindcluster with the Kubernetes Operator backend:/api/v1/instancesreturns correct user_id, policy_id, status, and resource info for each.DELETE /api/v1/instances/{uid}, verified the Terminal CR was deleted and the instance disappeared from subsequent list calls./api/v1/inforeturns the correct backend type (kubernetes-operator), resource caps from environment variables, and version.Related PRs
The Open WebUI PR adds:
The associated PR can be found in Open WebUI here: https://github.com/open-webui/open-webui/pull/23011
Contributor License Agreement
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.