[GH-ISSUE #442] terminals: the chart's Terminal CRD is out of sync with the operator — spec.env, contextId, podTemplate, restricted and both securityContexts are silently pruned #139

Open
opened 2026-10-18 21:06:34 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @wa91h on GitHub (Sep 17, 2026).
Original GitHub issue: https://github.com/open-webui/helm-charts/issues/442

Chart: terminals 0.7.0 (also 0.5.0; main is identical) · Images: terminals-operator:0.2.4, terminals:0.2.4 · Cluster: k3s v1.36.4 (Kubernetes 1.36), Helm v4.2.4

What happens

charts/terminals/templates/crd.yaml declares spec with seven properties (userId, image, resources, idleTimeoutMinutes, packages, pipPackages, persistence) and has no x-kubernetes-preserve-unknown-fields. The operator/orchestrator it ships (0.2.4) write and read six more that exist in the upstream CRD (open-webui/terminals manifests/terminal-crd.yaml):

  • env — the orchestrator forwards its own OPEN_TERMINAL_SYSTEM_PROMPT (and any policy env) here (terminals/utils/env.py, backends/kubernetes_operator.py); the operator copies it into the pod
  • contextId
  • podTemplate
  • restricted
  • podSecurityContext, containerSecurityContext

Because the schema is structural and the fields are undeclared, the API server prunes them on admission with no error: the orchestrator's create succeeds, the CR simply never has them, and the operator sees nothing. Every feature behind those fields is a silent no-op for chart users — a configured terminal system prompt never reaches a terminal pod, restricted/securityContext hardening is dropped, etc.

Reproduce

helm install t open-webui/terminals --version 0.7.0 -n x --create-namespace
cat <<'Y' | kubectl apply --dry-run=server -f - -o jsonpath='{.spec}'
apiVersion: openwebui.com/v1alpha1
kind: Terminal
metadata: {name: probe, namespace: x}
spec:
  userId: probe
  contextId: "chat:probe"
  env: {OPEN_TERMINAL_SYSTEM_PROMPT: "probe"}
Y
# → {"idleTimeoutMinutes":30,"image":"...","packages":[],"pipPackages":[],"userId":"probe"}   — env and contextId gone

Swap in the upstream CRD and the same object keeps env and contextId.

Expected

templates/crd.yaml byte-equal to the operator release's manifests/terminal-crd.yaml (v0.2.4 today), or generated from it at chart-build time — plus a note in the chart's changelog when the CRD moves, since Helm upgrades a templated CRD but never a crds/ one.

Workaround we use

crd.install: false and apply the upstream manifest ourselves. Note for anyone doing the same on an existing install: Helm deletes the CRD it no longer renders, the CRD's cleanup finalizer waits on the CRs, the CRs carry kopf's finalizer, and a terminating CRD drops patch from discovery — kopf then logs Non-patchable resources will not be served and the deletion hangs until you drop the CR finalizers by hand and restart the operator.

Related: #427 (persistence only via a named policy, duplicate TERMINAL_SERVER_CONNECTIONS) — same install, same week.

Originally created by @wa91h on GitHub (Sep 17, 2026). Original GitHub issue: https://github.com/open-webui/helm-charts/issues/442 **Chart:** `terminals` 0.7.0 (also 0.5.0; `main` is identical) · **Images:** `terminals-operator:0.2.4`, `terminals:0.2.4` · **Cluster:** k3s v1.36.4 (Kubernetes 1.36), Helm v4.2.4 ## What happens `charts/terminals/templates/crd.yaml` declares `spec` with seven properties (`userId`, `image`, `resources`, `idleTimeoutMinutes`, `packages`, `pipPackages`, `persistence`) and has no `x-kubernetes-preserve-unknown-fields`. The operator/orchestrator it ships (0.2.4) write and read six more that exist in the upstream CRD (`open-webui/terminals` `manifests/terminal-crd.yaml`): - `env` — the orchestrator forwards its own `OPEN_TERMINAL_SYSTEM_PROMPT` (and any policy `env`) here (`terminals/utils/env.py`, `backends/kubernetes_operator.py`); the operator copies it into the pod - `contextId` - `podTemplate` - `restricted` - `podSecurityContext`, `containerSecurityContext` Because the schema is structural and the fields are undeclared, the API server **prunes them on admission with no error**: the orchestrator's create succeeds, the CR simply never has them, and the operator sees nothing. Every feature behind those fields is a silent no-op for chart users — a configured terminal system prompt never reaches a terminal pod, `restricted`/securityContext hardening is dropped, etc. ## Reproduce ```sh helm install t open-webui/terminals --version 0.7.0 -n x --create-namespace cat <<'Y' | kubectl apply --dry-run=server -f - -o jsonpath='{.spec}' apiVersion: openwebui.com/v1alpha1 kind: Terminal metadata: {name: probe, namespace: x} spec: userId: probe contextId: "chat:probe" env: {OPEN_TERMINAL_SYSTEM_PROMPT: "probe"} Y # → {"idleTimeoutMinutes":30,"image":"...","packages":[],"pipPackages":[],"userId":"probe"} — env and contextId gone ``` Swap in the upstream CRD and the same object keeps `env` and `contextId`. ## Expected `templates/crd.yaml` byte-equal to the operator release's `manifests/terminal-crd.yaml` (v0.2.4 today), or generated from it at chart-build time — plus a note in the chart's changelog when the CRD moves, since Helm upgrades a templated CRD but never a `crds/` one. ## Workaround we use `crd.install: false` and apply the upstream manifest ourselves. Note for anyone doing the same on an existing install: Helm deletes the CRD it no longer renders, the CRD's cleanup finalizer waits on the CRs, the CRs carry kopf's finalizer, and a terminating CRD drops `patch` from discovery — kopf then logs `Non-patchable resources will not be served` and the deletion hangs until you drop the CR finalizers by hand and restart the operator. Related: #427 (persistence only via a named policy, duplicate `TERMINAL_SERVER_CONNECTIONS`) — same install, same week.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
open-webui/helm-charts#139
No description provided.